Interrupting last touch event in Android

109 views Asked by At

My app shows ListPopupWindow as a context menu when user long clicks on list item. After the context menu is displayed, background is still avalable for dragging untill the user lifts his finger up. You can see behaviour in attached gifs. I want to know how to interrup this dragging.

TrackListAdapter.java:

private final float[] longClickLastTouchDownXY = new float[2];

@Override
@CallSuper
public void onBindViewHolder(VH holder, int position) {
    holder.itemView.setOnTouchListener((v, event) -> {
        if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
            longClickLastTouchDownXY[0] = event.getX();
            longClickLastTouchDownXY[1] = event.getY();
        }
        return false;
    });
    holder.itemView.setOnLongClickListener(v -> {
        if (onItemLongClickListener != null) {
            onItemLongClickListener.onItemLongClick((ViewGroup) v,
                    (int) longClickLastTouchDownXY[0], (int) longClickLastTouchDownXY[1],
                    holder.getAdapterPosition());
            return true;
        }
        return false;
    });
}

TrackListFragment.java:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View layout = inflater.inflate(R.layout.list_track, container, false);
    ButterKnife.bind(this, layout);


    tracksList.setAdapter(tracksAdapter);
    tracksAdapter.setOnItemLongClickListener(this::showTrackContextMenu);

    return layout;
}

private void showTrackContextMenu(ViewGroup rootView, float x, float y, int itemPosition) {
    Track selectedTrack = tracksAdapter.get(itemPosition);
    ListPopupWindow popupWindow = new ListPopupWindow(requireContext());
    ListPopupWindowAdapter adapter = new ListPopupWindowAdapter(requireContext(), R.menu.track_menu);
    popupWindow.setAdapter(adapter);

    View tempView = new View(requireContext());
    ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(0, 0);
    tempView.setLayoutParams(lp);
    tempView.setX(x - rootView.getPaddingLeft());
    tempView.setY(y - rootView.getPaddingTop());
    rootView.addView(tempView);

    popupWindow.setAnchorView(tempView);
    popupWindow.setModal(true);
    popupWindow.setOnDismissListener(() -> rootView.removeView(tempView));
    popupWindow.show();
}

image image2

1

There are 1 answers

5
Hasan Bou Taam On

This should work in theory, I didn't test this:

For freezing vertical scroll of RecyclerView:

RecyclerView has a method called setLayoutFrozen(boolean frozen);, this method seems to block the TouchEvent of the RecyclerView while it is active (when you set frozen to true).

Now I am assuming that your method showTrackContextMenu(.....) is called when you longClick an item in your list (it seems you made an interface for this). Anyway try to freeze the RecyclerView at the end of this method. Like this:

private void showTrackContextMenu(ViewGroup rootView, float x, float y, int itemPosition) {

.......
.......
.......

popupWindow.show();

//here
yourRecyclerView.setLayoutFrozen(true);

}

If you want to remove the freeze so you can scroll again, just call this:

yourRecyclerView.setLayoutFrozen(false);

For freezing ViewPager:

Okay I can't find a method that is built to freeze the ViewPager, the only thing you can really do is to make a custom ViewPager and use that instead and make it do what you want:

class MyViewPager extends ViewPager{

private boolean frozen = false;

public MyViewPager(Context context){
super(context);
}

public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}

public void freezeViewPager(boolean frozen){
this.frozen = frozen;
}

@Override
 public boolean onTouchEvent(MotionEvent event) {
if(frozen){
 return false;
}else{
 return super.onTouchEvent(event);
}

}

}

Then you use the above ViewPager in xml instead of the default one that you are using.

To freeze it:

.......

popupWindow.show();

//here freeze recyclerView
yourRecyclerView.setLayoutFrozen(true);
//here freeze view pager
myViewPager.freezeViewPager(true);

To stop the freeze:

myViewPager.freezeViewPager(false);