zoukankan      html  css  js  c++  java
  • RecyclerView实现一个页面有多种item,每个item有多个view,并且可以让任意item的任意view自定义监听,通过接口方法进行触发操作

    百度了很多贴子,看着大佬的博客,模仿尝试,最终都是以失败告终,api可能版本不一样,

    毕竟博客大佬都是7~8前写的,日期新点的都是好几年前了,多次尝试,还是报出莫名其妙的错。

        哎,忧伤。

    翻阅各种资料,看了将近30多篇各种网站的贴子,从一开始的茫然,变成现在从容,因为我终于摸索出适合自己的方法了,

    我要把完整的代码贴出来,供小白参考,不要再像我这样掉坑里了。

    看效果图,看看是不是你要的效果

    话不多说,我直接把完整的代码贴出来,

    需要创建一个这样的泛型类出来装数据格式

    package util;

    public class ChatTwoType {
    public static final int TYPE_ONE = 1;//类型1
    public static final int TYPE_TWO = 2;//类型2
    public int type;//item内容 类型
    public int icon;
    public String username;
    public String message;

    public ChatTwoType(int type, int icon, String username, String message){
    this.type = type;
    this.icon = icon;
    this.username = username;
    this.message = message;
    }



    public static int getTypeOne() {
    return TYPE_ONE;
    }

    public static int getTypeTwo() {
    return TYPE_TWO;
    }

    public int getType() {
    return type;
    }

    public void setType(int type) {
    this.type = type;
    }

    public int getIcon() {
    return icon;
    }

    public void setIcon(int icon) {
    this.icon = icon;
    }

    public String getUsername() {
    return username;
    }

    public void setUsername(String username) {
    this.username = username;
    }

    public String getMessage() {
    return message;
    }

    public void setMessage(String message) {
    this.message = message;
    }
    }

    然后,新建一个新的空的MainActivity和xml出来,最好用gradle,会自动帮你配置文件

    xml文件如下:

    <?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"
    android:background="@drawable/timg_2"
    android:orientation="vertical"
    tools:context=".MainTwoTypeAdaper">

    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="7">

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

    </LinearLayout>

    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="70dp"

    android:background="#FCFAFA">
    <Button
    android:id="@+id/b2"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_margin="10dp"
    android:layout_weight="1"
    android:text="换边" />

    <EditText
    android:id="@+id/t1"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_margin="10dp"
    android:layout_weight="3" />

    <Button
    android:id="@+id/b1"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_margin="10dp"
    android:layout_weight="1"
    android:text="发送" />


    </LinearLayout>


    </LinearLayout>
    效果如下图:

    
    

     现在要去设置item啦,虽然是有多个不同的item,但是,实际是将所有都放在一个xml文件里,我新建了个xml文件,文件名为item1.xml,名字随便取,记得是哪个就行

    item1.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"
    android:orientation="vertical"
    android:padding="10dp"
    >
    <!--padding是在控件内部的,margin是在控件外部的-->
    <LinearLayout
    android:id="@+id/iteml"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="left">

    <LinearLayout
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:layout_gravity="top"
    >
    <ImageView
    android:id="@+id/item1i"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"


    />
    </LinearLayout>
    <LinearLayout
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="4"
    android:padding="10dp">
    <TextView
    android:id="@+id/item1t"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/chat3"
    android:gravity="center"
    />
    </LinearLayout>
    <LinearLayout
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1" />
    </LinearLayout>











    <LinearLayout
    android:id="@+id/itemr"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="right"

    >

    <LinearLayout
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1" />


    <LinearLayout
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="4"
    android:padding="10dp"
    android:layout_gravity="right"
    android:gravity="right"
    >
    <TextView
    android:id="@+id/item2t"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"

    android:background="@drawable/chat3"
    android:gravity="center" />
    </LinearLayout>




    <LinearLayout
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:layout_gravity="top"
    >
    <ImageView
    android:id="@+id/item2i"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:gravity="center" />
    </LinearLayout>


    </LinearLayout>


    </LinearLayout>
    效果如下图:

    看看activity处的代码:

    package com.example.love5;

    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.text.TextUtils;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Button;
    import android.widget.ImageView;
    import android.widget.TextView;
    import android.widget.Toast;

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

    import util.ChatAdaper;
    import util.ChatTwoType;
    import util.Myada;

    public class MainTwoTypeAdaper extends AppCompatActivity implements ChatAdaper.OnRecyclerItemClickListener{
    private RecyclerView recyclerView;
    private ChatAdaper adapter;
    private List<ChatTwoType> list;
    Button b1,b2;
    TextView t1;
    //识别是接收还是发送
    private int user = 2;
    private int rp = R.drawable.xiaren;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main_two_type_adaper);
    //实列父view
    recyclerView = findViewById(R.id.r1);

    //实列化list
    list = new ArrayList<>();
    for (int i = 0 ; i < 20;i++){

    // 加入初始数据,可以不加
    list.add(new ChatTwoType(1, R.drawable.coffee, "cen", "吃饭没?\n\n\n5533\n44534"));
    list.add(new ChatTwoType(2, R.drawable.xiaren, "666", "吃了,你呢"));

    }

    //垂直布局,默认底下添加
    LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
    recyclerView.setLayoutManager(layoutManager);

    //实列适配并且赋值,具体参数需要对应适配器方法里的参数顺序
    adapter = new ChatAdaper(list);
    //这是适配器的接口监听,如果没有,则会报错接口空指针异常
    adapter.setOnRecyclerItemClickListener(this);

    recyclerView.setAdapter(adapter);

    t1 =findViewById(R.id.t1);
    b1 = findViewById(R.id.b1);
    b1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    if(!TextUtils.isEmpty(t1.getText())){

    ChatTwoType c = new ChatTwoType(user,rp,"666",t1.getText().toString());
    list.add(c);
              //插入新数据,默认是参数就是要插入的位置,因为item排列的下标由0开始递增,所以要减一,如果想插入顶上,参数改成零就可以了

    adapter.notifyItemInserted(list.size()-1);
              //滚动到最底下,//若要滚动到顶上则把参数改成零就可以了

    recyclerView.scrollToPosition(list.size()-1);
              //编辑框清空
                
    t1.setText("");
                    }
    }
    });

    b2 = findViewById(R.id.b2);
    b2.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    // 换成接收
    if(user == 2){
    // 换成接收
    rp = R.drawable.coffee;
    user = 1;

    }else if(user == 1){
    //换成发送
    rp = R.drawable.xiaren;
    user = 2;
    }

    }
    });



    }

    private ImageView imageView,imageView2;
    //用来实现item的头像图片宽与高大小相等,,获取任何view的宽高都要使用onWindowFocusChanged,否则获取的数据为null
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    imageView = findViewById(R.id.item1i);
    int width = imageView.getWidth();
    int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    imageView.measure(w, h);
    ViewGroup.LayoutParams params = imageView.getLayoutParams();
    int height = width;
    params.height = height;
    imageView.setLayoutParams(params);

    imageView2 = findViewById(R.id.item2i);
    imageView2.setLayoutParams(params);
    }


    //使用接口里的方法
    public void a55(int u){
    if(u == 1){
    Toast.makeText(getApplicationContext(),"这是对方头像",Toast.LENGTH_SHORT).show();
    }else {
    Toast.makeText(getApplicationContext(),"这是我的头像",Toast.LENGTH_SHORT).show();
    }


    }
    }



    最后关键的一步,就是适配器的设置
    代码如下:
    package util;

    import android.content.Context;
    import android.support.annotation.NonNull;
    import android.support.v7.widget.RecyclerView;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.AdapterView;
    import android.widget.ImageView;
    import android.widget.LinearLayout;
    import android.widget.TextView;

    import com.example.love5.R;

    import java.util.List;


    public class ChatAdaper extends RecyclerView.Adapter<ChatAdaper.ViewHolder> {
    private List<ChatTwoType> list;//数据源


    //实列化所有item的所有控件,包括布局实列化
    static class ViewHolder extends RecyclerView.ViewHolder {

    LinearLayout leftlayout;
    LinearLayout rightlayout;
    TextView lefttext;
    TextView righttext;
    ImageView lefyim;
    ImageView rightim;

    public ViewHolder(View view) {
    super(view);
    leftlayout = view.findViewById(R.id.iteml);
    lefttext = view.findViewById(R.id.item1t);
    lefyim = view.findViewById(R.id.item1i);
    rightlayout = view.findViewById(R.id.itemr);
    righttext = view.findViewById(R.id.item2t);
    rightim = view.findViewById(R.id.item2i);
    }
    }

    //activity传进来的数据,参数可以根据需要修改,需要context才传,不用则不传,参数与在activity实列适配器的参数对应
    public ChatAdaper(List<ChatTwoType> list) {
    this.list = list;
    Log.d("ChatAdaper", "============" + list.get(0).getMessage());

    }


    //计算有多少个item
    @Override
    public int getItemCount() {
    return list == null ? 0 : list.size();
    }

    //获取item并实列ViewHolder,把所有触发事件监控写出来,然后调用接口的方法执行你要做的事情,一般是用来传值到context然后再处理
    @Override
    public ChatAdaper.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    //parent.getContext()可用context替换,前提是context需要由activity传进来
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item1, parent, false);


    final ViewHolder holder =new ViewHolder(view);
    holder.lefyim.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    Log.d("ChatAdaper","7777777777777777777777");
    listener.a55(1);
    }
    });

    holder.rightim.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    Log.d("ChatAdaper","444444444444444444444444444444444444477");
    listener.a55(2);
    }
    });
    return holder;
    }



    //绑定控件根据泛型类型的参数类型判断哪个布局显示,并将该布局的所有控件绑定相应的数据,不要的布局item一定要隐藏
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
    ChatTwoType chatTwoType = list.get(position);
    if (chatTwoType.getType() == ChatTwoType.TYPE_ONE) {
    //收到的消息

    //item布局显示
    holder.leftlayout.setVisibility(View.VISIBLE);
    //item布局隐藏
    holder.rightlayout.setVisibility(View.GONE);
    // 控件绑定相应的数据
    holder.lefyim.setImageResource(chatTwoType.getIcon());
    holder.lefttext.setText(chatTwoType.getMessage());

    } else if (chatTwoType.getType() == ChatTwoType.TYPE_TWO) {
    //item布局显示
    holder.rightlayout.setVisibility(View.VISIBLE);
    //item布局隐藏
    holder.leftlayout.setVisibility(View.GONE);
    // 控件绑定相应的数据
    holder.rightim.setImageResource(chatTwoType.getIcon());
    holder.righttext.setText(chatTwoType.getMessage());
    }


    }



    //自定义实列
    private ChatAdaper.OnRecyclerItemClickListener listener;
    //实列接口setOnRecyclerItemClickListener要在activity的适配器实列后设置,用来给接口实列,如果没有会报空指针
    public void setOnRecyclerItemClickListener(ChatAdaper.OnRecyclerItemClickListener listener) {
    this.listener = listener;
    }
    //自定义接口名称,然后自定义接口里的方法,方法用于适配器监听触发调用,具体的方法内容在activity里,一般是用来从适配器传输数据到activity去,然后在activity里执行操作
    public interface OnRecyclerItemClickListener {
    //这里是适配器调用的方法可以返回值给activity,可以自定义
    void a55(int u);
    }


    }






























    
    
    
  • 相关阅读:
    Android性能调优实例
    Android移动端网络优化
    性能优化之Java(Android)代码优化
    Android性能优化之布局优化
    Android性能优化之数据库优化
    Android性能优化系列总篇
    ViewGroup的事件分发机制
    Apk大瘦身
    不安装APK直接启动应用
    Intent详解
  • 原文地址:https://www.cnblogs.com/c2g5201314/p/10554190.html
Copyright © 2011-2022 走看看