day23 Recyclerview、XRecyclerview的使用:上拉加载 下拉刷新、万能适配器、ItemTouchHelpe实现拖拽和侧滑删除

本文详细介绍了RecyclerView的基本使用、优点,包括封装的ViewHolder复用、布局管理器的设置、Item动画以及点击事件的自定义。还探讨了多布局实现、随机高度瀑布流,并介绍了XRecyclerView的上拉加载和下拉刷新功能。此外,通过ItemTouchHelper实现了RecyclerView中的拖拽和侧滑删除操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

RecyclerView是什么
从Android 5.0开始,谷歌公司推出了一个用于大量数据展示的新控件RecylerView,可以用来代替传统的ListView,更加强大和灵活。RecyclerView的官方定义如下:
A flexible view for providing a limited window into a large data set.
从定义可以看出,flexible(可扩展性)是RecyclerView的特点。

RecyclerView是support-v7包中的新组件,是一个强大的滑动组件,与经典的ListView相比,同样拥有item回收复用的功能,这一点从它的名字Recyclerview即回收view也可以看出。

优点

RecyclerView并不会完全替代ListView(这点从ListView没有被标记为@Deprecated可以看出),两者的使用场景不一样。但是RecyclerView的出现会让很多开源项目被废弃,例如横向滚动的ListView, 横向滚动的GridView, 瀑布流控件,因为RecyclerView能够实现所有这些功能。

RecylerView相对于ListView的优点如下:

·RecyclerView封装了viewholder的回收复用,也就是说RecyclerView标准化了ViewHolder,编写Adapter面向的是ViewHolder而不再是View了,复用的逻辑被封装了,写起来更加简单。
·提供了一种插拔式的体验,高度的解耦,异常的灵活,针对一个Item的显示RecyclerView专门抽取出了相应的类,来控制Item的显示,使其的扩展性非常强。
·设置布局管理器以控制Item的布局方式,横向、竖向以及瀑布流方式
·可设置Item的间隔样式(可绘制)
通过继承RecyclerView的ItemDecoration这个类,然后针对自己的业务需求去书写代码。
·可以控制Item增删的动画,可以通过ItemAnimator这个类进行控制,当然针对增删的动画,RecyclerView有其自己默认的实现。

但是关于Item的点击和长按事件,需要用户自己去实现。
重要方法·

1.RecyclerView横向滑动:
LinearLayoutManager.HORIZONTAL横向滑动LinearLayoutManager.VERTICAL垂直滑动
2.RecyclerView.Adapter中刷新方法区别:
notifyDataSetChanged();整体刷新+没有动画效果
notifyItemInserted(int position,Object data):有动画效果+添加一条数据在position位置
notifyItemRemoved(position);有动画效果+删除一条数据并刷新
注意:当添加和删除的时候,要更新下标,不然有错位现象
先在集合中删除要删除的数据
之后
myRecyclerViewAdapter.notifyItemRangeChanged(0,arrayList.size());
3.RecyclerView多布局展示:
public int getItemViewType(int position)返回当前数据的itemview类型
4.RecyclerView常见方法:
LinearLayoutManager:recyclerview线性管理器(垂直水平方向);
GridLayoutManager:网格布局管理器;
StaggeredGridLayoutManager:瀑布流布局管理器;
RecyclerView.setLayoutManager(LayoutManager manager):添加布局管理器
RecyclerView.addItemDecoration(ItemDecoration decoration):添加分割线
RecyclerView.setItemAnimator(ItemAnimator animator):添加动画方法
RecyclerView.setAdapter(Adapter adapter):添加适配器

RecyclerView的使用

1.导入依赖
implementation ‘com.android.support:recyclerview-v7:28.0.0’

布局

<?xml version="1.0" encoding="utf-8"?>
<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">

    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/my_recycler_view">

    </android.support.v7.widget.RecyclerView>

</LinearLayout>

2.适配器

点击事件(接口回调)

public interface MyClickListener {
    void onItemClick(int i);
}
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

    ArrayList<HashMap<String,String>> arrayList;
    Context context;
    MyClickListener myClickListener;

    public MyAdapter(ArrayList<HashMap<String, String>> arrayList, Context context,MyClickListener myClickListener) {
        this.arrayList = arrayList;
        this.context = context;
        this.myClickListener = myClickListener;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view = View.inflate(context,R.layout.item,null);
        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, final int i) {
        myViewHolder.textView.setText(arrayList.get(i).get("title"));
        myViewHolder.textView2.setText(arrayList.get(i).get("intro"));
        Glide.with(context).load(arrayList.get(i).get("strUrl")).apply(RequestOptions.bitmapTransform(new RoundedCorners(20))).into(myViewHolder.imageView);
        myViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myClickListener.onItemClick(i);
            }
        });
    }

    @Override
    public int getItemCount() {
        return arrayList.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder{

        ImageView imageView;
        TextView textView,textView2;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.item_img);
            textView = itemView.findViewById(R.id.item_txt);
            textView2 = itemView.findViewById(R.id.item_txt2);
        }
    }
}

实现多布局(联系人)

注意添加权限
适配器

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

    ArrayList<MyContent> arrayList;
    Context context;

    public MyRecyclerViewAdapter(ArrayList<MyContent> arrayList, Context context) {
        this.arrayList = arrayList;
        this.context = context;
    }

    @Override
    public int getItemViewType(int position) {
        return arrayList.get(position).getFlag();
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        if (i == 0){
            View view = LayoutInflater.from(context).inflate(R.layout.item_title,viewGroup,false);
            return new TitleViewHolder(view);
        }else {
            View view = LayoutInflater.from(context).inflate(R.layout.item_phone,viewGroup,false);
            return new PhoneViewHolder(view);
        }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
        if (arrayList.get(i).getFlag() == 0){
            TitleViewHolder titleViewHolder = (TitleViewHolder) viewHolder;
            titleViewHolder.textView.setText(arrayList.get(i).getPhonebook_label());
        }else {
            PhoneViewHolder phoneViewHolder = (PhoneViewHolder) viewHolder;
            phoneViewHolder.textView.setText(arrayList.get(i).getName()+"       "+arrayList.get(i).getPhoneNum());
        }
    }

    @Override
    public int getItemCount() {
        Log.e("####",arrayList.size()+"");
        return arrayList.size();
    }

    class TitleViewHolder extends RecyclerView.ViewHolder{

        TextView textView;
        public TitleViewHolder(@NonNull View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.item_title);
        }
    }
    class PhoneViewHolder extends RecyclerView.ViewHolder{

        TextView textView;
        public PhoneViewHolder(@NonNull View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.item_phone);
        }
    }
}

联系人 类

public class MyContent {
    private String name;
    private String phoneNum;
    private String phonebook_label;
    private int flag;

    public MyContent(String name, String phoneNum, String phonebook_label, int flag) {
        this.name = name;
        this.phoneNum = phoneNum;
        this.phonebook_label = phonebook_label;
        this.flag = flag;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhoneNum() {
        return phoneNum;
    }

    public void setPhoneNum(String phoneNum) {
        this.phoneNum = phoneNum;
    }

    public String getPhonebook_label() {
        return phonebook_label;
    }

    public void setPhonebook_label(String phonebook_label) {
        this.phonebook_label = phonebook_label;
    }

    public int getFlag() {
        return flag;
    }

    public void setFlag(int flag) {
        this.flag = flag;
    }

    @Override
    public String toString() {
        return "MyContent{" +
                "name='" + name + '\'' +
                ", phoneNum='" + phoneNum + '\'' +
                ", phonebook_label='" + phonebook_label + '\'' +
                ", flag=" + flag +
                '}';
    }
}

Activity

public class MainActivity extends AppCompatActivity {

    RecyclerView recyclerView;
    ArrayList<MyContent> arrayList = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (Build.VERSION.SDK_INT > 23){
            int i = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS);
            if (i == PackageManager.PERMISSION_DENIED){
                requestPermissions(new String[]{Manifest.permission.READ_CONTACTS,Manifest.permission.WRITE_CONTACTS},60);
            }
        }
        recyclerView = findViewById(R.id.my_recycler_view);
        Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
        ContentResolver resolver = getContentResolver();
        Cursor cursor = resolver.query(uri, null, null, null, "phonebook_label");
        String str = "";
        while (cursor.moveToNext()){
            String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
            String phoneNum = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
            String phonebook_label = cursor.getString(cursor.getColumnIndex("phonebook_label"));
            MyContent myContent = new MyContent(name, phoneNum, phonebook_label, 1);
            Log.e("####",phonebook_label);
            if (str.equals(phonebook_label)){
                arrayList.add(myContent);
            }else {
                arrayList.add(new MyContent(null,null,phonebook_label,0));
                arrayList.add(myContent);
                str = phonebook_label;
            }
        }
        MyRecyclerViewAdapter myRecyclerViewAdapter = new MyRecyclerViewAdapter(arrayList, this);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerView.setAdapter(myRecyclerViewAdapter);
        myRecyclerViewAdapter.notifyItemRangeChanged(0,arrayList.size());

    }
}

随机高度瀑布流

在这里插入图片描述

imageView = itemView.findViewById(R.id.video);
ViewGroup.LayoutParams layoutParams = imageView.getLayoutParams();
layoutParams.height = (int) (Math.random() * 200+400);
imageView.setLayoutParams(layoutParams);
textView = itemView.findViewById(R.id.textview);

item行布局ImageView添加的属性

<ImageView
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:scaleType="fitXY"
    android:id="@+id/item_img"/>

XRecyclerview的使用:上拉加载 下拉刷新

与Recyclerview使用基本相同
导入依赖
implementation ‘com.android.support:recyclerview-v7:28.0.0’
api(‘com.jcodecraeer:xrecyclerview:1.5.9’) {
exclude group: ‘com.android.support’
}

布局(布局显示为灰色 不影响)

<?xml version="1.0" encoding="utf-8"?>
<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">

    <com.jcodecraeer.xrecyclerview.XRecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/my_recycler_view"
        android:background="#FFFFFF">

    </com.jcodecraeer.xrecyclerview.XRecyclerView>
</LinearLayout>

item布局

<?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"
    android:background="#E6DFDF"
    android:padding="10dp">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:scaleType="fitXY"
        android:id="@+id/item_img"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:id="@+id/item_txt"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="15sp"
        android:id="@+id/item_txt2"/>
</LinearLayout>

适配器

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

    ArrayList<HashMap<String,String>> arrayList;
    Context context;
    MyClickListener myClickListener;

    public MyAdapter(ArrayList<HashMap<String, String>> arrayList, Context context,MyClickListener myClickListener) {
        this.arrayList = arrayList;
        this.context = context;
        this.myClickListener = myClickListener;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view = View.inflate(context,R.layout.item,null);
        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, final int i) {
        myViewHolder.textView.setText(arrayList.get(i).get("title"));
        myViewHolder.textView2.setText(arrayList.get(i).get("intro"));
        Glide.with(context).load(arrayList.get(i).get("strUrl")).apply(RequestOptions.bitmapTransform(new RoundedCorners(20))).into(myViewHolder.imageView);
        myViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myClickListener.onItemClick(i);
            }
        });
    }

    @Override
    public int getItemCount() {
        return arrayList.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder{

        ImageView imageView;
        TextView textView,textView2;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.item_img);
            textView = itemView.findViewById(R.id.item_txt);
            textView2 = itemView.findViewById(R.id.item_txt2);
        }
    }
}

点击事件接口

public interface MyClickListener {
    void onItemClick(int i);
}

全局变量

public class MyApplication extends Application {
    String strUrl;
}

Activity

public class MainActivity extends AppCompatActivity {

    XRecyclerView recyclerView;
    ArrayList<HashMap<String,String>> arrayList;
    static int i = 1;
    @SuppressLint("HandlerLeak")
    Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 1001){
                myAdapter.notifyDataSetChanged();
                recyclerView.loadMoreComplete();
                recyclerView.refreshComplete();

            }
        }
    };
    MyAdapter myAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = findViewById(R.id.my_recycler_view);

        arrayList = new ArrayList<>();
        StaggeredGridLayoutManager manager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(manager);
        myAdapter= new MyAdapter(arrayList, MainActivity.this, new MyClickListener() {
            @Override
            public void onItemClick(int i) {
                MyApplication application = (MyApplication) MainActivity.this.getApplication();
                application.strUrl = arrayList.get(i).get("strUrl");
                Intent intent = new Intent(MainActivity.this, Main2Activity.class);
                startActivity(intent);
            }
        });
        recyclerView.setAdapter(myAdapter);
        getJson();
        // 可以设置是否开启加载更多/下拉刷新
        recyclerView.setLoadingMoreEnabled(true);
        recyclerView.setPullRefreshEnabled(true);
        // 如果设置上这个,下拉刷新的时候会显示上次刷新的时间
        recyclerView.getDefaultRefreshHeaderView() // get default refresh header view
                .setRefreshTimeVisible(true);  // make refresh time visible,false means hiding
        recyclerView.setLoadingListener(new XRecyclerView.LoadingListener() {
            @Override
            public void onRefresh() {
                i = 1;
                arrayList.clear();
                getJson();

            }

            @Override
            public void onLoadMore() {
                i++;
                getJson();

            }
        });
    }
    private void getJson(){
        OkGo.<String>get("https://www.apiopen.top/satinApi?type=1&page="+i).execute(new StringCallback() {
            @Override
            public void onSuccess(Response<String> response) {
                String body = response.body();
                try {
                    JSONObject jsonObject = new JSONObject(body);
                    JSONArray data = jsonObject.getJSONArray("data");
                    for (int i = 0; i < data.length(); i++){
                        JSONObject jsonObject1 = data.getJSONObject(i);
                        String name = jsonObject1.getString("name");
                        String text = jsonObject1.getString("text");
                        String strUrl = jsonObject1.getString("videouri");
                        if (strUrl.isEmpty()){
                            continue;
                        }
                        HashMap<String, String> map = new HashMap<>();
                        map.put("title",name);
                        map.put("intro",text);
                        map.put("strUrl",strUrl);
                        arrayList.add(map);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onFinish() {
                super.onFinish();
                handler.sendEmptyMessage(1001);

            }

            @Override
            public void onError(Response<String> response) {
                super.onError(response);
                Log.e("####",response.body()+"");
            }
        });
    }
}

跳转的Activity
布局

<?xml version="1.0" encoding="utf-8"?>
<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=".Main2Activity">
    <VideoView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/my_video_view"/>

</LinearLayout>
public class Main2Activity extends AppCompatActivity {

    VideoView videoView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        videoView = findViewById(R.id.my_video_view);
        MyApplication application = (MyApplication) getApplication();
        videoView.setVideoPath(application.strUrl);
        videoView.requestFocus();
        videoView.start();
        videoView.setMediaController(new MediaController(this));
    }
}

常用方法:
在这里插入图片描述

万能适配器

project中的gradle添加
maven {
url ‘https://jitpack.io
}
在这里插入图片描述

导入依赖
implementation ‘com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.42’
implementation ‘com.android.support:recyclerview-v7:28.0.0’

适配器

public class MyAdapter extends BaseQuickAdapter<Bean,BaseViewHolder> {

    private Context context;

    public MyAdapter(int layoutResId, @Nullable List<Bean> data,Context context) {
        super(layoutResId, data);
        this.context = context;
    }

    @Override
    protected void convert(BaseViewHolder helper, Bean item) {
        helper.setText(R.id.item_txt,item.getTitle());
        Glide.with(context).load(item.getImgUrl())
                .apply(RequestOptions.bitmapTransform(new CircleCrop()))
                .into((ImageView) helper.getView(R.id.item_img));
    }
}

Bean

public class Bean {
    private String title;
    private String imgUrl;

    public Bean(String title, String imgUrl) {
        this.title = title;
        this.imgUrl = imgUrl;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getImgUrl() {
        return imgUrl;
    }

    public void setImgUrl(String imgUrl) {
        this.imgUrl = imgUrl;
    }

    @Override
    public String toString() {
        return "Bean{" +
                "title='" + title + '\'' +
                ", imgUrl='" + imgUrl + '\'' +
                '}';
    }
}

Activity

public class MainActivity extends AppCompatActivity {

    RecyclerView recyclerView;
    MyAdapter myAdapter;
    ArrayList<Bean> arrayList = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = findViewById(R.id.my_recycler_view);
        getData();
        myAdapter = new MyAdapter(R.layout.item,arrayList,this);
        recyclerView.setAdapter(myAdapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
    }
    public void getData(){
        OkGo.<String>get("http://www.qubaobei.com/ios/cf/dish_list.php?stage_id=1&limit=20&page=1").execute(new StringCallback() {
            @Override
            public void onSuccess(Response<String> response) {
                String body = response.body();
                try {
                    JSONObject jsonObject = new JSONObject(body);
                    JSONArray data = jsonObject.getJSONArray("data");
                    for (int i = 0; i < data.length(); i++){
                        JSONObject jsonObject1 = data.getJSONObject(i);
                        String title = jsonObject1.getString("title");
                        String pic = jsonObject1.getString("pic");
                        Bean bean = new Bean(title, pic);
                        arrayList.add(bean);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                myAdapter.notifyDataSetChanged();
            }

            @Override
            public void onError(Response<String> response) {
                super.onError(response);
                Log.e("####",response.body());
            }
        });
    }
}

万能适配器介绍

使用ItemTouchHelper实现拖拽和侧滑删除

引用大佬博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值