百度了很多貼子,看着大佬的博客,模仿嘗試,最終都是以失敗告終,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);
}
}