Reputation: 3084
I implemented Recycler
swipe effect by ItemTouchHelper.SimpleCallback
and put some buttons on the back view which shows after swiping. the funny problem is that when I clicked button the don't work. I should press them twice and in the third try they work!!! this is a gif:
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0,
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT ) {
@Override
public int getMovementFlags(RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder) {
int dragFlags = 0;
int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
return makeMovementFlags(dragFlags, swipeFlags);
}
@Override
public boolean isItemViewSwipeEnabled() {
return true;
}
@Override
public boolean isLongPressDragEnabled() {
return false;
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
((InvoiceItemListAdapter.ViewHolder)viewHolder).lunchSwipeLeftEffect(dX);
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
}
};
recentInvoicesItemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
recentInvoicesItemTouchHelper.attachToRecyclerView(recentInvoiceRecyclerView);
and this is my RecyclerView.ViewHolder
:
private class RecentInvoiceViewHolder extends RecyclerView.ViewHolder{
private TextView price;
private TextView hours;
private TextView minutes;
private TextView desc;
private View color;
private View sent;
private View swipeActionsView;
private View frontView;
private Button print;
private Button cancelSwipe;
boolean swiped = false;
public RecentInvoiceViewHolder(View view) {
super(view);
price = (TextView) view.findViewById(R.id.invoice_review_in_day_price);
hours = (TextView) view.findViewById(R.id.invoice_review_in_day_hours);
minutes = (TextView) view.findViewById(R.id.invoice_review_in_day_minutes);
desc = (TextView) view.findViewById(R.id.invoice_review_in_day_decs);
color = view.findViewById(R.id.invoice_review_in_day_color);
sent = view.findViewById(R.id.invoice_review_in_day_sent_check);
swipeActionsView = view.findViewById(R.id.swipe_actions);
frontView = view.findViewById(R.id.front_view);
print = (Button) view.findViewById(R.id.print_recent_invoice);
cancelSwipe = (Button) view.findViewById(R.id.cancel_swipe);
cancelSwipe.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
frontView.setTranslationX(0);
frontView.setVisibility(View.VISIBLE);
swiped = false;
}
});
}
public void lunchSwipeEffect(float dx){
if(!swiped)
frontView.setTranslationX(dx);//TranslationX(dx);
if(Math.abs(dx)> frontView.getMeasuredWidth()) {
swiped = true;
frontView.setVisibility(View.GONE);
}
}
}
and finally this is my ViewHolder
layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/archived_right_one_day_invoice_item_height"
android:layout_margin="@dimen/archived_right_one_day_item_margin"
android:clipChildren="false"
android:clipToPadding="false">
<TableLayout
android:id="@+id/swipe_actions"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:stretchColumns="0,1,2"
android:clickable="false">
<TableRow
android:layout_weight="1"
>
<ir.masna.hetab.views.IranFontButton
android:id="@+id/print_recent_invoice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/archived_right_one_day_item_time_font"
android:gravity="center"
android:text="print"
style="@style/CustomFontStyleYekan"
android:layout_column="0"/>
<ir.masna.hetab.views.IranFontButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/archived_right_one_day_item_time_font"
android:gravity="center"
android:text="print"
style="@style/CustomFontStyleYekan"
android:layout_column="1"/>
<ir.masna.hetab.views.IranFontButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/archived_right_one_day_item_time_font"
android:gravity="center"
android:text="print"
style="@style/CustomFontStyleYekan"
android:layout_column="2"/>
</TableRow>
<TableRow
android:layout_weight="1">
<ir.masna.hetab.views.IranFontButton
android:id="@+id/cancel_swipe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/archived_right_one_day_item_time_font"
android:gravity="center"
android:text="cancel"
style="@style/CustomFontStyleYekan"
android:layout_column="0"/>
<ir.masna.hetab.views.IranFontButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/archived_right_one_day_item_time_font"
android:gravity="center"
android:text="print"
style="@style/CustomFontStyleYekan"
android:layout_column="1"/>
<ir.masna.hetab.views.IranFontButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/archived_right_one_day_item_time_font"
android:gravity="center"
android:text="print"
style="@style/CustomFontStyleYekan"
android:layout_column="2"/>
</TableRow>
</TableLayout>
<RelativeLayout
android:id="@+id/front_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:clickable="true"
>
<View
android:id="@+id/invoice_review_in_day_color"
android:layout_width="@dimen/archived_right_one_day_item_colored_view_width"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:background="@drawable/invoice_review_box_radius_right_shape"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toLeftOf="@+id/invoice_review_in_day_color"
android:layout_alignParentLeft="true"
android:background="@drawable/invoice_review_main_box_radius_shape"
android:padding="@dimen/archived_right_one_day_item_border">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="@integer/archived_right_one_day_item_top_invoice_section_weight"
android:orientation="horizontal"
android:background="@drawable/invoice_review_box_radius_top_left_shape"
android:padding="@dimen/archived_right_one_day_item_top_section_padding">
<LinearLayout
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal">
<ir.masna.hetab.views.IranFontTextView
android:id="@+id/invoice_review_in_day_hours"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="@dimen/archived_right_one_day_item_time_margin"
android:textSize="@dimen/archived_right_one_day_item_time_font"
android:textColor="@color/archived_right_one_day_item_time_text_color"
android:gravity="center"
android:background="@drawable/clock_background"
style="@style/CustomFontStyleYekan"/>
<ir.masna.hetab.views.IranFontTextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="@dimen/archived_right_one_day_item_time_separator_font"
android:textColor="@color/archived_right_one_day_item_time_text_color"
android:text=":"
android:layout_marginTop="@dimen/archived_right_one_day_item_time_separator_margin_top"/>
<ir.masna.hetab.views.IranFontTextView
android:id="@+id/invoice_review_in_day_minutes"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginRight="@dimen/archived_right_one_day_item_time_margin"
android:textSize="@dimen/archived_right_one_day_item_time_font"
android:textColor="@color/archived_right_one_day_item_time_text_color"
android:gravity="center"
android:background="@drawable/clock_background"
style="@style/CustomFontStyleYekan"/>
</LinearLayout>
<LinearLayout
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<ir.masna.hetab.views.IranFontTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/archived_right_one_day_item_total_title"
android:textColor="#6d6d6d"
android:textSize="@dimen/archived_right_one_day_item_price_title_font"
android:gravity="bottom|right"
android:includeFontPadding="false"
android:layout_alignParentRight="true"
style="@style/CustomFontStyleYekan"/>
<ir.masna.hetab.views.AutoResize.AutoResizeTextView
android:id="@+id/invoice_review_in_day_price"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="@dimen/archived_right_one_day_item_price_font"
android:gravity="top|right"
android:includeFontPadding="false"
android:maxLines="1"
style="@style/CustomFontStyleYekan"/>
</LinearLayout>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="@integer/archived_right_one_day_item_bottom_invoice_section_weight"
android:background="@drawable/invoice_review_box_radius_bottom_left_shape">
<ir.masna.hetab.views.IranFontTextView
android:id="@+id/invoice_review_in_day_decs"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical|right"
android:textColor="@color/archived_right_one_day_item_time_text_color"
android:textSize="@dimen/archived_right_one_day_item_desc_font"
android:padding="@dimen/archived_right_one_day_item_desc_padding"
android:layout_toRightOf="@+id/invoice_review_in_day_sent_check"
android:ellipsize="end"
android:maxLines="1"
style="@style/CustomFontStyleYekan" />
<View
android:id="@+id/invoice_review_in_day_sent_check"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:gravity="center"
android:background="@drawable/tick"/>
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
</FrameLayout>
and the recyclerView is in a NestedScrollView
with collapsing toolbar effect.
Which Views consumes two first click?!
Upvotes: 4
Views: 521
Reputation: 56
You can simply use some tricky like wrap your view by a transparent view then set on click listener for that view
<View
android:id="@+id/root_clicker"
android:layout_width="@dimen/dp_0"
android:layout_height="@dimen/dp_0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:background="@android:color/transparent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Like this
Upvotes: 0
Reputation: 1229
How I solved:
1.) Create two layouts in xml file (one for swipeable layout, one for the background layout with buttons) Set swipeableLayout to VISIBLE and backgroundLayout to GONE
2.) Create a variable in the row data to keep track of whether that row has been swiped by the user. (Example: email.isBackgroundMenuBehindSwipeOverlayVisible = false
When user swipes to remove a row (triggers ItemTouchHelper.onSwiped()), set the row's isBackgroundMenuBehindSwipeOverlayVisible = true. This persists a field we can use when refreshing the adapter.
3.) (This part is cringe, but it's the ONLY solution so far on this issue) Replace the entire adapter with a brand new one: Ex.)
email?.isBackgroundMenuBehindenterSwipeOverlayVisible = true // Persist user swipe to show menu on this row when the adapter is refreshed.
val savedLinearLayoutManagerState = linearLayoutManager?.onSaveInstanceState() // To persist users scroll position before scrapping adapter
inboxAdapter = inboxAdapter(requireContext(), recentThreads)
linearLayoutManager = LinearLayoutManager(requireContext())
binding.inboxRecyclerView.layoutManager = linearLayoutManager
binding.inboxRecyclerView.adapter = inboxAdapter
linearLayoutManager?.onRestoreInstanceState(savedLinearLayoutManagerState) // Return the user to the position they were when they swiped.
Upvotes: 0
Reputation: 91
The ItemTouchHelper
is gripping the touch from the RecyclerView
Upvotes: 0