实现删除文件夹收藏功能。
神马笔记最新版本:【神马笔记 版本1.3.0.apk】
我们需要在普通状态和编辑状态下,均可以移除文件夹收藏。
参考《RecyclerView使用ItemTouchHelper实现拖拽排序》一文,介绍了如何使用ItemTouchHelper
以及通过实现ItemTouchHelper.Callback
实现侧滑删除功能。
因为ItemTouchHelper
是对ViewHolder
的itemView
设置translationX
实现滑动。
这样会导致列表项控件整体移动,因此,需要做一些定制才能完成功能设计。
这里,使用了SwipeActionHelper
来完成这个工作。
你可以在WhatsAndroid项目中找到这份代码。
GitHub项目地址:https://github.com/jicanghai37927/WhatsAndroid
public interface Adapter {
boolean isSwiped(SwipeActionHelper helper);
Adapter getActive(SwipeActionHelper helper);
int getDirection(SwipeActionHelper helper);
View getSwipeView(SwipeActionHelper helper);
List<View> getTouchable(SwipeActionHelper helper);
void clear(SwipeActionHelper helper);
void onBegin(SwipeActionHelper helper);
void onMove(SwipeActionHelper helper, float deltaX);
void onEnd(SwipeActionHelper helper, float velocityX);
void onDraw(SwipeActionHelper helper, Canvas canvas);
void onDrawOver(SwipeActionHelper helper, Canvas canvas);
void onActionBegin(SwipeActionHelper helper, int action);
void onActionEnd(SwipeActionHelper helper, int action);
void onClear(SwipeActionHelper helper, int direction);
}
子类ViewHolder
需要实现Adapter
接口,完成SwipeActionHelper
与ViewHolder
之间的通信。
public abstract class SwipeViewHolder<T> extends BridgeViewHolder<T> implements SwipeActionHelper.Adapter, MarginDividerDecoration.Adapter {
}
提供了SwipeActionHelper.Adapter
的实现。
public class SwipeHolder {
View container;
View swipeView;
boolean isDrag;
SwipeRunner activeRunner;
ArrayList<SwipeRunner> list;
Rect bounds = new Rect();
SwipeActionHelper helper;
}
横向滑动的容器。
定义了具体的滑动功能,目前支持5种滑动模式。
SwipeRunner子类 | 滑动行为 |
---|---|
DeleteRunner | 支持右侧删除按钮 |
RightDeleteRunner | 支持右侧删除及菜单 |
RightActionRunner | 支持右侧菜单 |
SnapRightRunner | 支持按钮吸附在右侧 |
SnapLeftRunner | 支持按钮吸附在左侧 |
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorWindowBackground">
<FrameLayout
android:id="@+id/btn_delete"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_red_light"
android:foreground="?selectableItemBackground">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:layout_gravity="left"
android:paddingLeft="24dp"
android:paddingRight="24dp"
android:text="移除"
android:textStyle="bold"
android:textColor="@android:color/white"
android:textAppearance="@style/TextAppearance.AppCompat.Button"/>
FrameLayout>
<LinearLayout
android:id="@+id/swipe_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="@dimen/entranceItemHeight"
android:paddingLeft="?listPreferredItemPaddingLeft"
android:paddingRight="?listPreferredItemPaddingRight"
android:background="@color/colorWindowBackground"
android:foreground="?selectableItemBackground"
android:clipToPadding="false"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_gravity="center">
<ImageView
android:id="@+id/btn_remove"
android:layout_width="28dp"
android:layout_height="28dp"
android:src="@drawable/ic_remove_circle_white_24dp"
android:tint="@android:color/holo_red_light"
android:scaleType="centerInside"
android:layout_gravity="left|center_vertical"
android:visibility="gone"
android:layout_marginRight="?listPreferredItemPaddingRight"/>
<ImageView
android:id="@+id/iv_icon"
android:layout_marginRight="?listPreferredItemPaddingRight"
android:layout_width="28dp"
android:src="@drawable/ic_folder_white_24dp"
android:tint="@color/colorFolder"
android:layout_height="28dp"/>
<TextView
android:id="@+id/tv_name"
android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:singleLine="true"
android:layout_weight="1"/>
<ImageView
android:id="@+id/btn_drag"
android:layout_width="28dp"
android:layout_height="28dp"
android:src="@drawable/ic_drag_handle_white_24dp"
android:tint="@color/colorDrag"
android:scaleType="centerInside"
android:visibility="gone"
android:layout_gravity="right|center_vertical"
android:layout_marginLeft="?listPreferredItemPaddingLeft"/>
LinearLayout>
FrameLayout>
注意移除按钮的定义方式,必须使用FrameLayout作为外层容器。
this.swipeActionHelper = new SwipeActionHelper();
swipeActionHelper.setOnSwipeActionListener(new SwipeActionListener());
swipeActionHelper.attach(recyclerView);
SwipeHolder swipeHolder = new SwipeHolder(parent.swipeActionHelper, view, view.findViewById(R.id.swipe_view));
{
View btnAction = view.findViewById(R.id.btn_delete);
btnAction.setOnClickListener(this::onDeleteClick);
DeleteRunner r = new DeleteRunner();
r.add(btnAction);
swipeHolder.add(r);
}
this.setSwipeHolder(swipeHolder);
使用DeleteRunner
来实现侧滑动能。
public class RemoveDecoration extends RecyclerView.ItemDecoration {
ArrayList<RemoveInfo> list;
public RemoveDecoration(Context context) {
this.list = new ArrayList<>();
}
public void add(Drawable d, long duration) {
this.list.add(new RemoveInfo(d, System.currentTimeMillis() + duration));
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
{
drawVertical(c, parent, state);
}
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
}
void drawVertical(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
if (parent.getLayoutManager() == null) {
return;
}
canvas.save();
{
final int left;
final int right;
//noinspection AndroidLintNewApi - NewApi lint fails to handle overrides.
if (parent.getClipToPadding()) {
left = parent.getPaddingLeft();
right = parent.getWidth() - parent.getPaddingRight();
canvas.clipRect(left, parent.getPaddingTop(), right,
parent.getHeight() - parent.getPaddingBottom());
}
}
{
long time = System.currentTimeMillis();
for (int i = list.size() - 1; i >= 0; i--) {
RemoveInfo info = list.get(i);
if (time >= info.expire) {
list.remove(i);
}
}
}
{
for (RemoveInfo info: list) {
info.drawable.draw(canvas);
}
}
canvas.restore();
}
/**
*
*/
private static class RemoveInfo {
Drawable drawable;
long expire;
RemoveInfo(Drawable d, long time) {
this.drawable = d;
this.expire = time;
}
}
}
通过RemoveDecoration
实现列表项被移除时的红色背景。
以王维的诗句结束这篇文章。
~随意春芳歇~王孙自可留~