Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Saturday, April 16, 2016

Nested RecyclerView. How to prevent parent RecyclerView from getting scrolled while child RecyclerView is scrolling?

Nested RecyclerView. How to prevent parent RecyclerView from getting scrolled while child RecyclerView is scrolling?


I am trying to implement a horizontal recyclerview and each item of the recyclerview will be a vertical recyclerview with a grid layout. The problem that i am facing is that when I try to scroll the child recyclerview vertically sometimes the parent recyclerview takes the scroll and starts scrolling horizontally. The approaches I tried to fix this are,

  1. setNestedScrollingEnabled(false) on the parent recyclerview
  2. In the onTouch() of the child recyclerview I disable touch events on the parent recyclerview by called requestdisallowinterceptTouchevent(false)

None of the above solutions provide a perfect fix for the problem. Any help is appreciated

Answer by Andrey for Nested RecyclerView. How to prevent parent RecyclerView from getting scrolled while child RecyclerView is scrolling?


Try this. For my use-case it has worked:

nestedRecyclerView.setOnTouchListener(new View.OnTouchListener() {        @Override      public boolean onTouch(View v, MotionEvent event) {          return true;      }  });  

Answer by pRaNaY for Nested RecyclerView. How to prevent parent RecyclerView from getting scrolled while child RecyclerView is scrolling?


Try below code to scroll inner RecyclerView.

innerRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {            @Override          public void onTouchEvent(RecyclerView recycler, MotionEvent event) {              // Handle on touch events here              int action = event.getAction();              switch (action) {                  case MotionEvent.ACTION_DOWN:                      // Disallow Parent RecyclerView to intercept touch events.                      recycler.getParent().requestDisallowInterceptTouchEvent(true);                      break;                    case MotionEvent.ACTION_UP:                      // Allow Parent RecyclerView to intercept touch events.                      recycler.getParent().requestDisallowInterceptTouchEvent(false);                      break;              }              }            @Override          public boolean onInterceptTouchEvent(RecyclerView recycler, MotionEvent event) {              return false;          }        });  

Answer by BNK for Nested RecyclerView. How to prevent parent RecyclerView from getting scrolled while child RecyclerView is scrolling?


IMO, you can try the following inside the Adapter of outer RecyclerView:

    @Override      public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {          View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview, parent, false);            RVAdapter2 recyclerViewAdapter2 = new RVAdapter2();          RecyclerView innerRV = (RecyclerView) v.findViewById(R.id.rv2);          // Setup layout manager for items          LinearLayoutManager layoutManager2 = new LinearLayoutManager(parent.getContext());          // Control orientation of the items          layoutManager2.setOrientation(LinearLayoutManager.VERTICAL);          innerRV.setLayoutManager(layoutManager2);          innerRV.setAdapter(recyclerViewAdapter2);            innerRV.setOnScrollListener(new RecyclerView.OnScrollListener() {              @Override              public void onScrollStateChanged(RecyclerView recyclerView, int newState) {                  super.onScrollStateChanged(recyclerView, newState);                  recyclerView.getParent().requestDisallowInterceptTouchEvent(true);              }          });            return new MyViewHolder(v);      }  

For API23, you can also try innerRV.setOnScrollChangeListener because setOnScrollListener is deprecated.

UPDATE:

Another option is using addOnScrollListener instead of setOnScrollListener

Hope it helps!

Answer by m vai for Nested RecyclerView. How to prevent parent RecyclerView from getting scrolled while child RecyclerView is scrolling?


setNestedScrollingEnabled(false) on the parent recyclerview

What you could try is setNestedScrollingEnabled(false) on the child RecyclerView, if any. RecyclerView 's nestedscroll-ness is that of a child (that's why it implements NestedScrollingChild).

In the onTouch() of the child recyclerview I disable touch events on the parent recyclerview by called requestdisallowinterceptTouchevent(false)

This should work, but what you should do is requestDisallowInterceptTouchEvent(true), not false. If you subclass RecyclerView, you can override onTouchEvent:

@Override  public boolean onTouchEvent(MotionEvent event) {      if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_UP) {          // ensure we release the disallow request when the finger is lifted          getParent().requestDisallowInterceptTouchEvent(false);      } else {          getParent().requestDisallowInterceptTouchEvent(true);      }      // Call the super class to ensure touch handling      return super.onTouchEvent(event);  }  

Or, with a touch listener from outside,

child.setOnTouchListener(new View.OnTouchListener() {        @Override      public boolean onTouch(View v, MotionEvent event) {          if (v.getId() == child.getId()) {              if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_UP) {                  // ensure we release the disallow request when the finger is lifted                  child.getParent().requestDisallowInterceptTouchEvent(false);              } else {                  child.getParent().requestDisallowInterceptTouchEvent(true);              }          }          // Call the super class to ensure touch handling          return super.onTouchEvent(event);      }  });  

Answer by Nick Cardoso for Nested RecyclerView. How to prevent parent RecyclerView from getting scrolled while child RecyclerView is scrolling?


I fixed this issue in a similar project by taking the opposite approach to you (and everyone else here).

Rather than allow the child to tell the parent when to stop looking at events, I let the parent decide when to ignore (based on direction). This approach requires a custom view though which can be a little more work. Below is what I created which would be used as the Outer/Parent view.

public class DirectionalRecyclerView extends RecyclerView {        private static float LOCK_DIRECTION_THRESHOLD; //The slop      private float startX;      private float startY;      private LockDirection mLockDirection = null;        public DirectionalRecyclerView(Context context) {          super(context);          findThreshold(context);      }        public DirectionalRecyclerView(Context context, AttributeSet attrs) {          super(context, attrs);          findThreshold(context)      }        public DirectionalRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {          super(context, attrs, defStyleAttr);          findThreshold(context);      }        private void findThreshold(Context context) {          //last number is number of dp to move before deciding that's a direction not a tap, you might want to tweak it          LOCK_DIRECTION_THRESHOLD = context.getResources().getDisplayMetrics().density * 12;      }        //events start at the top of the tree and then pass down to      //each child view until they reach where they were initiated      //unless the parent (this) method returns true for this visitor      @Override      public boolean onInterceptTouchEvent(MotionEvent event) {          switch (event.getAction()) {              case MotionEvent.ACTION_DOWN:                  startX = event.getX();                  startY = event.getY();                  break;              case MotionEvent.ACTION_MOVE:                  if (mLockDirection == null) {                      float currentX = event.getX();                      float currentY = event.getY();                      float diffX = Math.abs(currentX - startX);                      float diffY = Math.abs(currentY - startY);                      if (diffX > LOCK_DIRECTION_THRESHOLD) {                          mLockDirection = LockDirection.HORIZONTAL;                      } else if (diffY > LOCK_DIRECTION_THRESHOLD) {                          mLockDirection = LockDirection.VERTICAL;                      }                  } else {                      //we have locked a direction, check whether we intercept                      //the future touches in this event chain                      //(returning true steals children's events, otherwise we'll                      // just let the event trickle down to the child as usual)                      return mLockDirection == LockDirection.HORIZONTAL;                  }                  break;              case MotionEvent.ACTION_UP:                  mLockDirection = null;                  break;          }          //dispatch cancel, clicks etc. normally          return super.onInterceptTouchEvent(event);      }        private enum LockDirection {          HORIZONTAL,          VERTICAL      }    }  

Answer by inkedTechie for Nested RecyclerView. How to prevent parent RecyclerView from getting scrolled while child RecyclerView is scrolling?


Use this code to turn off scroll on recyclerview:

recyclerView.setOnTouchListener(new View.OnTouchListener() {      @Override      public boolean onTouch(View v, MotionEvent event) {          return true;      }  });  

Answer by I2S0215WMAB08 for Nested RecyclerView. How to prevent parent RecyclerView from getting scrolled while child RecyclerView is scrolling?


extend a custom layout manager like this

 public class CustomLayoutManager extends LinearLayoutManager {   private boolean isScrollEnabled = true;     public CustomGridLayoutManager(Context context) {   super(context);          }    @Override   public boolean canScrollVertically() {   return false;   }  }  

Set the layout manager to this "Custom layout Manager"

Answer by Hiren Patel for Nested RecyclerView. How to prevent parent RecyclerView from getting scrolled while child RecyclerView is scrolling?


You should do this way:

innerRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {            @Override          public void onTouchEvent(RecyclerView recycler, MotionEvent event) {              // Handle on touch events here              int action = event.getAction();              switch (action) {                  case MotionEvent.ACTION_DOWN:                        recycler.getParent().requestDisallowInterceptTouchEvent(true);                        break;                    case MotionEvent.ACTION_UP:                        recycler.getParent().requestDisallowInterceptTouchEvent(false);                        break;                    case MotionEvent.ACTION_MOVE:                        recycler.getParent().requestDisallowInterceptTouchEvent(true);                        break;              }              }            @Override          public boolean onInterceptTouchEvent(RecyclerView recycler, MotionEvent event) {              return false;          }        });  

Hope this would help you.


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.