高級UI-RecyclerView拖拽和側滑

RecyclerView強大的地方在於高度的可定製,正式由於此優點,現在的項目大多使用RecyclerView,這裏我們仿照QQ的功能,實現RecyclerView的拖拽和側滑功能

功能說明

上下拖拽,實現Item的交換
左右側滑,實現Item的刪除
在此基礎上,增加額外的一些交互功能

實現過程

首先模擬數據,需要一個bean文件來存儲數據

public class MyMessage {
    private int logo;
    private String name;
    private String lastMsg;
    private String time;

    public MyMessage(int logo, String name, String lastMsg, String time) {
        this.logo = logo;
        this.name = name;
        this.lastMsg = lastMsg;
        this.time = time;
    }

    public int getLogo() {
        return logo;
    }

    public void setLogo(int logo) {
        this.logo = logo;
    }

    public String getName() {
        return name;
    }

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

    public String getLastMsg() {
        return lastMsg;
    }

    public void setLastMsg(String lastMsg) {
        this.lastMsg = lastMsg;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    @Override
    public String toString() {
        return "MyMessage [logo=" + logo + ",name=" + name +
                ",lastMsg=" + lastMsg + ",time=" + time + "]";
    }
}

然後準備數據,這裏直接使用靜態方法模擬出數據

public class DataUtils {
    public static List<MyMessage> init(){
        List<MyMessage> list = new ArrayList<MyMessage>();
        list.add(new MyMessage(R.drawable.logo, "測試一號", "測試內容","01:34"));
        list.add(new MyMessage(R.drawable.logo, "測試二號", "測試內容","09:41"));
        list.add(new MyMessage(R.drawable.logo, "測試三號", "測試內容","11:28"));
        list.add(new MyMessage(R.drawable.logo, "測試四號", "測試內容","12:22"));
        list.add(new MyMessage(R.drawable.logo, "測試五號", "測試內容","15:25"));
        list.add(new MyMessage(R.drawable.logo, "測試六號", "測試內容","17:22"));
        list.add(new MyMessage(R.drawable.logo, "測試七號", "測試內容","19:59"));
        list.add(new MyMessage(R.drawable.logo, "測試八號", "測試內容","20:17"));
        list.add(new MyMessage(R.drawable.logo, "測試九號", "測試內容","22:30"));
        list.add(new MyMessage(R.drawable.logo, "測試十號", "測試內容","23:01"));
        return list;
    }
}

添加動作刷新回調接口

public interface ItemTouchMoveListener {
    //拖拽回調,拖拽效果刷新
    boolean onItemMove(int fromPosition,int toPosition);
    //側滑回調,側滑效果刷新
    boolean onItemRemove(int position);
}

添加拖拽回調接口

public interface StartDragListener {
    void onStartDrag(ViewHolder viewHolder);
}

實現適配器,複寫需要的方法

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> implements ItemTouchMoveListener{
    private StartDragListener dragListener;
    private List<MyMessage> list;

    public MyAdapter(StartDragListener dragListener, List<MyMessage> list) {
        this.list = list;
        this.dragListener = dragListener;
    }

    @Override
    public boolean onItemMove(int fromPosition, int toPosition) {
        //數據交換
        Collections.swap(list,fromPosition,toPosition);
        //刷新
        notifyItemMoved(fromPosition,toPosition);
        return true;
    }

    @Override
    public boolean onItemRemove(int position) {
        //刪除數據
        list.remove(position);
        //刷新界面
        notifyItemRemoved(position);
        return true;
    }

    class MyViewHolder extends RecyclerView.ViewHolder {
        private ImageView iv_logo;
        private TextView tv_name;
        private TextView tv_msg;
        private TextView tv_time;

        public MyViewHolder(View itemView) {
            super(itemView);
            iv_logo = (ImageView) itemView.findViewById(R.id.iv_logo);
            tv_name = (TextView) itemView.findViewById(R.id.tv_name);
            tv_msg = (TextView) itemView.findViewById(R.id.tv_lastMsg);
            tv_time = (TextView) itemView.findViewById(R.id.tv_time);
        }
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
        View view = layoutInflater.inflate(R.layout.item_list, parent, false);
        MyViewHolder holder = new MyViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, int position) {
        MyMessage message = list.get(position);
        holder.iv_logo.setImageResource(message.getLogo());
        holder.tv_name.setText(message.getName());
        holder.tv_msg.setText(message.getLastMsg());
        holder.tv_time.setText(message.getTime());
        //監聽logo觸摸事件,使用觸摸拖拽
        holder.iv_logo.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    //傳遞給callback
                    dragListener.onStartDrag(holder);
                }
                return false;
            }
        });
    }

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

處理回調動作的callback

public class MyItemTouchHelperCallback extends Callback {

    private static final String TAG = "MyItemTouchHelperCallba";
    private ItemTouchMoveListener moveListener;

    public MyItemTouchHelperCallback(ItemTouchMoveListener moveListener) {
        this.moveListener = moveListener;
    }

    //先回調,用來判斷當前動作
    @Override
    public int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder) {
        //監聽拖拽方向
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        //監聽側滑方向
        int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
        int flags = makeMovementFlags(dragFlags, swipeFlags);
        return flags;
    }

    @Override
    public boolean isLongPressDragEnabled() {
        //是否允許長按拖拽
        return true;
    }

    //移動時候回調
    @Override
    public boolean onMove(RecyclerView recyclerView, ViewHolder viewHolder, ViewHolder target) {
        //調用adapter.notifyItemMoved(from,to)方法,刷新界面
        if (viewHolder.getItemViewType() != target.getItemViewType()) {
            return false;
        }
        //交換
        boolean result = moveListener.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
        return result;
    }

    //側滑時候回調
    @Override
    public void onSwiped(ViewHolder viewHolder, int direction) {
        //刪除數據
        moveListener.onItemRemove(viewHolder.getAdapterPosition());
    }

    //選中的狀態
    @Override
    public void onSelectedChanged(ViewHolder viewHolder, int actionState) {
        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
            viewHolder.itemView.setBackgroundColor(Color.BLUE);
        }
        super.onSelectedChanged(viewHolder, actionState);
    }

    //恢復
    @Override
    public void clearView(RecyclerView recyclerView, ViewHolder viewHolder) {
        viewHolder.itemView.setBackgroundColor(Color.WHITE);
        super.clearView(recyclerView, viewHolder);
    }

    //拖拽側滑特效
    @Override
    public void onChildDraw(Canvas c, RecyclerView recyclerView, ViewHolder viewHolder,
                            float dX, float dY, int actionState, boolean isCurrentlyActive) {
        float alpha = 1 - Math.abs(dX) / viewHolder.itemView.getWidth();
		if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
            //透明度,XY縮放
            viewHolder.itemView.setAlpha(alpha);
            //viewHolder.itemView.setScaleX(alpha);
            //viewHolder.itemView.setScaleY(alpha);
        }
        if (alpha == 0) {
            viewHolder.itemView.setAlpha(1);
			//viewHolder.itemView.setScaleX(1);
            //viewHolder.itemView.setScaleY(1);
        }
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    }
}

在主活動中調用

public class MainActivity extends AppCompatActivity implements StartDragListener {

    private RecyclerView recyclerView;
    private ItemTouchHelper itemTouchHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        List<MyMessage> list = DataUtils.init();
        MyAdapter adapter = new MyAdapter(this, list);
        recyclerView.setAdapter(adapter);
        ItemTouchHelper.Callback callback = new MyItemTouchHelperCallback(adapter);
        itemTouchHelper = new ItemTouchHelper(callback);
        itemTouchHelper.attachToRecyclerView(recyclerView);
    }

    @Override
    public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
        itemTouchHelper.startDrag(viewHolder);
    }
}

至此便完成了RecycleView的拖拽和側滑,下圖是實現效果
RecyclerView拖拽和側滑-初步實現

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