4

Hello am having a Bottom Sheet Dialog Fragment that is show when an item in a recyclerview is clicked. The showing of the bottom sheet implementation is in an adapter for the recyclerview. The problem am having is that when you quickly double tap on the items to show the bottom sheet it shows twice, is there a way to limit the tap to only one tap or not to show the bottom sheet dialog fragment again when it is being shown by checking

Here is how am showing the bottom sheet on item click in the recyclerview


@Override
    public void onBindViewHolder(@NonNull final MyViewHolder myViewHolder, final int position) {


        myViewHolder.cardView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {


                BottomSheetFragment bottomSheetFragment = new BottomSheetFragment();
                Bundle bundle = new Bundle();

                bundle.putInt("id",productList.get(position).getId());
                bundle.putString("name",productList.get(position).getName());
                bundle.putDouble("price",productList.get(position).getPrice());
                bundle.putInt("stock",productList.get(position).getStock());
                bundle.putInt("quantity",productList.get(position).getQuantity());
                bundle.putString("photo",productList.get(position).getPhoto());

                bottomSheetFragment.setArguments(bundle);
                bottomSheetFragment.show(fragmentManager, bottomSheetFragment.getTag());
            }
        });

    }

I have tried using Muhannad Fakhouri answer by doing the following

Declaring a boolean to show if BottomSheet is showing or not

 private boolean isBottomSheetShowing = false;

Implementation in the bottom sheet


if(!isBottomSheetShowing){

                 isBottomSheetShowing = true;

                ItemBottomSheet itemBottomSheet = new ItemBottomSheet();
                Bundle bundle = new Bundle();

                bundle.putString("code",itemPosition.getCode());
                bundle.putString("name",itemPosition.getName());
                bundle.putString("description",itemPosition.getDescription());
                bundle.putString("upcCode",itemPosition.getUpcCode());
                bundle.putString("photoBlob",itemPosition.getPhotoBlob());
                bundle.putDouble("discount",itemPosition.getDiscount());
                bundle.putDouble("price",itemPosition.getPrice());
                bundle.putInt("available",itemPosition.getAvailable());

                itemBottomSheet.setArguments(bundle);
                itemBottomSheet.show(fragmentManager, itemBottomSheet.getTag());

                }else{
                    isBottomSheetShowing = false;
                }

The issue arrising now is that there is a time when nothing happens totally when i click on the item and then after i click the item again it shows

Emmanuel Njorodongo
  • 1,004
  • 17
  • 35

4 Answers4

3

I am trying to check that the fragment is already added or not in the fragment support manager, if added then not showing again.

Here is the code: ( Put this piece of code in synchronized block for better functionality )

        for(Fragment fragment: activity.getSupportFragmentManager().getFragments()){
            if(fragment instanceof BottomSheetFragment)
                return;
        }
       BottomSheetFragment bottomSheetFragment = BottomSheetFragment.newInstance();
       bottomSheetFragment.show(activity.getSupportFragmentManager(), "bottom_sheet_fragment");

If any exception comes, please comment, I will try to fix it.

DeePanShu
  • 1,236
  • 10
  • 23
  • Put that piece of code into a synchronized block/method and it should be the correct answer ! – Paul W Mar 15 '22 at 20:13
  • 1
    thanks for the fragment check i applied ist for me like this: private fun isBottomSheetShown(): Boolean { this.childFragmentManager.fragments.forEach { fragment -> if (fragment is ConsentDialogFragment) return true } return false } – writer_chris Sep 26 '22 at 12:10
1

There are many ways to do that, one way to do this is to save the bottomSheetFragment in a field and check if it's showing before showing it

BottomSheetFragment bottomSheetFragment = new BottomSheetFragment();

@Override
    public void onBindViewHolder(@NonNull final MyViewHolder myViewHolder, final int position) {


        myViewHolder.cardView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(bottomSheetFragment.isAdded()) return
                Bundle bundle = new Bundle();

                bundle.putInt("id",productList.get(position).getId());
                bundle.putString("name",productList.get(position).getName());
                bundle.putDouble("price",productList.get(position).getPrice());
                bundle.putInt("stock",productList.get(position).getStock());
                bundle.putInt("quantity", productList.get(position).getQuantity());
                bundle.putString("photo",productList.get(position).getPhoto());

                bottomSheetFragment.setArguments(bundle);
                bottomSheetFragment.showNow(fragmentManager, bottomSheetFragment.getTag());
            }
        });

    }
Muhannad Fakhouri
  • 1,468
  • 11
  • 14
0

You can also use the OnSingleClickListener to prevent showing the bottom sheet twice:

OnSingleClickListener:

/**
 * This class allows a single click and prevents multiple clicks on
 * the same button in rapid succession. Setting unclickable is not enough
 * because click events may still be queued up.
 *
 * Override onSingleClick() to handle single clicks.
 */
abstract class OnSingleClickListener : View.OnClickListener {

    companion object {
        private const val MIN_DELAY_MS: Long = 500L
    }

    private var mLastClickTime = 0L

    abstract fun onSingleClick(v: View)

    override fun onClick(v: View) {
        val lastClickTime: Long = mLastClickTime
        val now = System.currentTimeMillis()
        mLastClickTime = now
        if (now - lastClickTime < MIN_DELAY_MS) {
            Timber.d("OnClick clicked too quickly: ignored")
        } else {
            // Register the click
            onSingleClick(v)
        }
    }
}

Here is also a useful extension for this class:

fun View.setOnSingleClickListener(callback: (View) -> Unit) {
    setOnClickListener(object: OnSingleClickListener() {
        override fun onSingleClick(v: View) {
            callback.invoke(v)
        }
    })
}

Sample code:

myViewHolder.cardView.setOnSingleClickListener {
    // Open bottom sheet here
}
Veniamin
  • 774
  • 5
  • 12
-4

If using an external library is an option, then you could use RxView from RxBinding to control this, e.g.

RxView.clicks(myViewHolder.cardView)
    .throttle(2, TimeUnit.SECONDS)
    .subscribe {}

Here, throttle is the length of time to disable the click.

Fifer Sheep
  • 2,900
  • 2
  • 30
  • 47