【Android、IOS、Flutter、鸿蒙、ReactNative 】列表布局

122 阅读10分钟

Android Java RecyclerView

配置依赖

implementation ("androidx.recyclerview:recyclerview:1.1.0")

创建适配器ItemAdapter 参考Android Developer

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.recyclerview.widget.RecyclerView;

import com.java.bean.ItemBean;
import com.java.recyclerview.R;

import java.util.List;

public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ViewHolder> {

    private List<ItemBean> itemBeanList;//数据源
    private OnItemClickListener myClickListener;
    private View mPreClickView;

    public ItemAdapter(List<ItemBean> itemBeanList) {
        this.itemBeanList = itemBeanList;
    }


    //静态内部类, 每个条目对应的布局
    static class ViewHolder extends RecyclerView.ViewHolder {
        AppCompatImageView imageView;
        AppCompatTextView tvTitle;
        AppCompatTextView tvContent;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.imageView);
            tvTitle = itemView.findViewById(R.id.tvTitle);
            tvContent = itemView.findViewById(R.id.tvContent);
        }
    }

    //用于创建ViewHolder实例,并把加载的布局传入到ViewHolder的构造函数去
    @NonNull
    @Override
    public ItemAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item_one, parent, false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        ItemBean itemBean = itemBeanList.get(position);
        holder.imageView.setImageResource(itemBean.getDrawableId());
        holder.tvTitle.setText(itemBean.getTitle());
        holder.tvContent.setText(itemBean.getContent());

        // 设置每一项点击事件
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(myClickListener!=null){
                    myClickListener.OnClick(position);
                }
                if(mPreClickView!=null){
                    mPreClickView.setBackgroundResource(R.color.white);
                }
                view.setBackgroundResource(R.color.purple_200);
                mPreClickView=view;
            }
        });
    }

    @Override
    public int getItemCount() {
        return (itemBeanList ==null ? 0 : itemBeanList.size());
    }

    public void setOnItemClickListener(OnItemClickListener myClickListener) {
        this.myClickListener = myClickListener;
    }

   public interface OnItemClickListener{
        void OnClick(int position);
    }

}

为列表绑定数据

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;
import android.widget.Toast;

import com.java.adapter.ItemAdapter;
import com.java.bean.ItemBean;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private List<ItemBean> itemBeanList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initAdapter();
    }

    private void initAdapter() {
        RecyclerView recyclerView = findViewById(R.id.recyclerView);
        // 设置布局垂直方向
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(layoutManager);
        // 设置分割线
        DividerItemDecoration decoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);
        recyclerView.addItemDecoration(decoration);
        // 为适配器绑定数据
        initItemBeanList();
        ItemAdapter itemAdapter = new ItemAdapter(itemBeanList);
        // 为列表设置适配器
        recyclerView.setAdapter(itemAdapter);
        itemAdapter.setOnItemClickListener(new ItemAdapter.OnItemClickListener() {
            @Override
            public void OnClick(int position) {
                Toast.makeText(getBaseContext(),"当前列表点击项"+position,Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void initItemBeanList() {
        itemBeanList.add(new ItemBean(R.drawable.icon_1, "列表标题1", "列表内容1/列表内容1/列表内容1/"));
        itemBeanList.add(new ItemBean(R.drawable.icon_2, "列表标题2", "列表内容2/列表内容2/列表内容2/"));
        itemBeanList.add(new ItemBean(R.drawable.icon_3, "列表标题3", "列表内容3/列表内容3/列表内容3/"));
        itemBeanList.add(new ItemBean(R.drawable.icon_4, "列表标题4", "列表内容4/列表内容4/列表内容4/"));
        itemBeanList.add(new ItemBean(R.drawable.icon_5, "列表标题5", "列表内容5/列表内容5/列表内容5/"));
        itemBeanList.add(new ItemBean(R.drawable.icon_6, "列表标题6", "列表内容6/列表内容6/列表内容6/"));
        itemBeanList.add(new ItemBean(R.drawable.icon_7, "列表标题7", "列表内容7/列表内容7/列表内容7/"));
        itemBeanList.add(new ItemBean(R.drawable.icon_8, "列表标题8", "列表内容8/列表内容8/列表内容8/"));
        itemBeanList.add(new ItemBean(R.drawable.icon_9, "列表标题9", "列表内容9/列表内容9/列表内容9/"));
    }
}

预览视图

创建适配器ItemViewTypeAdapter

在列表中展现不同类型的布局。

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.recyclerview.widget.RecyclerView;

import com.java.bean.ItemBean;
import com.java.recyclerview.R;

import java.util.List;

public class ItemViewTypeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private List<ItemBean> itemBeanList;//数据源
    private OnItemClickListener myClickListener;
    private View mPreClickView;

    public ItemViewTypeAdapter(List<ItemBean> itemBeanList) {
        this.itemBeanList = itemBeanList;
    }


    //静态内部类, 每个条目对应的布局
    static class ViewHolderOne extends RecyclerView.ViewHolder {
        AppCompatImageView imageView;
        AppCompatTextView tvTitle;
        AppCompatTextView tvContent;

        public ViewHolderOne(@NonNull View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.imageView);
            tvTitle = itemView.findViewById(R.id.tvTitle);
            tvContent = itemView.findViewById(R.id.tvContent);
        }
    }

    //静态内部类, 每个条目对应的布局
    static class ViewHolderTwo extends RecyclerView.ViewHolder {
        AppCompatImageView imageViewL;
        AppCompatImageView imageViewM;
        AppCompatImageView imageViewR;

        public ViewHolderTwo(@NonNull View itemView) {
            super(itemView);
            imageViewL = itemView.findViewById(R.id.imageViewL);
            imageViewM = itemView.findViewById(R.id.imageViewM);
            imageViewR = itemView.findViewById(R.id.imageViewR);
        }
    }

    //静态内部类, 每个条目对应的布局
    static class ViewHolderThree extends RecyclerView.ViewHolder {
        AppCompatImageView imageViewL;
        AppCompatTextView tvTitle;
        AppCompatTextView tvContent;
        AppCompatImageView imageViewR;

        public ViewHolderThree(@NonNull View itemView) {
            super(itemView);
            imageViewL = itemView.findViewById(R.id.imageViewL);
            tvTitle = itemView.findViewById(R.id.tvTitle);
            tvContent = itemView.findViewById(R.id.tvContent);
            imageViewR = itemView.findViewById(R.id.imageViewR);
        }
    }


    //用于创建ViewHolder实例,并把加载的布局传入到ViewHolder的构造函数去
    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if (viewType == ViewType.VIEW_TYPE_ONE.getValue()) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item_one, parent, false);
            ViewHolderOne holder = new ViewHolderOne(view);
            return holder;
        } else if (viewType == ViewType.VIEW_TYPE_TWO.getValue()) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item_two, parent, false);
            ViewHolderTwo holder = new ViewHolderTwo(view);
            return holder;
        } else {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item_three, parent, false);
            ViewHolderThree holder = new ViewHolderThree(view);
            return holder;
        }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        if (getItemViewType(position) == ViewType.VIEW_TYPE_ONE.getValue()) {
            ViewHolderOne viewHolderOne=(ViewHolderOne) holder;
            ItemBean itemBean = itemBeanList.get(position);
            viewHolderOne.imageView.setImageResource(itemBean.getDrawableId());
            viewHolderOne.tvTitle.setText(itemBean.getTitle());
            viewHolderOne.tvContent.setText(itemBean.getContent());
        } else if (getItemViewType(position) == ViewType.VIEW_TYPE_TWO.getValue()) {
            ViewHolderTwo viewHolderTwo=(ViewHolderTwo) holder;
            ItemBean itemBean = itemBeanList.get(position);
            viewHolderTwo.imageViewL.setImageResource(itemBean.getDrawableId());
            viewHolderTwo.imageViewM.setImageResource(itemBean.getDrawableId());
            viewHolderTwo.imageViewR.setImageResource(itemBean.getDrawableId());
        } else {
            ViewHolderThree viewHolderThree=(ViewHolderThree) holder;
            ItemBean itemBean = itemBeanList.get(position);
            viewHolderThree.imageViewL.setImageResource(itemBean.getDrawableId());
            viewHolderThree.tvTitle.setText(itemBean.getTitle());
            viewHolderThree.tvContent.setText(itemBean.getContent());
            viewHolderThree.imageViewR.setImageResource(itemBean.getDrawableId());
        }

        // 设置每一项点击事件
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(myClickListener!=null){
                    myClickListener.OnClick(position);
                }
                if(mPreClickView!=null){
                    mPreClickView.setBackgroundResource(R.color.white);
                }
                view.setBackgroundResource(R.color.purple_200);
                mPreClickView=view;
            }
        });
    }

    @Override
    public int getItemCount() {
        return (itemBeanList == null ? 0 : itemBeanList.size());
    }

    @Override
    public int getItemViewType(int position) {
        // 返回不同类型的布局
        int position3 = (position % 3);
        return position3;
    }

    public void setOnItemClickListener(OnItemClickListener myClickListener) {
        this.myClickListener = myClickListener;
    }

    public interface OnItemClickListener {
        void OnClick(int position);
    }

    public enum ViewType {
        VIEW_TYPE_ONE(0), VIEW_TYPE_TWO(1), VIEW_TYPE_THREE(2);

        private final int value;

        ViewType(int value) {
            this.value = value;
        }

        public int getValue() {
            return value;
        }
    }

}

为列表绑定数据

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;
import android.widget.Toast;

import com.java.adapter.ItemAdapter;
import com.java.bean.ItemBean;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private List<ItemBean> itemBeanList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initAdapter();
    }

    private void initAdapter() {
        RecyclerView recyclerView = findViewById(R.id.recyclerView);
        // 设置布局垂直方向
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(layoutManager);
        // 设置分割线
        DividerItemDecoration decoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);
        recyclerView.addItemDecoration(decoration);
        // 为适配器绑定数据
        initItemBeanList();
        ItemAdapter itemAdapter = new ItemAdapter(itemBeanList);
        // 为列表设置适配器
        recyclerView.setAdapter(itemAdapter);
        itemAdapter.setOnItemClickListener(new ItemAdapter.OnItemClickListener() {
            @Override
            public void OnClick(int position) {
                Toast.makeText(getBaseContext(),"当前列表点击项"+position,Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void initItemBeanList() {
        itemBeanList.add(new ItemBean(R.drawable.icon_1, "列表标题1", "列表内容1/列表内容1/列表内容1/"));
        itemBeanList.add(new ItemBean(R.drawable.icon_2, "列表标题2", "列表内容2/列表内容2/列表内容2/"));
        itemBeanList.add(new ItemBean(R.drawable.icon_3, "列表标题3", "列表内容3/列表内容3/列表内容3/"));
        itemBeanList.add(new ItemBean(R.drawable.icon_4, "列表标题4", "列表内容4/列表内容4/列表内容4/"));
        itemBeanList.add(new ItemBean(R.drawable.icon_5, "列表标题5", "列表内容5/列表内容5/列表内容5/"));
        itemBeanList.add(new ItemBean(R.drawable.icon_6, "列表标题6", "列表内容6/列表内容6/列表内容6/"));
        itemBeanList.add(new ItemBean(R.drawable.icon_7, "列表标题7", "列表内容7/列表内容7/列表内容7/"));
        itemBeanList.add(new ItemBean(R.drawable.icon_8, "列表标题8", "列表内容8/列表内容8/列表内容8/"));
        itemBeanList.add(new ItemBean(R.drawable.icon_9, "列表标题9", "列表内容9/列表内容9/列表内容9/"));
    }
}

预览视图

Android Kotlin RecyclerView

配置依赖

implementation ("androidx.recyclerview:recyclerview:1.1.0")

创建适配器ItemAdapter

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView
import androidx.recyclerview.widget.RecyclerView
import com.kotlin.bean.ItemBean
import com.kotlin.recyclerview.R


 class ItemAdapter(itemBeanList: List<ItemBean>?) :
    RecyclerView.Adapter<ItemAdapter.ViewHolder>() {
    private val itemBeanList //数据源
            : List<ItemBean>?
    private var myClickListener: OnItemClickListener? = null
    private var mPreClickView: View? = null

    init {
        this.itemBeanList = itemBeanList
    }

    //静态内部类, 每个条目对应的布局
    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var imageView: AppCompatImageView
        var tvTitle: AppCompatTextView
        var tvContent: AppCompatTextView

        init {
            imageView = itemView.findViewById(R.id.imageView)
            tvTitle = itemView.findViewById(R.id.tvTitle)
            tvContent = itemView.findViewById(R.id.tvContent)
        }
    }

    //用于创建ViewHolder实例,并把加载的布局传入到ViewHolder的构造函数去
    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): ViewHolder {
        val view: View = LayoutInflater.from(parent.context)
            .inflate(R.layout.recyclerview_item_one, parent, false)
        return ViewHolder(view)
    }


    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val itemBean: ItemBean = itemBeanList!![position]
        holder.imageView.setImageResource(itemBean.drawableId)
        holder.tvTitle.text = itemBean.title
        holder.tvContent.text = itemBean.content

        // 设置每一项点击事件
        holder.itemView.setOnClickListener { view ->
            if (myClickListener != null) {
                myClickListener!!.OnClick(position)
            }
            if (mPreClickView != null) {
                mPreClickView!!.setBackgroundResource(R.color.white)
            }
            view.setBackgroundResource(R.color.purple_200)
            mPreClickView = view
        }
    }

    override fun getItemCount(): Int {
        return itemBeanList?.size ?: 0
    }

    fun setOnItemClickListener(myClickListener: OnItemClickListener?) {
        this.myClickListener = myClickListener
    }

    interface OnItemClickListener {
        fun OnClick(position: Int)
    }
}

为列表绑定数据

import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.kotlin.adapter.ItemAdapter
import com.kotlin.bean.ItemBean

class MainActivity : AppCompatActivity() {
    private val itemBeanList: MutableList<ItemBean> = ArrayList()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initAdapter();
    }

    private fun initAdapter() {
        val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
        // 设置布局垂直方向
        val layoutManager = LinearLayoutManager(this)
        layoutManager.orientation = LinearLayoutManager.VERTICAL
        recyclerView.layoutManager = layoutManager
        // 设置分割线
        val decoration = DividerItemDecoration(this, DividerItemDecoration.VERTICAL)
        recyclerView.addItemDecoration(decoration)
        // 为适配器绑定数据
        initItemBeanList()
        val itemAdapter = ItemAdapter(itemBeanList)
        // 为列表设置适配器
        recyclerView.adapter = itemAdapter
        itemAdapter.setOnItemClickListener(object : ItemAdapter.OnItemClickListener {
            override fun OnClick(position: Int) {
                Toast.makeText(baseContext, "当前列表点击项$position", Toast.LENGTH_SHORT).show()
            }
        })
    }

    private fun initItemBeanList() {
        itemBeanList.add(ItemBean(R.drawable.icon_1, "列表标题1", "列表内容1/列表内容1/列表内容1/"))
        itemBeanList.add(ItemBean(R.drawable.icon_2, "列表标题2", "列表内容2/列表内容2/列表内容2/"))
        itemBeanList.add(ItemBean(R.drawable.icon_3, "列表标题3", "列表内容3/列表内容3/列表内容3/"))
        itemBeanList.add(ItemBean(R.drawable.icon_4, "列表标题4", "列表内容4/列表内容4/列表内容4/"))
        itemBeanList.add(ItemBean(R.drawable.icon_5, "列表标题5", "列表内容5/列表内容5/列表内容5/"))
        itemBeanList.add(ItemBean(R.drawable.icon_6, "列表标题6", "列表内容6/列表内容6/列表内容6/"))
        itemBeanList.add(ItemBean(R.drawable.icon_7, "列表标题7", "列表内容7/列表内容7/列表内容7/"))
        itemBeanList.add(ItemBean(R.drawable.icon_8, "列表标题8", "列表内容8/列表内容8/列表内容8/"))
        itemBeanList.add(ItemBean(R.drawable.icon_9, "列表标题9", "列表内容9/列表内容9/列表内容9/"))

    }
}

预览视图

创建适配器ItemViewTypeAdapter

在列表中展现不同类型的布局。

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView
import androidx.recyclerview.widget.RecyclerView
import com.kotlin.bean.ItemBean
import com.kotlin.recyclerview.R


class ItemViewTypeAdapter(itemBeanList: List<ItemBean>?) :
    RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    private val itemBeanList //数据源
            : List<ItemBean>?
    private var myClickListener: OnItemClickListener? = null
    private var mPreClickView: View? = null

    init {
        this.itemBeanList = itemBeanList
    }

    //静态内部类, 每个条目对应的布局
    internal class ViewHolderOne(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var imageView: AppCompatImageView
        var tvTitle: AppCompatTextView
        var tvContent: AppCompatTextView

        init {
            imageView = itemView.findViewById<AppCompatImageView>(R.id.imageView)
            tvTitle = itemView.findViewById<AppCompatTextView>(R.id.tvTitle)
            tvContent = itemView.findViewById<AppCompatTextView>(R.id.tvContent)
        }
    }

    //静态内部类, 每个条目对应的布局
    internal class ViewHolderTwo(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var imageViewL: AppCompatImageView
        var imageViewM: AppCompatImageView
        var imageViewR: AppCompatImageView

        init {
            imageViewL = itemView.findViewById<AppCompatImageView>(R.id.imageViewL)
            imageViewM = itemView.findViewById<AppCompatImageView>(R.id.imageViewM)
            imageViewR = itemView.findViewById<AppCompatImageView>(R.id.imageViewR)
        }
    }

    //静态内部类, 每个条目对应的布局
    internal class ViewHolderThree(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var imageViewL: AppCompatImageView
        var tvTitle: AppCompatTextView
        var tvContent: AppCompatTextView
        var imageViewR: AppCompatImageView

        init {
            imageViewL = itemView.findViewById<AppCompatImageView>(R.id.imageViewL)
            tvTitle = itemView.findViewById<AppCompatTextView>(R.id.tvTitle)
            tvContent = itemView.findViewById<AppCompatTextView>(R.id.tvContent)
            imageViewR = itemView.findViewById<AppCompatImageView>(R.id.imageViewR)
        }
    }

    //用于创建ViewHolder实例,并把加载的布局传入到ViewHolder的构造函数去
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return if (viewType == ViewType.VIEW_TYPE_ONE.value) {
            val view: View = LayoutInflater.from(parent.context)
                .inflate(R.layout.recyclerview_item_one, parent, false)
            ViewHolderOne(view)
        } else if (viewType == ViewType.VIEW_TYPE_TWO.value) {
            val view: View = LayoutInflater.from(parent.context)
                .inflate(R.layout.recyclerview_item_two, parent, false)
            ViewHolderTwo(view)
        } else {
            val view: View = LayoutInflater.from(parent.context)
                .inflate(R.layout.recyclerview_item_three, parent, false)
            ViewHolderThree(view)
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        if (getItemViewType(position) == ViewType.VIEW_TYPE_ONE.value) {
            val viewHolderOne = holder as ViewHolderOne
            val itemBean: ItemBean = itemBeanList!![position]
            viewHolderOne.imageView.setImageResource(itemBean.drawableId)
            viewHolderOne.tvTitle.setText(itemBean.title)
            viewHolderOne.tvContent.setText(itemBean.content)
        } else if (getItemViewType(position) == ViewType.VIEW_TYPE_TWO.value) {
            val viewHolderTwo = holder as ViewHolderTwo
            val itemBean: ItemBean = itemBeanList!![position]
            viewHolderTwo.imageViewL.setImageResource(itemBean.drawableId)
            viewHolderTwo.imageViewM.setImageResource(itemBean.drawableId)
            viewHolderTwo.imageViewR.setImageResource(itemBean.drawableId)
        } else {
            val viewHolderThree = holder as ViewHolderThree
            val itemBean: ItemBean = itemBeanList!![position]
            viewHolderThree.imageViewL.setImageResource(itemBean.drawableId)
            viewHolderThree.tvTitle.setText(itemBean.title)
            viewHolderThree.tvContent.setText(itemBean.content)
            viewHolderThree.imageViewR.setImageResource(itemBean.drawableId)
        }

        // 设置每一项点击事件
        holder.itemView.setOnClickListener { view ->
            if (myClickListener != null) {
                myClickListener!!.OnClick(position)
            }
            if (mPreClickView != null) {
                mPreClickView!!.setBackgroundResource(R.color.white)
            }
            view.setBackgroundResource(R.color.purple_200)
            mPreClickView = view
        }
    }

    override fun getItemCount(): Int {
        return itemBeanList?.size ?: 0
    }

    override fun getItemViewType(position: Int): Int {
        // 返回不同类型的布局
        return position % 3
    }

    fun setOnItemClickListener(myClickListener: OnItemClickListener?) {
        this.myClickListener = myClickListener
    }

    interface OnItemClickListener {
        fun OnClick(position: Int)
    }

    enum class ViewType(val value: Int) {
        VIEW_TYPE_ONE(0), VIEW_TYPE_TWO(1), VIEW_TYPE_THREE(2)

    }
}

为列表绑定数据

import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.kotlin.adapter.ItemViewTypeAdapter
import com.kotlin.bean.ItemBean


class MainViewTypeActivity : AppCompatActivity() {
    private val itemBeanList: MutableList<ItemBean> = ArrayList()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initAdapter()
    }

    private fun initAdapter() {
        val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
        // 设置布局垂直方向
        val layoutManager = LinearLayoutManager(this)
        layoutManager.orientation = LinearLayoutManager.VERTICAL
        recyclerView.layoutManager = layoutManager
        // 设置分割线
        val decoration = DividerItemDecoration(this, DividerItemDecoration.VERTICAL)
        recyclerView.addItemDecoration(decoration)
        // 为适配器绑定数据
        initItemBeanList()
        val itemAdapter = ItemViewTypeAdapter(itemBeanList)
        // 为列表设置适配器
        recyclerView.adapter = itemAdapter
        itemAdapter.setOnItemClickListener(object : ItemViewTypeAdapter.OnItemClickListener {
            override fun OnClick(position: Int) {
                Toast.makeText(baseContext, "当前列表点击项$position", Toast.LENGTH_SHORT).show()
            }
        })
    }

    private fun initItemBeanList() {
        itemBeanList.add(ItemBean(R.drawable.icon_1, "列表标题1", "列表内容1/列表内容1/列表内容1/"))
        itemBeanList.add(ItemBean(R.drawable.icon_2, "列表标题2", "列表内容2/列表内容2/列表内容2/"))
        itemBeanList.add(ItemBean(R.drawable.icon_3, "列表标题3", "列表内容3/列表内容3/列表内容3/"))
        itemBeanList.add(ItemBean(R.drawable.icon_4, "列表标题4", "列表内容4/列表内容4/列表内容4/"))
        itemBeanList.add(ItemBean(R.drawable.icon_5, "列表标题5", "列表内容5/列表内容5/列表内容5/"))
        itemBeanList.add(ItemBean(R.drawable.icon_6, "列表标题6", "列表内容6/列表内容6/列表内容6/"))
        itemBeanList.add(ItemBean(R.drawable.icon_7, "列表标题7", "列表内容7/列表内容7/列表内容7/"))
        itemBeanList.add(ItemBean(R.drawable.icon_8, "列表标题8", "列表内容8/列表内容8/列表内容8/"))
        itemBeanList.add(ItemBean(R.drawable.icon_9, "列表标题9", "列表内容9/列表内容9/列表内容9/"))
    }
}

预览视图

Android Compose 列表布局参考 Android Developers

列表实现参考

预览效果

Android Compose 实现列表布局

列表一种样式布局

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Card
import androidx.compose.material3.Divider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.TextUnitType
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.compose.lazycolumn.model.Affirmation
import com.compose.lazycolumn.ui.theme.AndroidComposeLazyColumnTheme
import com.example.affirmations.data.Datasource

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            AndroidComposeLazyColumnTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    AffirmationsApp()
                }
            }
        }
    }
}

@Composable
fun AffirmationsApp() {
    AffirmationList(
        affirmationList = Datasource().loadAffirmations(),
    )
}

@Composable
fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
    LazyColumn(modifier = modifier) {
        items(affirmationList) { affirmation ->
            AffirmationCard(
                affirmation = affirmation,
                modifier = Modifier.padding(8.dp)
            )
            // 这里是最后一个项目的下方添加一个额外的分割线
            Spacer(
                modifier = Modifier
                    .height(1.dp)
                    .background(Color.Red)
            )
            Divider()
        }
    }
}

@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
    Card(modifier = modifier) {
        Row(
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.Center,
            modifier = Modifier.padding(top = 10.dp, bottom = 10.dp)
        ) {
            Image(
                painter = painterResource(affirmation.imageResourceId),
                contentDescription = stringResource(affirmation.titleResourceId),
                modifier = Modifier
                    .width(60.dp)
                    .height(60.dp),
                contentScale = ContentScale.Crop
            )
            Box(modifier = Modifier.weight(1.0f)) {
                Column {
                    Text(
                        text = LocalContext.current.getString(affirmation.titleResourceId),
                        fontSize = 16.sp,
                    )
                    Text(
                        text = LocalContext.current.getString(affirmation.contentResourceId),
                        fontSize = 14.sp,
                        lineHeight = TextUnit(value = 16.0f, type = TextUnitType.Sp)
                    )
                }
            }
            Image(
                painter = painterResource(affirmation.imageResourceId),
                contentDescription = stringResource(affirmation.titleResourceId),
                modifier = Modifier
                    .width(60.dp)
                    .height(60.dp),
                contentScale = ContentScale.Crop
            )
        }
    }
}

预览列表样式

列表多种样式布局

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Card
import androidx.compose.material3.Divider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.TextUnitType
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.compose.lazycolumn.ui.theme.AndroidComposeLazyColumnTheme
import com.example.affirmations.data.Datasource
import com.compose.lazycolumn.model.Affirmation

enum class Type(val value: Int) {
    TYPE_ONE(0),
    TYPE_TWO(1),
    TYPE_THREE(2)
}

class MainViewTypeActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            AndroidComposeLazyColumnTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    AffirmationsApp1()
                }
            }
        }
    }
}

@Composable
fun AffirmationsApp1() {
    AffirmationList1(
        affirmationList = Datasource().loadAffirmations(),
    )
}

@Composable
fun AffirmationList1(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
    LazyColumn(modifier = modifier) {
        items(affirmationList) { affirmation ->
            val index = affirmationList.indexOf(affirmation);
            when (index % 3) {
                Type.TYPE_ONE.value -> {
                    AffirmationCardOne(
                        affirmation = affirmation,
                        modifier = Modifier.padding(8.dp)
                    )
                }

                Type.TYPE_TWO.value -> {
                    AffirmationCardTwo(
                        affirmation = affirmation,
                        modifier = Modifier.padding(8.dp)
                    )
                }

                Type.TYPE_THREE.value -> {
                    AffirmationCardThree(
                        affirmation = affirmation,
                        modifier = Modifier.padding(8.dp)
                    )
                }
            }
            // 这里是最后一个项目的下方添加一个额外的分割线
            Spacer(
                modifier = Modifier
                    .height(1.dp)
                    .background(Color.Red)
            )
            Divider()
        }
    }
}

@Composable
fun AffirmationCardOne(affirmation: Affirmation, modifier: Modifier = Modifier) {
    Card(modifier = modifier) {
        Row(
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.Center,
            modifier = Modifier.padding(top = 10.dp, bottom = 10.dp)
        ) {
            Image(
                painter = painterResource(affirmation.imageResourceId),
                contentDescription = stringResource(affirmation.titleResourceId),
                modifier = Modifier
                    .width(60.dp)
                    .height(60.dp),
                contentScale = ContentScale.Crop
            )
            Box(modifier = Modifier.weight(1.0f)) {
                Column {
                    Text(
                        text = LocalContext.current.getString(affirmation.titleResourceId),
                        fontSize = 16.sp,
                    )
                    Text(
                        text = LocalContext.current.getString(affirmation.contentResourceId),
                        fontSize = 14.sp,
                        lineHeight = TextUnit(value = 16.0f, type = TextUnitType.Sp)
                    )
                }
            }
            Image(
                painter = painterResource(affirmation.imageResourceId),
                contentDescription = stringResource(affirmation.titleResourceId),
                modifier = Modifier
                    .width(60.dp)
                    .height(60.dp),
                contentScale = ContentScale.Crop
            )
        }
    }
}

@Composable
fun AffirmationCardTwo(affirmation: Affirmation, modifier: Modifier = Modifier) {
    Card(modifier = modifier) {
        Row(
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.Center,
            modifier = Modifier.padding(top = 10.dp, bottom = 10.dp)
        ) {
            Image(
                painter = painterResource(affirmation.imageResourceId),
                contentDescription = stringResource(affirmation.titleResourceId),
                modifier = Modifier
                    .width(60.dp)
                    .height(60.dp),
                contentScale = ContentScale.Crop
            )
            Box(modifier = Modifier.weight(1.0f), contentAlignment = Alignment.Center) {
                Image(
                    painter = painterResource(affirmation.imageResourceId),
                    contentDescription = stringResource(affirmation.titleResourceId),
                    modifier = Modifier
                        .width(60.dp)
                        .height(60.dp),
                    contentScale = ContentScale.Crop
                )
            }
            Image(
                painter = painterResource(affirmation.imageResourceId),
                contentDescription = stringResource(affirmation.titleResourceId),
                modifier = Modifier
                    .width(60.dp)
                    .height(60.dp),
                contentScale = ContentScale.Crop
            )
        }
    }
}

@Composable
fun AffirmationCardThree(affirmation: Affirmation, modifier: Modifier = Modifier) {
    Card(modifier = modifier) {
        Row(
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.Center,
            modifier = Modifier.padding(top = 10.dp, bottom = 10.dp, end = 10.dp)
        ) {
            Image(
                painter = painterResource(affirmation.imageResourceId),
                contentDescription = stringResource(affirmation.titleResourceId),
                modifier = Modifier
                    .width(60.dp)
                    .height(60.dp),
                contentScale = ContentScale.Crop
            )
            Box(modifier = Modifier.weight(1.0f)) {
                Column {
                    Text(
                        text = LocalContext.current.getString(affirmation.titleResourceId),
                        fontSize = 16.sp,
                    )
                    Text(
                        text = LocalContext.current.getString(affirmation.contentResourceId),
                        fontSize = 14.sp,
                        lineHeight = TextUnit(value = 16.0f, type = TextUnitType.Sp)
                    )
                }
            }
        }
    }
}

预览列表样式

IOS Object-c UITableView 列表布局

使用UITableView创建列表

实现代理、数据源代理

image.png

初始化UITableView

image.png

UITableViewCell显示内容

image.png

预览效果

IOS Object-c UITableView 自定义Cell

使用UITableView自定义Cell创建列表

实现代理、数据源代理 image.png

自定义CustomTableViewOneCell

image.png

image.png

自定义CustomTableViewTwoCell

image.png

image.png

初始化UITableView

image.png

自定义Cell显示内容

image.png

预览效果

IOS Object-c UICollectionView 列表布局

参考简书

预览布局

IOS Swift UITableView 列表布局

Object-c转Swift

使用UITableView创建列表

实现代理、数据源代理

image.png

初始化UITableView

image.png

UITableViewCell显示内容

image.png

预览效果

IOS Swift UITableView 自定义Cell

使用UITableView自定义Cell创建列表

实现代理、数据源代理

image.png

自定义CustomTableViewOneCell

image.png

自定义CustomTableViewTwoCell

image.png

初始化UITableView

image.png

自定义Cell显示内容

image.png

预览效果

Flutter 列表布局

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: ListView.builder(
          itemCount: 20,
          itemExtent: 50.0, //强制高度为50.0
          itemBuilder: (BuildContext context, int index) {
            int indexRemainder = (index % 3);
            switch (indexRemainder) {
              case 0:
                return _listViewOne(index);
              case 1:
                return _listViewTwo(index);
              case 2:
                return _listViewThree(index);
              default:
                break;
            }
          }),
    );
  }

  Widget _listViewOne(index) {
    return Container(
      color: Colors.black.withOpacity(0.1),
      child: Row(
        children: [
          Image.asset(
            'assets/icon_1.png',
            width: 60.0,
            height: 60.0,
          ),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [Text("标题$index"), Text("内容$index")],
            ),
          ),
          Image.asset(
            'assets/icon_2.png',
            width: 60.0,
            height: 60.0,
          ),
        ],
      ),
    );
  }

  Widget _listViewTwo(index) {
    return Container(
        color: Colors.black.withOpacity(0.2),
        child: Row(
          children: [
            Image.asset(
              'assets/icon_3.png',
              width: 60.0,
              height: 60.0,
            ),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [Text("标题$index"), Text("内容$index")],
              ),
            ),
            Image.asset(
              'assets/icon_4.png',
              width: 60.0,
              height: 60.0,
            ),
          ],
        ));
  }

  Widget _listViewThree(index) {
    return Container(
        color: Colors.black.withOpacity(0.3),
        child: Row(
          children: [
            Image.asset(
              'assets/icon_3.png',
              width: 60.0,
              height: 60.0,
            ),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [Text("标题$index"), Text("内容$index")],
              ),
            ),
            Image.asset(
              'assets/icon_4.png',
              width: 60.0,
              height: 60.0,
            ),
          ],
        ));
  }
}

预览布局

鸿蒙 列表布局

创建ListBean 对象

@Observed
export default class ListBean {
  public title: string = '';
  public content: string = '';
  public pic: Resource;
  public type: number;

  constructor(title: string, content: string, pic: Resource,type:number) {
    this.title = title;
    this.content = content;
    this.pic = pic;
    this.type=type;
  }
}

使用 List组件 创建列表布局

import ListBean from '../bean/ListBean'

@Entry
@Component
struct Index {
  @State message: string = 'Hello World'
  @State listBeans: Array<ListBean> = new Array

  aboutToAppear() {
    let lisBean1: ListBean = new ListBean("标题one", "内容one", $r("app.media.icon_1"), 0)
    let lisBean2: ListBean = new ListBean("标题two", "内容two", $r("app.media.icon_2"), 1)
    let lisBean3: ListBean = new ListBean("标题three", "内容three", $r("app.media.icon_3"), 2)
    let lisBean4: ListBean = new ListBean("标题Four", "内容Four", $r("app.media.icon_4"), 0)
    let lisBean5: ListBean = new ListBean("标题Five", "内容Five", $r("app.media.icon_5"), 1)
    let lisBean6: ListBean = new ListBean("标题Six", "内容Six", $r("app.media.icon_6"), 2)
    let lisBean7: ListBean = new ListBean("标题Seven", "内容Seven", $r("app.media.icon_7"), 0)
    let lisBean8: ListBean = new ListBean("标题Eight", "内容Eight", $r("app.media.icon_8"), 1)
    let lisBean9: ListBean = new ListBean("标题Nine", "内容Nine", $r("app.media.icon_9"), 2)
    this.listBeans.push(lisBean1)
    this.listBeans.push(lisBean2)
    this.listBeans.push(lisBean3)
    this.listBeans.push(lisBean4)
    this.listBeans.push(lisBean5)
    this.listBeans.push(lisBean6)
    this.listBeans.push(lisBean7)
    this.listBeans.push(lisBean8)
    this.listBeans.push(lisBean9)
    console.log(this.listBeans.length.toString());
  }

  build() {
    List({ space: 10 }) {
      ForEach(this.listBeans, (item: ListBean) => {
        ListItem() {
          this.listItem(item)
        }
      })
    }
    .padding(12)
    .height('100%')
    .backgroundColor(0xF1F3F5)
  }

  @Builder listItem(item: ListBean) {
    if (item.type == 0) {
      Row() {
        Image(item.pic).width(70.0).height(70.0)
        Stack() {
          Image(item.pic).width(70.0).height(70.0)
        }.layoutWeight(1.0).align(Alignment.Center)

        Image(item.pic).width(70.0).height(70.0)
      }
      .width('100%')
      .height(70.0)
      .borderRadius(10)
      .backgroundColor(0x007DFF)
    } else if (item.type == 1) {
      Row() {
        Image(item.pic).width(70.0).height(70.0)
        Column() {
          Text(item.title)
          Text(item.content)
        }
        .layoutWeight(1.0)
        .alignItems(HorizontalAlign.Start) //Column内容居左
        Image(item.pic).width(70.0).height(70.0)
      }
      .width('100%')
      .height(70.0)
      .borderRadius(10)
      .backgroundColor(0x007DFF)
    } else {
      Row() {
        Image(item.pic).width(70.0).height(70.0)
        Column() {
          Text(item.title)
          Text(item.content)
        }
        .layoutWeight(1.0)
        .alignItems(HorizontalAlign.Start) //Column内容居左
      }
      .width('100%')
      .height(70.0)
      .borderRadius(10)
      .backgroundColor(0x007DFF)
    }
  }
}

预览布局

ReactNative 列表布局

使用 FlatList 创建列表布局

import React from 'react';
import {AppRegistry} from 'react-native';
import {name as appName} from './app.json';
import { SafeAreaView,FlatList, Text, View, StyleSheet,Image,StatusBar } from 'react-native';

const DATA = [
  {
    id: '0',
    title: '当前列表选项1',
    icon: require('./assets/icon_0.png'),
  },
  {
    id: '1',
    title: '当前列表选项2',
     icon: require('./assets/icon_1.png'),
  },
  {
    id: '2',
    title: '当前列表选项3',
    icon: require('./assets/icon_2.png'),
  },
];

const Item = ({item}) => (
  <View style={styles.item}>
    <Image source={item.icon} style={styles.imageLeft}/>
    <Text style={styles.title}>{item.title}</Text>
    <Image source={item.icon} style={styles.imageLeft}/>
  </View>
);

const App = () => {
  return (
    <SafeAreaView style={styles.container}>
      <FlatList
        data={DATA}
        renderItem={({item}) => <Item item={item} />}
        keyExtractor={item => item.id}
      />
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: StatusBar.currentHeight || 0,
  },
  item: {
    backgroundColor: '#f9c2ff',
    padding: 10,
    marginVertical: 8,
    marginHorizontal: 8,
    flexDirection: 'row',//布局水平方向
    flex: 1,
    alignItems: 'center',//居中
  },
  title: {
    flex: 1,
    fontSize: 16,
    textAlign: 'start',//文本位于开始位置
    backgroundColor: '#CCCCFF',
  },
  imageLeft:{
    width:40,
    height:40,
  }
});

AppRegistry.registerComponent(appName, () => App);

预览布局

案例

image.png