Android控件学习(十)——RecyclerView

别来无恙 提交于 2020-01-24 22:14:56

ListView的进阶版,可以实现横向滚动

这次也新建一个项目:day05_RecyclerView

一、基本用法

1、导入依赖库

参考资料:Android布局学习(四)——百分比布局Percent?Layout
新增控件需要引入依赖库,在app/build.gradle中添加如下内容:

implementation 'androidx.recyclerview:recyclerview:1.0.0'

2、主布局添加控件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

</LinearLayout>

3、子布局

fruit_item.xml,和上篇文章一样

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/fruite_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
    <TextView
        android:id="@+id/fruite_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="10dp"
        />

</LinearLayout>

4、类和适配器

类和上篇文章一样:

public class Fruit {
    private String name;
    private int imageId;
    
    public Fruit(String name,int imageId){
        this.name = name;
        this.imageId = imageId;
    }
    public String getName(){
        return name;
    }
    public int getImageId(){
        return imageId;
    }
}

新建类FruitAdapter继承自RecyclerView.Adapter,指定泛型为FruitAdapter.ViewHolder

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
    private List<Fruit> mFruitList;

    static class ViewHolder extends RecyclerView.ViewHolder{
        ImageView fruitImage;
        TextView fruitName;

        public ViewHolder(View view){
            super(view);
            fruitImage = (ImageView) view.findViewById(R.id.fruite_image);
            fruitName = (TextView) view.findViewById(R.id.fruite_name);
        }
    }

    public FruitAdapter(List<Fruit> fruitList){
        mFruitList = fruitList;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent, false);
        ViewHolder viewholder = new ViewHolder(view);
        return viewholder;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Fruit fruit = mFruitList.get(position);
        holder.fruitImage.setImageResource(fruit.getImageId());
        holder.fruitName.setText(fruit.getName());
    }

    @Override
    public int getItemCount() {
        return mFruitList.size();
    }
}
  • 首先定义了内部类 ViewHolder,继承自RecyclerView.ViewHolder,其中传入了一个View参数,这个参数继承通常是RecycleView子项的最外层布局,通过它就能取到 ImageViewTextView
  • FruitAdapter 的构造函数把要传递的数据源传递进来,并赋给全局变量
  • 必须重写的三个方法:
    • onCreateViewHolder(): 用来创建ViewHolder实例,在这个方法中,将子布局传入创建的ViewHolder实例,然后将其返回
    • onBindViewHolder():对RecyclerView子项数据赋值,会在子项布局滚动到屏幕时执行
    • getItemCount():返回数据源的长度,用来判断子布局的个数

5、主活动修改

public class MainActivity extends AppCompatActivity {

    private List<Fruit> fruitList = new ArrayList<>();

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

        initFruits();
        FruitAdapter adapter = new FruitAdapter(fruitList);
        RecyclerView recyclerView = findViewById(R.id.recycler_view);
        
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setAdapter(adapter);
    }

    private void initFruits(){
        for (int i = 0; i < 2; i++){
            Fruit apple = new Fruit("苹果", R.drawable.apple);
            fruitList.add(apple);
            Fruit banana = new Fruit("香蕉", R.drawable.banana);
            fruitList.add(banana);
            Fruit orange = new Fruit("橙子", R.drawable.orange);
            fruitList.add(orange);
            Fruit watermelon = new Fruit("西瓜", R.drawable.watermelon);
            fruitList.add(watermelon);
            Fruit pear = new Fruit("梨", R.drawable.pear);
            fruitList.add(pear);
            Fruit grape = new Fruit("葡萄", R.drawable.grape);
            fruitList.add(grape);
            Fruit pineapple = new Fruit("菠萝", R.drawable.pineapple);
            fruitList.add(pineapple);
            Fruit strawberry = new Fruit("草莓", R.drawable.strawberry);
            fruitList.add(strawberry);
            Fruit cherry = new Fruit("樱桃", R.drawable.cherry);
            fruitList.add(cherry);
            Fruit mango = new Fruit("芒果", R.drawable.mango);
            fruitList.add(mango);
        }
    }
}

先通过initFruit()初始化水果数据,接着创建RecycleView实例,然后创建了一个LinearLayoutManger对象,并将它设置到RecycleView中,表示使用线性布局,最后创建FruitAdapter实例建立数据关联

6、运行

在这里插入图片描述

二、实现横向滚动

1、子布局

首先修改子布局,排列方向垂直,宽度100dp,图片和文字中心水平居中,上下边距10dp

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="100dp"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/fruite_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        />
    
    <TextView
        android:id="@+id/fruite_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"
        />

</LinearLayout>

2、主活动修改

只修改调用的LineatLayout属性,修改为水平,加入一行代码即可

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    initFruits();
    FruitAdapter adapter = new FruitAdapter(fruitList);
    RecyclerView recyclerView = findViewById(R.id.recycler_view);

    LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setAdapter(adapter);
}

3、运行

支持横向滚动:
在这里插入图片描述

三、实现瀑布流布局

1、子布局

这次的宽度根据布局的列数自动适配,设置了边距5dp

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp">

    <ImageView
        android:id="@+id/fruite_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        />

    <TextView
        android:id="@+id/fruite_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="ccenter_horizontal"
        android:layout_marginTop="10dp"
        />

</LinearLayout>

2、主活动修改

使用StaggeredGridLayoutManger布局,仅修改一行代码:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    initFruits();
    FruitAdapter adapter = new FruitAdapter(fruitList);
    RecyclerView recyclerView = findViewById(R.id.recycler_view);

    StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setAdapter(adapter);
}

StaggeredGridLayoutManger的构造函数接收两个参数,第一个参数用来指定布局列数;第二个参数指定排列方向

3、运行

在这里插入图片描述

四、点击事件

RecyclerView的点击实现起来比ListView要复杂,所有的点击事件都由具体的View去注册,这样每个子项的按钮都能注册不同的事件

1、修改适配器

重写两个方法viewHolderonCreateViewHolder

static class ViewHolder extends RecyclerView.ViewHolder{
    View fruitView;
    ImageView fruitImage;
    TextView fruitName;

    ViewHolder(View view){
        super(view);
        fruitView = view;
        fruitImage = view.findViewById(R.id.fruite_image);
        fruitName = view.findViewById(R.id.fruite_name);
    }
}

@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent, false);
    final ViewHolder holder = new ViewHolder(view);
    holder.fruitName.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v) {
            int position = holder.getAdapterPosition();
            Fruit fruit = mFruitList.get(position);
            Toast.makeText(v.getContext(), "你点击了文字 "+fruit.getName(), Toast.LENGTH_SHORT).show();
        }
    });
    holder.fruitImage.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int position = holder.getAdapterPosition();
            Fruit fruit = mFruitList.get(position);
            Toast.makeText(v.getContext(), "你点击了图片 "+fruit.getName(), Toast.LENGTH_SHORT).show();
        }
    });
    return holder;
}

2、运行

点击草莓的图片:
在这里插入图片描述
点击草莓的文字:
在这里插入图片描述

完成!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!