Android中RecycleView的使用

315 阅读4分钟

参考 《第一行代码》第二版

使用的工具

现在android项目使用的 android studio 来进行开发,开发的语言现在推荐的是 kotlin, 不过这里还是先使用 Java 来开发

添加依赖

想要使用 RecycleView 需要先添加对应的依赖,在 app 项目下的 build.gralde 文件中添加如下内容

dependencies {  
	......  
    implementation 'androidx.recyclerview:recyclerview:1.3.2'  
}

RecycleView的使用示例

最终的效果如下图所示 还有很多行数据,可以滑动显示 这个示例中主要包含

  • MainActivity 是项目的主 Activity
  • activity_main.xml 主Activity对应的配置文件
  • fruit_item.xml 是 RecycleView 中每一项元素的布局文件
  • CusRecycleAdapter 是 RecycleView 中对应的 Adapter

activity_main.xml

主布局文件中就使用了一个 RecycleView

<?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="match_parent"  
    android:orientation="vertical">  
    <androidx.recyclerview.widget.RecyclerView  
        android:id="@+id/recycle_view"  
        android:layout_width="match_parent"  
        android:layout_height="match_parent"/>  
</LinearLayout>

fruit_item.xml

  • fruit_item.xml 是对于 RecycleView 中每一项元素的布局
  • 每一项元素的根布局是 LinearLayout, 排列方向 orientation="horizontal",即是水平排列,因为这个布局里面包含两个元素,一个是图片(ImageView),另外一个是文本(TextView),因为是水平排列,所以左侧是图片,右侧是文字
<?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"  
    android:orientation="horizontal">  
  
    <ImageView  
        android:id="@+id/fruit_image"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content" />  
  
    <TextView  
        android:id="@+id/fruit_name"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_marginLeft="20dp"  
        android:layout_gravity="center_vertical"/>  
  
</LinearLayout>

CusRecycleAdapter

和 ListView 中的 Adapter 一样,RecycleView 也有一个 Adapter,起到的作用就是将单项数据绑定到对应的布局上(在这个例子中就是将单项数据绑定到 fruit_view.xml 对应的布局上)

package com.example.ademo.adapter;  
  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.ViewGroup;  
import android.widget.ImageView;  
import android.widget.TextView;  
  
import androidx.annotation.NonNull;  
import androidx.recyclerview.widget.RecyclerView;  
  
import com.example.ademo.R;  
import com.example.ademo.vo.EachItem;  
  
import java.util.List;  
  
public class CusRecycleAdapter extends RecyclerView.Adapter<CusRecycleAdapter.ViewHolder> {  
  
	// 保存需要展示的所有数据
    private List<EachItem> list;  
	// 构造 RecycleAdapter 的时候需要将需要展示的所有数据传递进来
    public CusRecycleAdapter(List<EachItem> list) {  
        this.list = list;  
    }  

	// ViewHolder 顾名思义就是持有 View 的,持有什么 View 呢? 其实就是
	// RecycleView 中单个元素所对应的布局,这里的 View 其实是 ViewGroup 类型
    static class ViewHolder extends RecyclerView.ViewHolder {  
        ImageView imageView;  
        TextView textView;  
  
        /**  
         * 这里的 View 一般就是 RecyclerView 子项的最外层布局, 在这个例子中其实就是 fruit_item 对应的布局  
         * 对应的就是 onCreateViewHolder 创建的 ViewHolder 中的  View  
         *         * @param itemView  
         */  
        public ViewHolder(@NonNull View itemView) {  
            super(itemView);  
            imageView = itemView.findViewById(R.id.fruit_image);  
            textView = itemView.findViewById(R.id.fruit_name);  
        }  
    }  
  
    /**  
     * onCreateViewHolder 的作用其实就是加载每一项元素的布局,这里加载的布局得到了 View  
     * 然后将 View 存储在 ViewHolder 中,然后返回 ViewHolder  
     *     * @return     */    @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;  
    }  
  
    /**  
     * onBindViewHolder()方法是用于对RecyclerView子项的数据进行赋值的,会在每个子项被滚动到屏幕内的时候执行  
     */  
    @Override  
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {  
        EachItem eachItem = list.get(position);  
        holder.imageView.setImageResource(eachItem.getImageId());  
        holder.textView.setText(eachItem.getName());  
    }  
  
    @Override  
    public int getItemCount() {  
        return list.size();  
    }  
}

MainActivity

接下来就是使用 RecycleView 的主 Activity 了

package com.example.ademo;  
  
import android.os.Bundle;  
import android.util.Log;  
  
import androidx.appcompat.app.AppCompatActivity;  
import androidx.recyclerview.widget.LinearLayoutManager;  
import androidx.recyclerview.widget.RecyclerView;  
  
import com.example.ademo.adapter.CusRecycleAdapter;  
import com.example.ademo.vo.EachItem;  
  
import java.util.ArrayList;  
import java.util.List;  
  
public class MainActivity extends AppCompatActivity {  
  
    private List<EachItem> list = new ArrayList<>();  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        Log.d("MainActivity", "开始创建主Activity" + this);  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        initItem();  
        RecyclerView recyclerView = findViewById(R.id.recycle_view);  
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);  
        recyclerView.setLayoutManager(linearLayoutManager);  
  
        CusRecycleAdapter adapter = new CusRecycleAdapter(list);  
        recyclerView.setAdapter(adapter);  
    }  
  
    /**  
     * 初始化明细数据  
     */  
    private void initItem() {  
        for (int i = 0; i < 20; i++) {  
            EachItem eachItem = new EachItem("水果" + i, R.drawable.ic_launcher_background);  
            list.add(eachItem);  
        }  
    }  
}

可以看到 RecycleView 和 ListView 的区别是使用 RecycleView 时除了要设置 Adapter 之外,还需要设置LayoutManager,这也是 RecycleView 的强大之处,可以自定义设置外层布局

RecycleView点击事件

RecyclerView 没有提供类似于 setOnItemClickListener() 这样的注册监听器方法,需要我们自己给子项具体的View去注册点击事件,我们在上面的例子中改造,点击每一项的时候都弹出对应的内容,主要是修改 Adapter 类

package com.example.ademo.adapter;  
  
import android.util.Log;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.ViewGroup;  
import android.widget.ImageView;  
import android.widget.TextView;  
import android.widget.Toast;  
  
import androidx.annotation.NonNull;  
import androidx.recyclerview.widget.RecyclerView;  
  
import com.example.ademo.R;  
import com.example.ademo.vo.EachItem;  
  
import java.util.List;  
  
public class CusRecycleAdapter extends RecyclerView.Adapter<CusRecycleAdapter.ViewHolder> {  
  
  
    private List<EachItem> list;  
  
    public CusRecycleAdapter(List<EachItem> list) {  
        this.list = list;  
    }  
  
    static class ViewHolder extends RecyclerView.ViewHolder {  
  
        ImageView imageView;  
        TextView textView;  
  
        /**  
         * 这里的 View 一般就是 RecyclerView 子项的最外层布局, 在这个例子中其实就是 fruit_item 对应的布局  
         * 对应的就是 onCreateViewHolder 创建的 ViewHolder 中的  View  
         *         * @param itemView  
         */  
        public ViewHolder(@NonNull View itemView) {  
            super(itemView);  
            imageView = itemView.findViewById(R.id.fruit_image);  
            textView = itemView.findViewById(R.id.fruit_name);  
        }  
    }  
  
    /**  
     * onCreateViewHolder 的作用其实就是加载每一项元素的布局,这里加载的布局得到了 View  
     * 然后将 View 存储在 ViewHolder 中,然后返回 ViewHolder  
     *     * @return     */    @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);  
        viewHolder.imageView.setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                int bindingAdapterPosition = viewHolder.getBindingAdapterPosition();  
                EachItem eachItem = list.get(bindingAdapterPosition);  
                Log.d("onCreateViewHolder", "图片点击: " + eachItem.getName());  
            }  
        });  
        viewHolder.textView.setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                int bindingAdapterPosition = viewHolder.getBindingAdapterPosition();  
                EachItem eachItem = list.get(bindingAdapterPosition);  
                Log.d("onCreateViewHolder", "文本点击: " + eachItem.getName());  
            }  
        });  
        return viewHolder;  
    }  
  
    /**  
     * onBindViewHolder()方法是用于对RecyclerView子项的数据进行赋值的,会在每个子项被滚动到屏幕内的时候执行  
     */  
    @Override  
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {  
        EachItem eachItem = list.get(position);  
        holder.imageView.setImageResource(eachItem.getImageId());  
        holder.textView.setText(eachItem.getName());  
    }  
  
    @Override  
    public int getItemCount() {  
        return list.size();  
    }  
}