RecyclerView Swipe avec une vue en dessous de lui
j'ai fait quelques recherches et je n'ai pas encore trouvé un exemple ou une implémentation qui vous permette de mettre une vue (Image D'exemple ci-dessous) sous le RecyclerView quand vous glissez. Est-ce que quelqu'un a un exemple ou une idée de la façon dont cela serait mis en œuvre sans utiliser une bibliothèque.
Voici comment je suis en train de mettre en œuvre le coup à rejeter.
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);
5 réponses
ma compréhension de la façon dont cela est fait est que l'on mettrait deux vues dans le xml qui seraient affichées par ligne dans votre recyclerview.
alors par exemple, ce serait mon adaptateur:
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);
}
}
}
chaque ligne de recyclerview tire la mise en page xml de R. layout.exemple. Par conséquent, pour créer une vue en dessous, vous pouvez juste utiliser relativelayout ou framelayout pour créer les vues les uns sur les autres:
<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>
Alors si vous ne voulez pas utiliser un bibliothèque pour le balayage, vous pouvez copier cette classe à partir de google et ensuite modifié par Bruno Romeu Nunes:
La classe va vous demander de créer un balayage auditeur:
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();
}
});
alors liez simplement avec votre recyclerview:
mRecyclerView.addOnItemTouchListener(swipeTouchListener);
j'enquêtais sur la même question.
Ce que j'ai fini par faire était, dans la mise en page qui contenait le recyclerView, j'ai ajouté un simple FrameLayout
appelé "swipe_bg" de la même hauteur que l'un de mes RecyclerView.ViewHolder
éléments. J'ai placé sa visibilité à "parti", et je l'ai placée sous le RecyclerView
puis dans mon activité où je mets le ItemTouchHelper
, je remplace la onChildDraw comme si..
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;
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);
}
};
Je ne sais pas si c'est la meilleure façon, mais ça m'a semblé la plus simple.
j'aime l'approche @erik mais je recommande de dessiner ce que vous voulez via la fonction Canvas passé à onChildDraw (). par exemple, un élément en arrière-plan ou une icône.
@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);
}
dans cette approche, vous tirerez ce qui est nécessaire sur demande et pas besoin de gonfler les vues inutilisées
solution Simple sans répartition ou dessin sur toile. SomeAdapter.SomeVH
devrait contenir la vue supérieure et la vue inférieure. Et avec cette approche nous serons en mesure de glisser seulement la vue supérieure (conteneur), en exposant sous la vue (avec étiquette, icône ce que vous voulez)
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);
}
}
...
}
n'oubliez pas de restaurer l'état de vue initial de SomeVH
en Adaptateur onViewRecycled ()
Vous pouvez utiliser RvTools Bibliothèque. Il vous aidera à mettre en application facilement ce que vous voulez.
il suffit de créer votre SwipeContextMenuDrawer avec le regard désiré
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) {
}
}
Et créer RvTools exemple avec l'action de balayage et balayez vers le menu contextuel de ce tiroir
new RvTools.Builder(recyclerView)
.withSwipeRightAction(this)
.withSwipeContextMenuDrawer(new YourSwipeContextMenuDrawer(getContext()))
.buildAndApplyToRecyclerView();