自定義View--RecyclerView

自定義View–RecyclerView

使用RecyvlerView替代ListView依然是趨勢,它可以更好的顯示大量的數據,所以我們來自定義一個RecyclerView,讓它具有更多的使用功能。

自定義view的目的:

  1. 增加左滑顯示刪除按鈕
  2. 點擊刪除按鈕刪除這一條數據

在這裏插入圖片描述

首先自定義RecyclerView需要新建三個文件,FxRecycleListView.javaFxRecycleListViewAdapter.javaFxRecycleModel.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 :如何滑動顯示刪除按鈕,待補充

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章