RecyclerView 在其下方滑动视图
RecyclerView Swipe with a view below it
我一直在做一些研究,但我还没有找到允许您在滑动时将视图(下面的示例图像)放在 RecyclerView 下方的示例或实现。有没有人有任何例子或想法如何 WITHOUT 使用库来实现。
下面是我实现滑动关闭的方法。
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
return super.getSwipeDirs(recyclerView, viewHolder);
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
if (viewHolder instanceof ViewDividers) {
Log.e("DIRECTION", direction + "");
}
}
};
new ItemTouchHelper(simpleItemTouchCallback).attachToRecyclerView(recycler);
以下是 Google 的收件箱示例:
我对如何做到这一点的理解是,将在 xml 中放置两个视图,这些视图将在您的回收视图中每行显示。
例如,这将是我的适配器:
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static class ExampleViewHolder extends RecyclerView.ViewHolder {
public TextView background;
public TextView foreground;
public ExampleViewHolder(View v) {
super(v);
background = (TextView) v.findViewById(R.id.background);
foreground = (TextView) v.findViewById(R.id.foreground);
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
if (holder instanceof ExampleViewHolder) {
((ExampleViewHolder) holder).background.setBackgroundColor(); // do your manipulation of background and foreground here.
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.example, parent, false);
return new ExampleViewHolder(v);
}
}
}
recyclerview 中的每一行都从 R.layout.example 拉取 xml 布局。因此,要在下方创建一个视图,您可以只使用 relativelayout 或 framelayout 在彼此之上创建视图:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/background"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/foreground"/>
</RelativeLayout>
然后如果你不想使用滑动库,你可以从 google 复制这个 class 并随后由 Bruno Romeu Nunes 修改:
class 将要求您创建滑动侦听器:
swipeTouchListener =
new SwipeableRecyclerViewTouchListener(mRecyclerView,
new SwipeableRecyclerViewTouchListener.SwipeListener() {
@Override
public boolean canSwipe(int position) {
if (position == totalPost.size() - 1 && !connected) {
return false;
}
return true;
}
@Override
public void onDismissedBySwipeLeft(RecyclerView recyclerView, int[] reverseSortedPositions) {
for (int position : reverseSortedPositions) {
//change some data if you swipe left
}
myAdapter.notifyDataSetChanged();
}
@Override
public void onDismissedBySwipeRight(RecyclerView recyclerView, int[] reverseSortedPositions) {
for (int position : reverseSortedPositions) {
//change some data if you swipe right
}
myAdapter.notifyDataSetChanged();
}
});
然后简单地 link 它与你的 recyclerview:
mRecyclerView.addOnItemTouchListener(swipeTouchListener);
我正在调查同样的问题。
我最终做的是,在包含 recyclerView 的布局中,我添加了一个名为 'swipe_bg' 的简单 FrameLayout
,其高度与我的 RecyclerView.ViewHolder
项目之一相同。我将其可见性设置为 "gone",并将其放在 RecyclerView
下
然后在我设置 ItemTouchHelper
的 activity 中,我像这样覆盖 onChildDraw ..
ItemTouchHelper.SimpleCallback swipeCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT) {
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
View itemView = viewHolder.itemView;
Imageview swipe_bg = itemView.findViewById(R.id.imageview_swipe_background);
swipe_bg.setY(itemView.getTop());
if (isCurrentlyActive) {
swipe_bg.setVisibility(View.VISIBLE);
} else {
swipe_bg.setVisibility(View.GONE);
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
};
不知道这是否是最好的方法,但似乎是最简单的方法。
我喜欢@erik 的方法,但我建议通过将 Canvas 传递给 onChildDraw() 函数来绘制您想要的内容。例如项目背景或图标。
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
final ColorDrawable background = new ColorDrawable(Color.RED);
background.setBounds(0, itemView.getTop(), itemView.getLeft() + dX, itemView.getBottom());
background.draw(c);
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
在这种方法中,您将按需绘制所需内容,无需扩充未使用的视图
您可以使用 RvTools Library。它将帮助您轻松实现您想要的。
只需创建具有所需外观的 SwipeContextMenuDrawer
public class YourSwipeContextMenuDrawer extends SwipeContextMenuDrawer {
private final Paint mRightPaint;
private final Paint mIconPaint;
private final Bitmap mRightIconBitmap;
public YourSwipeContextMenuDrawer(@NonNull Context context) {
mRightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mRightPaint.setColor(ContextCompat.getColor(context, R.color.deep_orange_400));
mRightIconBitmap = GraphicUtils.getBitmap(context, R.drawable.ic_delete, 100, 100);
mIconPaint = new Paint();
mIconPaint.setColorFilter(new PorterDuffColorFilter(ContextCompat.getColor(context, R.color.backgroundColor), PorterDuff.Mode.SRC_IN));
}
@Override
public void drawRight(@NonNull Canvas canvas, @NonNull View view) {
canvas.drawRect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom(), mRightPaint);
canvas.drawBitmap(mRightIconBitmap, view.getLeft() + mRightIconBitmap.getWidth() - 20, (view.getBottom() + view.getTop() - mRightIconBitmap.getHeight()) >> 1, mIconPaint);
}
@Override
public void drawLeft(@NonNull Canvas canvas, @NonNull View view) {
}
}
并像这样使用滑动操作和滑动上下文菜单抽屉创建 RvTools 实例
new RvTools.Builder(recyclerView)
.withSwipeRightAction(this)
.withSwipeContextMenuDrawer(new YourSwipeContextMenuDrawer(getContext()))
.buildAndApplyToRecyclerView();
无需分配或利用 canvas 的简单解决方案。 SomeAdapter.SomeVH
应包含上视图和下视图。通过这种方法,我们将能够仅滑动上视图(容器),在视图下显示(带有标签,任何你想要的图标)
class SomeTouchHelper extends ItemTouchHelper.Callback {
...
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
float dX, float dY, int actionState, boolean isCurrentlyActive) {
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
if (viewHolder instanceof SomeAdapter.SomeVH) {
SomeAdapter.SomeVH someViewHolder
= (SomeAdapter.SomeVH) viewHolder;
ViewCompat.setTranslationX(someViewHolder.mContainer, dX);
}
} else {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
}
...
}
附上
new ItemTouchHelper(SomeTouchHelper).attachToRecyclerView(recyclerView);
不要忘记在适配器 onViewRecycled()
中恢复 SomeVH
的初始视图状态
public void onViewRecycled(final SomeVH holder) {
if (holder.mContainer != null) {
holder.mContainer.setTranslationX(0);//restore position
}
}
更改 elevation
对我有用,可以将一项置于另一项之上。
我一直在做一些研究,但我还没有找到允许您在滑动时将视图(下面的示例图像)放在 RecyclerView 下方的示例或实现。有没有人有任何例子或想法如何 WITHOUT 使用库来实现。
下面是我实现滑动关闭的方法。
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
return super.getSwipeDirs(recyclerView, viewHolder);
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
if (viewHolder instanceof ViewDividers) {
Log.e("DIRECTION", direction + "");
}
}
};
new ItemTouchHelper(simpleItemTouchCallback).attachToRecyclerView(recycler);
以下是 Google 的收件箱示例:
我对如何做到这一点的理解是,将在 xml 中放置两个视图,这些视图将在您的回收视图中每行显示。
例如,这将是我的适配器:
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static class ExampleViewHolder extends RecyclerView.ViewHolder {
public TextView background;
public TextView foreground;
public ExampleViewHolder(View v) {
super(v);
background = (TextView) v.findViewById(R.id.background);
foreground = (TextView) v.findViewById(R.id.foreground);
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
if (holder instanceof ExampleViewHolder) {
((ExampleViewHolder) holder).background.setBackgroundColor(); // do your manipulation of background and foreground here.
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.example, parent, false);
return new ExampleViewHolder(v);
}
}
}
recyclerview 中的每一行都从 R.layout.example 拉取 xml 布局。因此,要在下方创建一个视图,您可以只使用 relativelayout 或 framelayout 在彼此之上创建视图:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/background"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/foreground"/>
</RelativeLayout>
然后如果你不想使用滑动库,你可以从 google 复制这个 class 并随后由 Bruno Romeu Nunes 修改:
class 将要求您创建滑动侦听器:
swipeTouchListener =
new SwipeableRecyclerViewTouchListener(mRecyclerView,
new SwipeableRecyclerViewTouchListener.SwipeListener() {
@Override
public boolean canSwipe(int position) {
if (position == totalPost.size() - 1 && !connected) {
return false;
}
return true;
}
@Override
public void onDismissedBySwipeLeft(RecyclerView recyclerView, int[] reverseSortedPositions) {
for (int position : reverseSortedPositions) {
//change some data if you swipe left
}
myAdapter.notifyDataSetChanged();
}
@Override
public void onDismissedBySwipeRight(RecyclerView recyclerView, int[] reverseSortedPositions) {
for (int position : reverseSortedPositions) {
//change some data if you swipe right
}
myAdapter.notifyDataSetChanged();
}
});
然后简单地 link 它与你的 recyclerview:
mRecyclerView.addOnItemTouchListener(swipeTouchListener);
我正在调查同样的问题。
我最终做的是,在包含 recyclerView 的布局中,我添加了一个名为 'swipe_bg' 的简单 FrameLayout
,其高度与我的 RecyclerView.ViewHolder
项目之一相同。我将其可见性设置为 "gone",并将其放在 RecyclerView
然后在我设置 ItemTouchHelper
的 activity 中,我像这样覆盖 onChildDraw ..
ItemTouchHelper.SimpleCallback swipeCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT) {
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
View itemView = viewHolder.itemView;
Imageview swipe_bg = itemView.findViewById(R.id.imageview_swipe_background);
swipe_bg.setY(itemView.getTop());
if (isCurrentlyActive) {
swipe_bg.setVisibility(View.VISIBLE);
} else {
swipe_bg.setVisibility(View.GONE);
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
};
不知道这是否是最好的方法,但似乎是最简单的方法。
我喜欢@erik 的方法,但我建议通过将 Canvas 传递给 onChildDraw() 函数来绘制您想要的内容。例如项目背景或图标。
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
final ColorDrawable background = new ColorDrawable(Color.RED);
background.setBounds(0, itemView.getTop(), itemView.getLeft() + dX, itemView.getBottom());
background.draw(c);
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
在这种方法中,您将按需绘制所需内容,无需扩充未使用的视图
您可以使用 RvTools Library。它将帮助您轻松实现您想要的。
只需创建具有所需外观的 SwipeContextMenuDrawer
public class YourSwipeContextMenuDrawer extends SwipeContextMenuDrawer {
private final Paint mRightPaint;
private final Paint mIconPaint;
private final Bitmap mRightIconBitmap;
public YourSwipeContextMenuDrawer(@NonNull Context context) {
mRightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mRightPaint.setColor(ContextCompat.getColor(context, R.color.deep_orange_400));
mRightIconBitmap = GraphicUtils.getBitmap(context, R.drawable.ic_delete, 100, 100);
mIconPaint = new Paint();
mIconPaint.setColorFilter(new PorterDuffColorFilter(ContextCompat.getColor(context, R.color.backgroundColor), PorterDuff.Mode.SRC_IN));
}
@Override
public void drawRight(@NonNull Canvas canvas, @NonNull View view) {
canvas.drawRect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom(), mRightPaint);
canvas.drawBitmap(mRightIconBitmap, view.getLeft() + mRightIconBitmap.getWidth() - 20, (view.getBottom() + view.getTop() - mRightIconBitmap.getHeight()) >> 1, mIconPaint);
}
@Override
public void drawLeft(@NonNull Canvas canvas, @NonNull View view) {
}
}
并像这样使用滑动操作和滑动上下文菜单抽屉创建 RvTools 实例
new RvTools.Builder(recyclerView)
.withSwipeRightAction(this)
.withSwipeContextMenuDrawer(new YourSwipeContextMenuDrawer(getContext()))
.buildAndApplyToRecyclerView();
无需分配或利用 canvas 的简单解决方案。 SomeAdapter.SomeVH
应包含上视图和下视图。通过这种方法,我们将能够仅滑动上视图(容器),在视图下显示(带有标签,任何你想要的图标)
class SomeTouchHelper extends ItemTouchHelper.Callback {
...
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
float dX, float dY, int actionState, boolean isCurrentlyActive) {
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
if (viewHolder instanceof SomeAdapter.SomeVH) {
SomeAdapter.SomeVH someViewHolder
= (SomeAdapter.SomeVH) viewHolder;
ViewCompat.setTranslationX(someViewHolder.mContainer, dX);
}
} else {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
}
...
}
附上
new ItemTouchHelper(SomeTouchHelper).attachToRecyclerView(recyclerView);
不要忘记在适配器 onViewRecycled()
中恢复SomeVH
的初始视图状态
public void onViewRecycled(final SomeVH holder) {
if (holder.mContainer != null) {
holder.mContainer.setTranslationX(0);//restore position
}
}
更改 elevation
对我有用,可以将一项置于另一项之上。