Added OverscrollLinearLayoutManager to fix scrolling in AppDetails2
This commit is contained in:
		
							parent
							
								
									343e91280a
								
							
						
					
					
						commit
						03a8151875
					
				| @ -13,6 +13,7 @@ import android.graphics.Bitmap; | ||||
| import android.graphics.Color; | ||||
| import android.net.Uri; | ||||
| import android.os.Bundle; | ||||
| import android.support.design.widget.AppBarLayout; | ||||
| import android.support.design.widget.CoordinatorLayout; | ||||
| import android.support.v4.content.LocalBroadcastManager; | ||||
| import android.support.v7.app.AlertDialog; | ||||
| @ -46,6 +47,7 @@ import org.fdroid.fdroid.installer.InstallerService; | ||||
| import org.fdroid.fdroid.net.Downloader; | ||||
| import org.fdroid.fdroid.net.DownloaderService; | ||||
| import org.fdroid.fdroid.views.AppDetailsRecyclerViewAdapter; | ||||
| import org.fdroid.fdroid.views.OverscrollLinearLayoutManager; | ||||
| import org.fdroid.fdroid.views.ShareChooserDialog; | ||||
| import org.fdroid.fdroid.views.apps.FeatureImage; | ||||
| 
 | ||||
| @ -59,6 +61,8 @@ public class AppDetails2 extends AppCompatActivity implements ShareChooserDialog | ||||
| 
 | ||||
|     private FDroidApp fdroidApp; | ||||
|     private App app; | ||||
|     private CoordinatorLayout coordinatorLayout; | ||||
|     private AppBarLayout appBarLayout; | ||||
|     private RecyclerView recyclerView; | ||||
|     private AppDetailsRecyclerViewAdapter adapter; | ||||
|     private LocalBroadcastManager localBroadcastManager; | ||||
| @ -91,10 +95,42 @@ public class AppDetails2 extends AppCompatActivity implements ShareChooserDialog | ||||
| 
 | ||||
|         localBroadcastManager = LocalBroadcastManager.getInstance(this); | ||||
| 
 | ||||
|         coordinatorLayout = (CoordinatorLayout) findViewById(R.id.rootCoordinator); | ||||
|         appBarLayout = (AppBarLayout) coordinatorLayout.findViewById(R.id.app_bar); | ||||
|         recyclerView = (RecyclerView) findViewById(R.id.rvDetails); | ||||
|         adapter = new AppDetailsRecyclerViewAdapter(this, app, this); | ||||
|         LinearLayoutManager lm = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); | ||||
|         OverscrollLinearLayoutManager lm = new OverscrollLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); | ||||
|         lm.setStackFromEnd(false); | ||||
| 
 | ||||
|         /** The recyclerView/AppBarLayout combo has a bug that prevents a "fling" from the bottom | ||||
|          * to continue all the way to the top by expanding the AppBarLayout. It will instead stop | ||||
|          * with the app bar in a collapsed state. See here: https://code.google.com/p/android/issues/detail?id=177729 | ||||
|          * Not sure this is the exact issue, but it is true that while in a fling the RecyclerView will | ||||
|          * consume the scroll events quietly, without calling the nested scrolling mechanism. | ||||
|          * We fix this behavior by using an OverscrollLinearLayoutManager that will give us information | ||||
|          * of overscroll, i.e. when we have not consumed all of a scroll event, and use this information | ||||
|          * to send the scroll to the app bar layout so that it will expand itself. | ||||
|          */ | ||||
|         lm.setOnOverscrollListener(new OverscrollLinearLayoutManager.OnOverscrollListener() { | ||||
|             @Override | ||||
|             public int onOverscrollX(int overscroll) { | ||||
|                 return 0; | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public int onOverscrollY(int overscroll) { | ||||
|                 int consumed = 0; | ||||
|                 if (overscroll < 0) { | ||||
|                     CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams(); | ||||
|                     CoordinatorLayout.Behavior behavior = lp.getBehavior(); | ||||
|                     if (behavior != null && behavior instanceof AppBarLayout.Behavior) { | ||||
|                         ((AppBarLayout.Behavior) behavior).onNestedScroll(coordinatorLayout, appBarLayout, recyclerView, 0, 0, 0, overscroll); | ||||
|                         consumed = overscroll; // Consume all of it! | ||||
|                     } | ||||
|                 } | ||||
|                 return consumed; | ||||
|             } | ||||
|         }); | ||||
|         recyclerView.setLayoutManager(lm); | ||||
|         recyclerView.setAdapter(adapter); | ||||
| 
 | ||||
|  | ||||
| @ -0,0 +1,91 @@ | ||||
| package org.fdroid.fdroid.views; | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.support.v7.widget.LinearLayoutManager; | ||||
| import android.support.v7.widget.RecyclerView; | ||||
| import android.util.AttributeSet; | ||||
| 
 | ||||
| /** | ||||
|  * This class is like a standard LinearLayoutManager but with an option to add an | ||||
|  * overscroll listener. This can be used to consume overscrolls, e.g. to draw custom | ||||
|  * "glows". | ||||
|  */ | ||||
| public class OverscrollLinearLayoutManager extends LinearLayoutManager { | ||||
| 
 | ||||
|     /** | ||||
|      * A listener interface to get overscroll infromation. | ||||
|      */ | ||||
|     public interface OnOverscrollListener { | ||||
|         /** | ||||
|          * Notifies the listener that an overscroll has happened in the x direction. | ||||
|          * @param overscroll If negative, the recycler view has been scrolled to the "start" | ||||
|          *                   position. If positive to the "end" position. | ||||
|          * @return Return the amount of overscroll consumed. Returning 0 will let the | ||||
|          * recycler view handle this in the default way. Return "overscroll" to consume the | ||||
|          * whole event. | ||||
|          */ | ||||
|         int onOverscrollX(int overscroll); | ||||
| 
 | ||||
|         /** | ||||
|          * Notifies the listener that an overscroll has happened in the y direction. | ||||
|          * @param overscroll If negative, the recycler view has been scrolled to the "top" | ||||
|          *                   position. If positive to the "bottom" position. | ||||
|          * @return Return the amount of overscroll consumed. Returning 0 will let the | ||||
|          * recycler view handle this in the default way. Return "overscroll" to consume the | ||||
|          * whole event. | ||||
|          */ | ||||
| 
 | ||||
|         int onOverscrollY(int overscroll); | ||||
|     } | ||||
| 
 | ||||
|     private OnOverscrollListener overscrollListener = null; | ||||
| 
 | ||||
|     public OverscrollLinearLayoutManager(Context context) { | ||||
|         super(context); | ||||
|     } | ||||
| 
 | ||||
|     public OverscrollLinearLayoutManager(Context context, int orientation, boolean reverseLayout) { | ||||
|         super(context, orientation, reverseLayout); | ||||
|     } | ||||
| 
 | ||||
|     public OverscrollLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { | ||||
|         super(context, attrs, defStyleAttr, defStyleRes); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Set the {@link OverscrollLinearLayoutManager.OnOverscrollListener} to get information about | ||||
|      * when the parent recyclerview is overscrolled. | ||||
|      * | ||||
|      * @param listener Listener to add | ||||
|      * @see OverscrollLinearLayoutManager.OnOverscrollListener | ||||
|      */ | ||||
|     public void setOnOverscrollListener(OnOverscrollListener listener) { | ||||
|         overscrollListener = listener; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) { | ||||
|         int consumed = super.scrollHorizontallyBy(dx, recycler, state); | ||||
|         int overscrollX = dx - consumed; | ||||
|         if (overscrollX != 0) { | ||||
|             if (overscrollListener != null) { | ||||
|                 int consumedByListener = overscrollListener.onOverscrollX(overscrollX); | ||||
|                 consumed += consumedByListener; | ||||
|             } | ||||
|         } | ||||
|         return consumed; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) { | ||||
|         int consumed = super.scrollVerticallyBy(dy, recycler, state); | ||||
|         int overscrollY = dy - consumed; | ||||
|         if (overscrollY != 0) { | ||||
|             if (overscrollListener != null) { | ||||
|                 int consumedByListener = overscrollListener.onOverscrollY(overscrollY); | ||||
|                 consumed += consumedByListener; | ||||
|             } | ||||
|         } | ||||
|         return consumed; | ||||
|     } | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 mvp76
						mvp76