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的拖拽和側滑,下圖是實現效果