自定義View–RecyclerView
使用RecyvlerView替代ListView依然是趨勢,它可以更好的顯示大量的數據,所以我們來自定義一個RecyclerView,讓它具有更多的使用功能。
自定義view的目的:
- 增加左滑顯示刪除按鈕
- 點擊刪除按鈕刪除這一條數據
首先自定義RecyclerView需要新建三個文件,FxRecycleListView.java,FxRecycleListViewAdapter.java,FxRecycleModel.java
FxRecycleListView.java
自定義RecyclerView,繼承RecyclerView
package com.felix.baselibrary.UI.recyclerview;
import android.content.Context;
import android.util.AttributeSet;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class FxRecycleListView extends RecyclerView {
public FxRecycleListView(@NonNull Context context) {
this(context, null);
}
public FxRecycleListView(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public FxRecycleListView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView(context, attrs);
}
private void initView(Context context, AttributeSet attrs) {
addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL));
setLayoutManager(new LinearLayoutManager(context));
}
}
沒做什麼特殊的處理,只是加入必要的兩行代碼,防止編寫時遺漏。這兩行代碼是寫RecyclerView必須加的兩行代碼
addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL));
setLayoutManager(new LinearLayoutManager(context));
FxRecycleModel.java
實體類,主要爲了給adapter數據
package com.felix.baselibrary.UI.recyclerview;
import android.content.Context;
import android.graphics.drawable.Drawable;
public class FxRecycleModel {
private static FxRecycleModel recycleModel;
private String title;
private String content;
private Drawable image;
private boolean isOpen = false;
public String getTitle() {
return title;
}
public String getContent() {
return content;
}
public Drawable getImageView() {
return image;
}
public boolean isOpen() {
return isOpen;
}
private FxRecycleModel() {
}
public static class Builder {
private String title = "";
private String content = "";
private Drawable image = null;
private boolean isOpen = false;
private Context mContext;
public Builder(Context context) {
mContext = context;
}
public FxRecycleModel create() {
recycleModel = new FxRecycleModel();
recycleModel.title = title;
recycleModel.content = content;
recycleModel.image = image;
recycleModel.isOpen = isOpen;
clearAll();
return recycleModel;
}
private void clearAll() {
title = "";
content = "";
image = null;
isOpen = false;
}
public Builder setTitle(String s) {
this.title = s;
return this;
}
public Builder setContent(String content) {
this.content = content;
return this;
}
public Builder setImageView(Drawable image) {
this.image = image;
return this;
}
public Builder setImageView(int imageSrc) {
this.image = mContext.getResources().getDrawable(imageSrc);
return this;
}
public Builder setOpen(boolean isOpen) {
this.isOpen = isOpen;
return this;
}
}
}
這裏用了建造者模式的設計模式。
新建實體類的方式:
FxRecycleModel.Builder builder = new FxRecycleModel.Builder(this);
FxRecycleModel model = builder.setTitle("123").setContent("456").setImageView(R.mipmap.ic_launcher).create();
FxRecycleListViewAdapter.java
關鍵的來啦,現在有了view和model了,需要寫adapter了。
package com.felix.baselibrary.UI.recyclerview;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import com.felix.baselibrary.R;
import java.util.ArrayList;
public class FxRecycleListViewAdapter extends RecyclerView.Adapter<FxRecycleListViewAdapter.FxRecyclerViewHolder> {
private static final String TAG = FxRecycleListViewAdapter.class.getSimpleName();
private int width;
private ArrayList<FxRecycleModel> models;
private Context mContext;
public FxRecycleListViewAdapter(Context context, ArrayList<FxRecycleModel> models) {
width = ((AppCompatActivity) context).getWindowManager().getDefaultDisplay().getWidth();
this.models = models;
this.mContext = context;
}
@NonNull
@Override
public FxRecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View root = View.inflate(parent.getContext(), R.layout.item_recycle_list, null);
return new FxRecyclerViewHolder(root);
}
@Override
public void onBindViewHolder(@NonNull final FxRecyclerViewHolder holder, final int position) {
FxRecycleModel model = models.get(position);
if (model.isOpen()) {
holder.itemView.scrollTo(holder.tvDelWidth, 0);
} else {
holder.itemView.scrollTo(0, 0);
}
holder.tvLine1.setVisibility(TextUtils.isEmpty(model.getTitle()) ? View.GONE : View.VISIBLE);
holder.tvLine1.setText(model.getTitle());
holder.tvLine2.setVisibility(TextUtils.isEmpty(model.getContent()) ? View.GONE : View.VISIBLE);
holder.tvLine2.setText(model.getContent());
if (model.getImageView() == null) {
holder.iv.setVisibility(View.GONE);
} else {
holder.iv.setVisibility(View.VISIBLE);
holder.iv.setBackground(model.getImageView());
}
ViewGroup.LayoutParams params = holder.rlItem.getLayoutParams();
params.width = width;
final int[] eventX = new int[2];
holder.itemView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
eventX[0] = (int) event.getX();
break;
case MotionEvent.ACTION_UP:
eventX[1] = (int) event.getX();
if (Math.abs(eventX[1] - eventX[0]) < 5) {
v.performClick();
}
int scrollX = holder.hsv.getScrollX();
Log.d(TAG, "onTouch: scrollX-> " + scrollX);
if (scrollX >= holder.tvDelWidth / 2) {
holder.hsv.post(new Runnable() {
@Override
public void run() {
holder.hsv.smoothScrollTo(holder.tvDelWidth, 0);
}
});
Log.d(TAG, "onTouch: scrollX2-> " + holder.hsv.getScrollX());
// mItemOpenedList.add(position + "");
} else {
holder.hsv.post(new Runnable() {
@Override
public void run() {
holder.hsv.smoothScrollTo(0, 0);
}
});
// mItemOpenedList.remove(position + "");
Log.d(TAG, "onTouch: scrollX3-> " + holder.hsv.getScrollX());
}
return true;
}
return false;
}
});
holder.tvDel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
holder.itemView.scrollTo(0, 0);
// mTitles.remove(position);
models.remove(position);
// mItemOpenedList.remove(position + "");
notifyDataSetChanged();
}
});
}
@Override
public int getItemCount() {
return models.size();
}
static class FxRecyclerViewHolder extends RecyclerView.ViewHolder {
final TextView tvLine1;
final TextView tvLine2;
final RelativeLayout rlItem;
final TextView tvDel;
final HorizontalScrollView hsv;
final int tvDelWidth;
final ImageView iv;
FxRecyclerViewHolder(@NonNull View itemView) {
super(itemView);
tvLine1 = itemView.findViewById(R.id.tv_item_list);
tvLine2 = itemView.findViewById(R.id.tv_item2_list);
tvDel = itemView.findViewById(R.id.tv_del);
rlItem = itemView.findViewById(R.id.rl_item);
hsv = itemView.findViewById(R.id.hsv);
tvDelWidth = tvDel.getLayoutParams().width;
iv = itemView.findViewById(R.id.iv_item_list);
}
}
public interface onDeleteButtonClickedListener {
void onDeleted();
}
}
重寫這個方法,是爲了將視圖和ViewHolder進行綁定
@NonNull
@Override
public FxRecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View root = View.inflate(parent.getContext(), R.layout.item_recycle_list, null);
return new FxRecyclerViewHolder(root);
}
內部類ViewHolder,初始化視圖中的控件。
static class FxRecyclerViewHolder extends RecyclerView.ViewHolder {
final TextView tvLine1;
final TextView tvLine2;
final RelativeLayout rlItem;
final TextView tvDel;
final HorizontalScrollView hsv;
final int tvDelWidth;
final ImageView iv;
FxRecyclerViewHolder(@NonNull View itemView) {
super(itemView);
tvLine1 = itemView.findViewById(R.id.tv_item_list);
tvLine2 = itemView.findViewById(R.id.tv_item2_list);
tvDel = itemView.findViewById(R.id.tv_del);
rlItem = itemView.findViewById(R.id.rl_item);
hsv = itemView.findViewById(R.id.hsv);
tvDelWidth = tvDel.getLayoutParams().width;
iv = itemView.findViewById(R.id.iv_item_list);
}
}
剩下的就是數據和視圖控件進行綁定顯示
@Override
public void onBindViewHolder(@NonNull final FxRecyclerViewHolder holder, final int position) {
//業務邏輯
}
todo :如何滑動顯示刪除按鈕,待補充