Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to disable scrolling of NestedScrollView&CollapsingToolbarLayout, for example when there is no more content below?

Background

I try to add the same functionality as shown on many apps, where the upper area of the screen shrinks&expands according to the scrolled content.

For this, I use Google's design library, as shown on the CheeseSquare sample.

The problem

Thing is, no matter how much content there is in the NestedScrollView , it lets me scroll way below the last view of the content, just to let me see the final state of the actionbar, having the minimal size of itself.

In short, this is what I see when scrolling to the bottom (modified content of CheeseSquare sample):

enter image description here

while this is what I'd like to have when scrolling to the bottom (taken from contacts app) :

enter image description here

I'm also trying to fix a bug on ThreePhasesBottomSheet sample that scrolling in the bottom sheet content is possible even when it's in peek-state. To reproduce, start scrolling horizontally (which doesn't do anything, as there is nothing to scroll this way) and then vertically, which would somehow trigger scrolling of the content of the bottom-sheet.

Therefore, I need to disable there the scrolling in "transformView()" method, in the case that "translation

This is how it works using normal usage:

enter image description here

And this is how it behaves with the bug of not blocking the scrolling:

enter image description here

What I've tried

I've tried to play with the "layout_scrollFlags" flags, to change the height to wrap_content, and to remove the clipToPadding and fitsSystemWindows attributes.

Here's the sample XML file, which I've modified to include only a single cardView instead of many:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     android:id="@+id/main_content"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:fitsSystemWindows="true">      <android.support.design.widget.AppBarLayout         android:id="@+id/appbar"         android:layout_width="match_parent"         android:layout_height="@dimen/detail_backdrop_height"         android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"         android:fitsSystemWindows="true">          <android.support.design.widget.CollapsingToolbarLayout             android:id="@+id/collapsing_toolbar"             android:layout_width="match_parent"             android:layout_height="match_parent"             app:layout_scrollFlags="scroll|exitUntilCollapsed"             android:fitsSystemWindows="true"             app:contentScrim="?attr/colorPrimary"             app:expandedTitleMarginStart="48dp"             app:expandedTitleMarginEnd="64dp">              <ImageView                 android:id="@+id/backdrop"                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:scaleType="centerCrop"                 android:fitsSystemWindows="true"                 app:layout_collapseMode="parallax" />              <android.support.v7.widget.Toolbar                 android:id="@+id/toolbar"                 android:layout_width="match_parent"                 android:layout_height="?attr/actionBarSize"                 app:popupTheme="@style/ThemeOverlay.AppCompat.Light"                 app:layout_collapseMode="pin" />          </android.support.design.widget.CollapsingToolbarLayout>      </android.support.design.widget.AppBarLayout>      <android.support.v4.widget.NestedScrollView         android:layout_width="match_parent"         android:layout_height="match_parent"         app:layout_behavior="@string/appbar_scrolling_view_behavior">          <LinearLayout             android:layout_width="match_parent"             android:layout_height="match_parent"             android:orientation="vertical"             android:paddingTop="24dp">              <android.support.v7.widget.CardView                 android:layout_width="match_parent"                 android:layout_height="wrap_content"                 android:layout_margin="@dimen/card_margin">                  <LinearLayout                     style="@style/Widget.CardContent"                     android:layout_width="match_parent"                     android:layout_height="wrap_content">                      <TextView                         android:layout_width="match_parent"                         android:layout_height="wrap_content"                         android:text="Info"                         android:textAppearance="@style/TextAppearance.AppCompat.Title" />                      <TextView                         android:layout_width="match_parent"                         android:layout_height="wrap_content"                         android:text="@string/cheese_ipsum" />                  </LinearLayout>              </android.support.v7.widget.CardView>          </LinearLayout>      </android.support.v4.widget.NestedScrollView>      <android.support.design.widget.FloatingActionButton         android:layout_height="wrap_content"         android:layout_width="wrap_content"         app:layout_anchor="@id/appbar"         app:layout_anchorGravity="bottom|right|end"         android:src="@drawable/ic_discuss"         android:layout_margin="@dimen/fab_margin"         android:clickable="true"/>  </android.support.design.widget.CoordinatorLayout> 

I've tried the next code too :

((AppBarLayout.LayoutParams) collapsingToolbar.getLayoutParams()).setScrollFlags(0); 

but this still allowed scrolling of the NestedScrollView itself in the CheeseSquare example, and also allowed flinging in the ThreePhasesBottomSheet sample .

The questions

  1. What can I do in order to make the scrolling stop when there is no more content to show at the bottom?

  2. In addition, what can be done to disable scrolling of the NestedScrollView in any time I wish ( for the ThreePhasesBottomSheet sample) ? Something like "setEnableScrolling(...)" ?

    I've tried to extend NestedScrollView and also extend from ScrollingViewBehavior, but failed to find what can be done to disable the scrolling.

It's probably a very simple thing to change, but I can't find out what...

EDIT: if needed, this is what I currently use for the design&support library

compile 'com.android.support:appcompat-v7:23.1.0' compile 'com.android.support:design:23.1.0' 

EDIT: for #2, I've found a workaround from within the BottomSheetLayout.java file, to disable all that's related to the variable "sheetViewOwnsTouch", as if it's always set to "false". This will allow stealing touch events on the bottom sheet. However, this is just a workaround, and only for this case. It also causes some touch events that should have been handled by other views. I still wish to know how to block the scrolling programmatically, and also in the other case of enough-space-to-show-content.

like image 881
android developer Avatar asked Nov 10 '15 13:11

android developer


People also ask

How do I stop NestedScrollView scrolling?

setnestedscrollingenabled set it to false.

How do I turn off scroll view?

You cannot disable the scrolling of a ScrollView. You would need to extend to ScrollView and override the onTouchEvent method to return false when some condition is matched.

How do I disable scroll in react native?

To enable or disable scrolling on FlatList with React Native, we can set the scrollEnabled prop. to set the scrollEnabled prop to false to disable scrolling on the FlatList.

What is nested scroll view?

NestedScrollView is just like ScrollView , but it supports acting as both a nested scrolling parent and child on both new and old versions of Android. Nested scrolling is enabled by default.


1 Answers

What can I do in order to make the scrolling stop when there is no more content to show at the bottom?

Firstly, as I have commented below, the scrolling you said in your question is not of the NestedScrollView. It belongs to the CollapsingToolbarLayout. The NestedScrollView's scroll event only happens when CollapsingToolbarLayout fully collapsed, and of course it will stop scrolling when when there is no more content inside it (bottom reached). For the CollapsingToolbarLayout, it will collapse to its Toolbar's layout_height (as in the xml file, you will find "?attr/actionBarSize"). The following image will demonstrate that, pay attention to the red rectangular that is the toolbar (I set its background)

BNK's image

So to have a solution for your #1, you need to calculate the height of NestedScrollView, then if it's smaller than screen height, we fix the toolbar's height.

In short, you can update activity_detail.xml as the following:

<?xml version="1.0" encoding="utf-8"?>  <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     android:id="@+id/main_content"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:fitsSystemWindows="true">      <android.support.design.widget.AppBarLayout         android:id="@+id/appbar"         android:layout_width="match_parent"         android:layout_height="@dimen/detail_backdrop_height"         android:fitsSystemWindows="true"         android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">          <android.support.design.widget.CollapsingToolbarLayout             android:id="@+id/collapsing_toolbar"             android:layout_width="match_parent"             android:layout_height="match_parent"             android:fitsSystemWindows="true"             app:contentScrim="?attr/colorPrimary"             app:layout_scrollFlags="scroll|exitUntilCollapsed">              <ImageView                 android:id="@+id/backdrop"                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:fitsSystemWindows="false"                 android:scaleType="centerCrop"                 app:layout_collapseMode="parallax" />              <android.support.v7.widget.Toolbar                 android:id="@+id/toolbar"                 android:layout_width="match_parent"                 android:layout_height="?attr/actionBarSize"                 app:layout_collapseMode="pin"                 app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />          </android.support.design.widget.CollapsingToolbarLayout>      </android.support.design.widget.AppBarLayout>      <android.support.v4.widget.NestedScrollView         android:layout_width="match_parent"         android:layout_height="wrap_content"                     app:layout_behavior="@string/appbar_scrolling_view_behavior">          <LinearLayout             android:id="@+id/linearLayout1"             android:layout_width="match_parent"             android:layout_height="match_parent"             android:orientation="vertical">              <android.support.v7.widget.CardView                 android:layout_width="match_parent"                 android:layout_height="wrap_content"                 android:layout_margin="@dimen/card_margin">                  <LinearLayout                     style="@style/Widget.CardContent"                     android:layout_width="match_parent"                     android:layout_height="wrap_content">                      <TextView                         android:layout_width="match_parent"                         android:layout_height="wrap_content"                         android:text="Info"                         android:textAppearance="@style/TextAppearance.AppCompat.Title" />                      <TextView                         android:layout_width="match_parent"                         android:layout_height="wrap_content"                         android:text="@string/cheese_ipsum" />                  </LinearLayout>              </android.support.v7.widget.CardView>          </LinearLayout>      </android.support.v4.widget.NestedScrollView>  </android.support.design.widget.CoordinatorLayout> 

And CheeseDetailActivity.java:

public class CheeseDetailActivity extends AppCompatActivity {      public static final String EXTRA_NAME = "cheese_name";     private final Context mContext = this;     private int screenHeight;     private int linearLayoutHeight;     private int toolbarHeight_org;     private int toolbarHeight;      @Override     public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_detail);          Intent intent = getIntent();         final String cheeseName = intent.getStringExtra(EXTRA_NAME);          screenHeight = getScreenHeight(this);          TypedValue typedValue = new TypedValue();         getTheme().resolveAttribute(R.attr.colorPrimary, typedValue, true);         final int colorPrimary = typedValue.data;          final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);         setSupportActionBar(toolbar);         getSupportActionBar().setDisplayHomeAsUpEnabled(true);          AppBarLayout appbar = (AppBarLayout) findViewById(R.id.appbar);         final CoordinatorLayout.LayoutParams appbarLayoutParams = (CoordinatorLayout.LayoutParams)appbar.getLayoutParams();          final ViewGroup.LayoutParams toolbarLayoutParams = toolbar.getLayoutParams();         if (toolbarLayoutParams != null) {             toolbarHeight_org = toolbarLayoutParams.height;             toolbarHeight = toolbarLayoutParams.height;         }          final CollapsingToolbarLayout collapsingToolbar =                 (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);         collapsingToolbar.setTitle(cheeseName);          collapsingToolbar.setContentScrimColor(colorPrimary);         collapsingToolbar.setExpandedTitleTextAppearance(R.style.ExpandedTitleTextAppearance);         //collapsingToolbar.setCollapsedTitleTextAppearance(R.style.CollapsedTitleTextAppearance);          final LinearLayout linearLayout = (LinearLayout) findViewById(R.id.linearLayout1);         ViewTreeObserver observer = linearLayout.getViewTreeObserver();         observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {             @Override             public void onGlobalLayout() {                 linearLayoutHeight = linearLayout.getHeight();                 if (linearLayoutHeight + toolbarHeight < screenHeight) {                     if (toolbarLayoutParams != null) {                         toolbarLayoutParams.height = screenHeight - linearLayoutHeight - 20;                         if (toolbarLayoutParams.height < toolbarHeight_org) {                             toolbarLayoutParams.height = toolbarHeight_org;                         }                          int extended_text_size = (int) getResources().getDimension(R.dimen.expanded_text_size);                          if (appbarLayoutParams.height - toolbarLayoutParams.height <= extended_text_size) {                             int value = appbarLayoutParams.height - toolbarLayoutParams.height;                             if (value < 0) {                                 appbarLayoutParams.height = toolbarLayoutParams.height - value + extended_text_size * 3;                             } else {                                 appbarLayoutParams.height = toolbarLayoutParams.height + extended_text_size * 3;                             }                             if (appbarLayoutParams.height >= screenHeight) {                                 appbarLayoutParams.height = screenHeight;                             }                         }                          // collapsingToolbar.setContentScrimColor(getResources().getColor(android.R.color.transparent));                         if (toolbarLayoutParams.height > toolbarHeight_org) {                             collapsingToolbar.setContentScrimColor(ContextCompat.getColor(mContext, android.R.color.transparent));                         }                     }                 }                 // Removes the listener if possible                 ViewTreeObserver viewTreeObserver = linearLayout.getViewTreeObserver();                 if (viewTreeObserver.isAlive()) {                     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {                         linearLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);                     } else {                         linearLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);                     }                 }             }         });          loadBackdrop();         appbar.setExpanded(true);     }      private int getScreenHeight(Context context) {         int measuredHeight;         Point size = new Point();         WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {             wm.getDefaultDisplay().getSize(size);             measuredHeight = size.y;         } else {             Display d = wm.getDefaultDisplay();             measuredHeight = d.getHeight();         }          return measuredHeight;     }      private void loadBackdrop() {         final ImageView imageView = (ImageView) findViewById(R.id.backdrop);         Glide.with(this).load(Cheeses.getRandomCheeseDrawable()).centerCrop().into(imageView);     }      @Override     public boolean onCreateOptionsMenu(Menu menu) {         getMenuInflater().inflate(R.menu.sample_actions, menu);         return true;     } } 

Here's the result:

BNK's screenshot

With Cheesesquare sample, I have customized this project and uploaded to My GitHub. I agree that it still has some problems, however, at least it can be a solution for your 1st issue.

Please take a look. Hope it helps!

like image 99
BNK Avatar answered Sep 24 '22 22:09

BNK