更强大的滚动控件---RecyclerView

更强大的滚动控件—RecyclerView

RecyclerView的基本用法

  • ListView的扩展性和性能比较差,需要做一些技巧来提升他的效率,而且他是能实现数据的纵向滚动,并不能横向滚动

  • RecyclerView是一个增强版的ListView,可以轻松实现ListView同样的效果,还优化了ListView的不足之处

    //首先在项目的build.gradle中添加相应的依赖库
    //打开app/build.gradle,在dependencies闭包中添加以下内容,添加完之后点击Sync Now进行同步
    dependencies {
        implementation fileTree(dir: 'libs',includes: ['*.jar'])
        implementation 'androidx.appcompat:appcompat:1.0.0'
        implementation 'androidx.recyclerview:recyclerview:1.0.0'
        testImplementation 'junit:junit:4.12'
    }
    
    //修改activity_main.xml
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    	//由于RecyclerView并不是内置在系统SDK中,所以需要把完整的包路径写出来
       <androidx.recyclerview.widget.RecyclerView
           android:id="@+id/relative_view"
           android:layout_width="match_parent"
           android:layout_height="match_parent"/>
    </LinearLayout>
               
    //将写在ListView项目的Fruit类和fruit_item.xml也复制过来,接下来为RecyclerView准备一个适配器,新建FruitAdapter类,让其继承自RecursiveAction.Adapter, ViewHolder是在FruitAdapter中定义的一个内置类
    public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
        //定义一个全局变量
        private List<Fruit> mFruitList;
        //定义一个内部类ViewHolder,ViewHolder要继承RecyclerView.ViewHolder
        static class ViewHolder extends RecyclerView.ViewHolder{
            ImageView fruitImage;
            TextView fruitName;
            //构造函数中要传入一个View参数,这个参数通常是RecyclerView子项的最外层布局,
            // 那么就可以通过findViewById()方法来获取到不居中的ImageView和TextView的实例了
            public ViewHolder(View view){
                super(view);
                fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
                fruitName = (TextView) view.findViewById(R.id.fruit_name);
            }
        }
        //FruitAdapter中也有一个构造函数,这个方法用于把展示的数据源传进来,并赋值给一个全局变量mFruitList,后		续操作都在这个数据源上进行
        public FruitAdapter(List<Fruit> fruitList){
            mFruitList = fruitList;
        }
        //由于RecyclerView继承自RecyclerView.Adapter,那么就必须重写onCreateViewHolder(),onBindViewHolder(),getItemCount()方法
        //onCreateViewHolder()方法用于创建ViewHolder实例,
        //在这个方法内将fruit_item布局加载进来,然后创建一个ViewHolder实例,并将加载出来的布局传入构造函数中,		最后将ViewHolder实例返回
        @Override
        public ViewHolder onCreateViewHolder( ViewGroup parent, int viewType) {
            View view= 										LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,parent,false);
            ViewHolder holder = new ViewHolder(view);
            return holder;
        }
        //onBindViewHolder()方法是用于对RecyclerView子项的数据进行赋值的,会在每个子项被滚动到屏幕内的时候执行,
        // 这里通过position参数的到当前项的Friut实例,然后再将数据设置到ViewHolder的ImageView和TextView中
        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            Fruit fruit = mFruitList.get(position);
            holder.fruitImage.setImageResource(fruit.getImageId());
            holder.fruitName.setText(fruit.getName());
        }
    
        //getItemCount()方法用于告诉RecyclerView一共有多少子项,直接返回数据源的长度
        @Override
        public int getItemCount() {
           return mFruitList.size();
        }
    }
    
               
    //修改MainActivity,使用RecyclerView
    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();
            //获取RecyclerView实例
            RecyclerView recyclerView = findViewById(R.id.relative_view);
            //创建一个LinearLayoutManager对象并将他设置到RecyclerView中,LayoutManager用于制定布局方式,LinearLayoutManager是线性布局的意思,可以实现与ListView相似的效果
            LinearLayoutManager layoutManager = new LinearLayoutManager(this);
            recyclerView.setLayoutManager(layoutManager);
            //创建FruitAdapter实例,并将水果数据传入FruitAdapter的构造函数中
            FruitAdapter adapter = new FruitAdapter(fruitList);
            //最后调用setAdapter()方法完成适配器设置
              recyclerView.setAdapter(adapter);
        }
        private  void initFruits(){
            for (int i = 0;i<2;i++){
                Fruit apple = new Fruit("Apple",R.drawable.apple);
                fruitList.add(apple);
                Fruit banner = new Fruit("Banner",R.drawable.banner);
                fruitList.add(banner);
                Fruit orange = new Fruit("Orange",R.drawable.orange);
                fruitList.add(orange);
                Fruit watermelon = new Fruit("Watermelon",R.drawable.watermelon);
                fruitList.add(watermelon);
                Fruit pear = new Fruit("Pear",R.drawable.pear);
                fruitList.add(pear);
                Fruit grape = new Fruit("Grape",R.drawable.grape);
                fruitList.add(grape);
                Fruit pineapple = new Fruit("Pineapple",R.drawable.pineapple);
                fruitList.add(pineapple);
                Fruit strawberry = new Fruit("Strawberry",R.drawable.strawberry);
                fruitList.add(strawberry);
                Fruit cherry = new Fruit("Cherry",R.drawable.cherry);
                fruitList.add(cherry);
                Fruit mango = new Fruit("Mango",R.drawable.mango);
                fruitList.add(mango);
    
            }
        }
    }
    
  • 运行结果

在这里插入图片描述

实现横向滚动和瀑布流布局

横向滚动
//修改布局fruit_item.xml,将元素改为垂直排列
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/fruit_image"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="center_horizontal" />

    <TextView
        android:id="@+id/fruit_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginTop="10dp" />
</LinearLayout>
            
//修改MainActivity,调用LinearLayoutManager的setOrientation()方法来设置布局的排列方向,默认是纵向,传入LinearLayoutManager.HORIZONTAL表示让布局横向排列
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();
        RecyclerView recyclerView = findViewById(R.id.relative_view);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        recyclerView.setLayoutManager(layoutManager);
        FruitAdapter adapter = new FruitAdapter(fruitList);
        recyclerView.setAdapter(adapter);
    }
    private  void initFruits(){
        for (int i = 0;i<2;i++){
            Fruit apple = new Fruit("Apple",R.drawable.apple);
            fruitList.add(apple);
            Fruit banner = new Fruit("Banner",R.drawable.banner);
            fruitList.add(banner);
            Fruit orange = new Fruit("Orange",R.drawable.orange);
            fruitList.add(orange);
            Fruit watermelon = new Fruit("Watermelon",R.drawable.watermelon);
            fruitList.add(watermelon);
            Fruit pear = new Fruit("Pear",R.drawable.pear);
            fruitList.add(pear);
            Fruit grape = new Fruit("Grape",R.drawable.grape);
            fruitList.add(grape);
            Fruit pineapple = new Fruit("Pineapple",R.drawable.pineapple);
            fruitList.add(pineapple);
            Fruit strawberry = new Fruit("Strawberry",R.drawable.strawberry);
            fruitList.add(strawberry);
            Fruit cherry = new Fruit("Cherry",R.drawable.cherry);
            fruitList.add(cherry);
            Fruit mango = new Fruit("Mango",R.drawable.mango);
            fruitList.add(mango);

        }
    }
}

在这里插入图片描述

瀑布流布局
//修改fruit_item布局,使用layout_margin属性让子项之间互留间距,TextView对其属性改为居左对齐
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:layout_margin="5dp"
    >

    <ImageView
        android:id="@+id/fruit_image"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="center_horizontal" />

    <TextView
        android:id="@+id/fruit_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:layout_marginTop="10dp" />
</LinearLayout>
            
//修改MainActivity
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();
        RecyclerView recyclerView = findViewById(R.id.relative_view);
        //创建StaggeredGridLayoutManager实例。StaggeredGridLayoutManager的构造函数接收两个参数,第一个是布局的列数,第二个是布局的排列方向,StaggeredGridLayoutManager.VERTICAL是让布局纵向排列
        StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);
        //吧创建好的实例设置到RecyclerView中
        recyclerView.setLayoutManager(layoutManager);
        FruitAdapter adapter = new FruitAdapter(fruitList);
        recyclerView.setAdapter(adapter);
    }
    private  void initFruits(){
        for (int i = 0;i<2;i++){
            Fruit apple = new Fruit(getRandomLengthName("Apple"),R.drawable.apple);
            fruitList.add(apple);
            Fruit banner = new Fruit(getRandomLengthName("Banner"),R.drawable.banner);
            fruitList.add(banner);
            Fruit orange = new Fruit(getRandomLengthName("Orange"),R.drawable.orange);
            fruitList.add(orange);
            Fruit watermelon = new Fruit(getRandomLengthName("Watermelon"),R.drawable.watermelon);
            fruitList.add(watermelon);
            Fruit pear = new Fruit(getRandomLengthName("Pear"),R.drawable.pear);
            fruitList.add(pear);
            Fruit grape = new Fruit(getRandomLengthName("Grape"),R.drawable.grape);
            fruitList.add(grape);
            Fruit pineapple = new Fruit(getRandomLengthName("Pineapple"),R.drawable.pineapple);
            fruitList.add(pineapple);
            Fruit strawberry = new Fruit(getRandomLengthName("Strawberry"),R.drawable.strawberry);
            fruitList.add(strawberry);
            Fruit cherry = new Fruit(getRandomLengthName("Cherry"),R.drawable.cherry);
            fruitList.add(cherry);
            Fruit mango = new Fruit(getRandomLengthName("Mango"),R.drawable.mango);
            fruitList.add(mango);

        }
    }
//设置名称长短随机
    private String getRandomLengthName(String name) {
        Random random = new Random();
        int length = random.nextInt(20)+1;
        StringBuilder builder = new StringBuilder();
        for (int i = 0;i<length;i++){
            builder.append(name);
        }
        return  builder.toString();
    }
}
  • 运行结果
    在这里插入图片描述

RecyclerView的点击事件

//修改FruitAdapter

//为RecyclerView准备一个适配器,新建FruitAdapter类,让这个适配器继承自RecursiveAction.Adapter
public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
    //定义一个全局变量
    private List<Fruit> mFruitList;
    //定义一个内部类ViewHolder,ViewHolder要继承RecyclerView.ViewHolder
    static class ViewHolder extends RecyclerView.ViewHolder{
        View fruitView; //添加fruitView变量来保存子项最外层布局的实例,然后在onCreateViewHolder()方法中注册点击事件
        ImageView fruitImage;
        TextView fruitName;
        //构造函数中要传入一个View参数,这个参数通常是RecyclerView子项的最外层布局,
        // 那么就可以通过findViewById()方法来获取到不居中的ImageView和TextView的实例了
        public ViewHolder(View view){
            super(view);
            fruitView = view;
            fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
            fruitName = (TextView) view.findViewById(R.id.fruit_name);
        }
    }
    //FruitAdapter中也有一个构造函数,这个方法用于把展示的数据源传进来,并赋值给一个全局变量mFruitList,后续操作都在这个数据源上进行
    public FruitAdapter(List<Fruit> fruitList){
        mFruitList = fruitList;
    }
    //由于RecyclerView继承自RecyclerView.Adapter,那么就必须重写onCreateViewHolder(),onBindViewHolder(),getItemCount()方法
    //onCreateViewHolder()方法用于创建ViewHolder实例,
    //在这个方法内将fruit_item布局加载进来,然后创建一个ViewHolder实例,并将加载出来的布局传入构造函数中,最后将ViewHolder实例返回
    @Override
    public ViewHolder onCreateViewHolder( ViewGroup parent, int viewType) {
        View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,parent,false);
        final  ViewHolder holder = new ViewHolder(view);
        //以下两个点击事件中先获取了用户点击的position,然后通过position拿到相应的Fruit实例
        //为最外层布局注册点击事件
        holder.fruitView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getAdapterPosition();
                Fruit fruit = mFruitList.get(position);
                Toast.makeText(v.getContext(),"you clicked view" + 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(),"you clicked image" + fruit.getName(),Toast.LENGTH_SHORT).show();
            }
        });
        return holder;
    }
    //onBindViewHolder()方法是用于对RecyclerView子项的数据进行赋值的,会在每个子项被滚动到屏幕内的时候执行,
    // 这里通过position参数的到当前项的Friut实例,然后再将数据设置到ViewHolder的ImageView和TextView中
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Fruit fruit = mFruitList.get(position);
        holder.fruitImage.setImageResource(fruit.getImageId());
        holder.fruitName.setText(fruit.getName());
    }
    //getItemCount()方法用于告诉RecyclerView一共有多少子项,直接返回数据源的长度
    @Override
    public int getItemCount() {
       return mFruitList.size();
    }
}
  • 运行结果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值