65

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.

android developer
  • 114,585
  • 152
  • 739
  • 1,270
  • Have no idea, but please give the library version you used too, and how you imolement your view (scroll flag, etc ..) – Nguyễn Hoài Nam Nov 10 '15 at 13:36
  • I only changed the content of the layout (to have textViews instead of cardViews), to show these screenshots. I've updated the question to show the libraries versions. Why downvote for this ? – android developer Nov 10 '15 at 14:27
  • Sorry I don't think that was me to down vote your question. Anyway I'll take a look – Nguyễn Hoài Nam Nov 10 '15 at 14:33
  • Have you tried using [canScrollVertically](http://developer.android.com/reference/android/view/View.html#canScrollVertically%28int%29)? Maybe if you return false the scrolling will stop. – Gent Ahmeti Nov 23 '15 at 14:27
  • @torque203 Return false on which cases, and in which function to call it? – android developer Nov 23 '15 at 14:28
  • You use your own custom `NestedScrollView` and override this method. Than maybe check your last `View` `getBottom`, if `view.getBottom()==screenHeight - softButtonsHeight` then you're at the end of the screen, you shouldn't scroll up. Also don't forget get to check the direction of the scroll. – Gent Ahmeti Nov 23 '15 at 14:31
  • @torque203 Interesting. Have you tried it? – android developer Nov 23 '15 at 14:35
  • Unfortunately, no. But if I had to do something like this, this would be my first try. – Gent Ahmeti Nov 23 '15 at 14:37
  • @torque203 What's "softButtonsHeight" ? the height of the bottom view? – android developer Nov 23 '15 at 14:53
  • The back button, home and recent apps buttons on the new android OS-es. You also need to remove the status bar height. This is to calculate where exactly is the bottom of the screen. – Gent Ahmeti Nov 23 '15 at 14:55
  • @torque203 Are you sure it's needed, instead of just getting the height of the view/parent ? – android developer Nov 23 '15 at 14:59
  • That should work, yeah. I guess you'd need the parents height. Bottom line is you need to know the value on which to stop scrolling vertically, how you get this value doesn't really matter, as long as it yields the correct value. – Gent Ahmeti Nov 23 '15 at 15:04
  • @torque203 Something weird: I've created a new class that extends NestedScrollView , and only wrote to the log for each time canScrollVertically is called. It seems that it doesn't get called often enough (only on first event of scroll-down/up batch events), so I don't think this solution can work . It's weird, because I'd expect it to be called very often, as long as I scroll. Not only that, but even though I've added an if(direction>0) condition, it gets called when scrolling up and down, and not just one of them... – android developer Nov 23 '15 at 15:14
  • That is weird. I guess that won't work. Another workaround I can think of is this: Add a `ScrollListener` to your `NestedScrollView` when you scroll an amount equals to your contents height use [ViewCompat.setNestedScrollEnabled](http://developer.android.com/reference/android/support/v4/view/ViewCompat.html#setNestedScrollingEnabled%28android.view.View,%20boolean%29), with arguments your `NestedScrollView` and false, otherwise set it to true. I don't like this solution very much, but I think it could work. – Gent Ahmeti Nov 23 '15 at 15:28
  • @torque203 There is no scrollListener for NestedScrollView (at least not something that Android Studio shows). Only thing I've found is setOnScrollChangeListener , but then it says it needs API 23 to work, and even then, it doesn't seem to get called. – android developer Nov 23 '15 at 15:48
  • @torque203 Also, even when extending the NestedScrollView, barely any function that has the word "scroll" in it gets called, and none gets called multiple times when you cause multiple scroll events. – android developer Nov 23 '15 at 15:50
  • @androiddeveloper [setOnScrollChangeListener](http://developer.android.com/reference/android/support/v4/widget/NestedScrollView.html#setOnScrollChangeListener%28android.support.v4.widget.NestedScrollView.OnScrollChangeListener%29) it says this should work all the way to v4. – Gent Ahmeti Nov 23 '15 at 15:54
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/95950/discussion-between-torque203-and-android-developer). – Gent Ahmeti Nov 23 '15 at 15:56
  • @torque203 So it's a bug in the IDE then. In any case, it doesn't get called at all (tested on Android 6) , so it can't help. – android developer Nov 23 '15 at 15:56
  • @android developer if you look closely this is a different method. It uses `NestedScrollView.OnScrollChangedListener` instead of `View.OnScrollChangedListener`. Can you try again? – Gent Ahmeti Nov 23 '15 at 15:59
  • @torque203 Oh, now it works. Question is, now what? I'm currently at home, so I will come back to this when I get back to the office. Quite curious now... – android developer Nov 23 '15 at 19:36
  • Well the idea remains the same. Use scrollY and oldScrollY to figure out if you can scroll up. If not disable nestedScrolling otherwise enable it. I'll try and make sample test, if I get it to work I'll post an answer. – Gent Ahmeti Nov 23 '15 at 19:46
  • Listening to `NestedScrollView` scroll changes doesn't work. If the `View` is too small to scroll you won't get any updates. I think your best bet is implementing a custom [Behavior](http://developer.android.com/reference/android/support/design/widget/CoordinatorLayout.Behavior.html). – Gent Ahmeti Nov 23 '15 at 22:38
  • @torque203 What do you mean it doesn't work? Also, what would I do to make it block the scrolling itself? – android developer Nov 24 '15 at 07:33
  • This is not you want i guess but this may help: you can decide collapsed size by changing android.support.v7.widget.Toolbars height – Tuna Karakasoglu Nov 30 '15 at 12:20
  • 1
    @TunaKarakasoglu Interesting. Can you please demonstrate? – android developer Nov 30 '15 at 23:01
  • Possibly related: http://stackoverflow.com/questions/32404979/dont-collapse-toolbar-when-recyclerview-fits-the-screen – Jiri Tousek Dec 01 '15 at 09:14
  • @JiriTousek I'm talking about NestedScrollView. You are saying I should use RecyclerView instead? – android developer Dec 01 '15 at 11:52
  • @androiddeveloper Sorry, cannot serve here, only relaying a link posted by another user (answer was since deleted as it was intended to be a comment, but the user had too low rep to comment). – Jiri Tousek Dec 01 '15 at 12:11
  • what did you use to create the GIFs? – Viral Patel Dec 22 '15 at 11:14
  • 1
    @Virus First capture the screen into a video file (use ADB or Android Studio), and then convert it to a gif using any tool you wish, like this one: http://image.online-convert.com/convert-to-gif – android developer Dec 22 '15 at 11:18
  • @Lakhan Why does it help? First link doesn't work. Second link has a lot of content to show in the NestedScrollView, so it can't even show the issue, where enough content is shown on the screen. – android developer Dec 22 '15 at 13:01
  • @androiddeveloper You might want to decompile that app(Contacts?) or try and find the source: https://github.com/android/platform_packages_apps_contacts – Jared Burrows Dec 23 '15 at 08:25
  • @JaredBurrows The code there is very complex to read, and we have a schedule to work with. I also don't think they use NestedScrollView or anything from the design library. – android developer Dec 23 '15 at 08:37
  • @androiddeveloper The linearlayout above cardview is having height = match_parent, have you tried with wrap_content. this is for 1st problem. – Shreyans jain Dec 29 '15 at 07:58

2 Answers2

12

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!

BNK
  • 23,994
  • 8
  • 77
  • 87
  • 1
    According to the animation you've shown, this doesn't work well, because the toolbar doesn't get pinned and the text of the title doesn't move&resize. It's similar to just putting a scrollView with content... – android developer Dec 24 '15 at 09:14
  • can you please explain what you did, and where there do you block the scrolling? Would it also help for the 2nd sample I've provided (of 3-phases bottom sheet) ? – android developer Dec 26 '15 at 00:16
  • As you can see in my code, I didn't do anything with NestedScrollView. Actually, NSV's scroll event only happens when Toolbar pinned to actionbar or Toolbar's layout_height fixed. CollapsingToolbarLayout depends on Toolbar's layout_height, so I calculate the linearLayout1's height runtime, then set Toolbar's layout_height in IF. I am not sure this works for #2 or not. – BNK Dec 26 '15 at 00:36
  • the linearLayout1's height of course relates to NestedScrollView (sorry for my English, I have not many words to explain well) :) – BNK Dec 26 '15 at 00:45
  • If using `nestedScrollView.setOnScrollChangeListener`, you can see it only happens as the following video clip https://drive.google.com/file/d/0B2HGUM4c0YwpZkVwSEhYWWc1cnM/view?usp=sharing – BNK Dec 26 '15 at 01:31
  • I have a small update with `toolbarHeight = toolbarLayoutParams.height;` and `if (linearLayoutHeight + toolbarHeight < screenHeight)` – BNK Dec 26 '15 at 04:15
  • so, it sets new height for Toolbar and then on scroll up works as CollapsingToolbarLayout was fully collapsed on that height? – GPack Dec 26 '15 at 22:01
  • @GPack toolbar new height only set when IF condition meets. Actually if that height fixed, CollapsingToolbarLayout only collapses to that height – BNK Dec 26 '15 at 22:16
  • The current code doesn't work as shown on the animation for me. In the case of a single card, I don't see a title at all, and if I switch to landscape, the title moves in a very weird way compared to the original (i think it's not bounded to the bottom of the collapsing app bar). – android developer Dec 26 '15 at 23:53
  • @androiddeveloper I have tested before posting here, I suggest that you download my customized project at GitHub (I updated above) and try. I tested cases: 1 cardview with short string content, 1 cardview with long string content and 2 cardviews. In my `activity_detail.xml` you will see I commented one cardview :) – BNK Dec 27 '15 at 00:02
  • @androiddeveloper: for your comment `the title moves in a very weird way compared to the original`, IMO that's because I use SnagIt to capture video, then convert to ani-gif so it's not beautiful, actually, in the real phone and AVDs, it's nice :). I cannot use `Screen Record` feature in Android Studio, my phone is Android 4.1.2 – BNK Dec 27 '15 at 00:05
  • @androiddeveloper only one problem with this code is that the `FloatingActionButton` disappeared, I have not checked why, anyway, I think it's not the main requirement in your #1 issue, so I removed it for now. – BNK Dec 27 '15 at 00:12
  • @androiddeveloper: I have updated my answer to fix `collapsingToolbar's title disappeared`, pls pay attention to `appbarLayoutParams.height = toolbarLayoutParams.height + 70;`. I think there's no space for the title after setting toolbar height, so need to increase appbar height, why 70, actually I don't know, just increasing from 40, 50,... I think need many devices/avds to test more. Pls note that I only update this answer, not GitHub project at this time (perhaps tomorrow morning) – BNK Dec 27 '15 at 05:49
  • @BNK Thing is that I tested it on a real device (which is why i wrote "for me"). It's different than how it worked on the original example. I want to have the exact same effect as before, without changing positions. Just let the scrolling stop. If you look at the code of the CheeseSquare, you will see that they do not modify how the title is positioned. It's all automatic by the design library. – android developer Dec 27 '15 at 06:20
  • @androiddeveloper as I said before, not stop scrolling of NestedScrollView, just for the toolbar, you can check NSV's scroll change listener. I have spent time to find a solution for you, of course, if it's not working for you, you should wait for another answers. I will stop here :) – BNK Dec 27 '15 at 06:45
  • @androiddeveloper "that they do not modify how the title is positioned. It's all automatic by the design library", you see android:layout_height="?attr/actionBarSize", right? If you set it more than 200, title will disappear since appBar height fixed 256dp (detail_backdrop_height). Without coding, IMHO, your #1 issue cannot be solved. – BNK Dec 27 '15 at 06:57
  • @androiddeveloper final words I'd like to say that of course NSV stops scrolling when there's no more content in it (bottom reached). Here, the scroll that you said in your question is of collapsingToolbar which will be collapsed to its toolbar's height. I am not good at English so cannot explain much. Hope you understand my idea :) – BNK Dec 27 '15 at 07:24
  • @BNK Isn't there a way to extend one of the design library classes to fix it? – android developer Dec 27 '15 at 07:53
  • I've now tested the github repo. It still doesn't show a title at all. On landscape, it does show, but as I said the animation as I scroll seem very weird. Tested on Nexus 4 with Kitkat. – android developer Dec 27 '15 at 08:00
  • @androiddeveloper as I said 2 hours ago, I only update "appbarLayoutParams.height = toolbarLayoutParams.height + 70;" in my answer, GitHub not yet (I'll update tomorrow) You can add to the project you have just downloaded. – BNK Dec 27 '15 at 08:08
  • If you wanna extend one of the design library classes, IMO, you can try a custom CollapsingToolbarLayout class ( https://android.googlesource.com/platform/frameworks/support.git/+/master/design/src/android/support/design/widget/CollapsingToolbarLayout.java) – BNK Dec 27 '15 at 08:43
  • @androiddeveloper Pls see my updated GitHub sample. I have just tested with Nexus S4 emulator – BNK Dec 28 '15 at 09:19
  • @BNK It still looks bad. Sorry. The title isn't aligned to the bottom of the header background. it moves a lot. it's very different than the official way to do it. please just use the official way to show the title, or mimic it to be 100% the same. – android developer Dec 28 '15 at 11:18
  • @androiddeveloper: in the original Cheesesquare sample, if you set `android:layout_height="170dp"`, for example, for `android.support.v7.widget.Toolbar`, the title isn't aligned to the bottom of the header background, it moves a lot too :) – BNK Dec 29 '15 at 06:14
  • @BNK Why change the size of the toolbar? It doesn't make sense. The toolbar has a standard size... – android developer Jan 01 '16 at 17:44
  • @androiddeveloper I just want to tell you why and when the title move alot. Google does not deny us to change it, right? It should be changed in some cases to solve some issues such as your first one. – BNK Jan 01 '16 at 23:52
  • 1
    @BNK Why should I change it in my #1 case? I don't need to change the toolbar size. I want to stop the scrolling when there is no more content to scroll to, at the bottom. – android developer Jan 02 '16 at 13:19
0

To disable scrolling, just set both NestedScrollView and it's LinearLayout child height to 'wrap_content'.

That will not work completely as you wish, but at least it will not be scrollable, if content fits on screen completely.


Talking about your Contacts app example, looks like it's not using CoordinatorLayout and other things that come with it.

This behavior can be done in this way:

<ScrollView
    android:id="@+id/scroll_adinfo"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/image"
            android:layout_width="match_parent"
            android:layout_height="@dimen/image_height"
            android:src="@mipmap/ic_launcher"/>

        <LinearLayout
            android:id="@+id/layout_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingTop="@dimen/image_height">

            <!-- YOUR CONTENT HERE -->
        </LinearLayout>
    </FrameLayout>
</ScrollView>

And in your code you will move the image on scroll:

final ImageView image = (ImageView) findViewById(R.id.image);

((ScrollView) rootView.findViewById(R.id.scroll_adinfo)).getViewTreeObserver().addOnScrollChangedListener(
            new ViewTreeObserver.OnScrollChangedListener() {

                @Override
                public void onScrollChanged() {
                    int scrollY = ((ScrollView) rootView.findViewById(R.id.scroll_adinfo)).getScrollY();

                    image.setY(scrollY / 2);
                }
            });

I have extracted that from one of my projects and edited it so I can miss something.

geNia
  • 985
  • 9
  • 20
  • The "wrap_content" solution doesn't always work. as an example, set the first item (in the LinearLayout) to be the card from the sample, and the second item to be a TextView with textSize="20dp" and layout_marginTop="80dp" . It will allow to scroll too much till the action bar is collapsed and there is a huge empty space below the TextView. Tested on Galaxy S4. But as you said it's not perfect. I don't understand about the second solution. Have you tried it? – android developer Dec 23 '15 at 06:17
  • @androiddeveloper The second solution code is extracted from one of my projects. But it is using the simple ScrollView. I have no idea how to make it work with NestedScrollView and CoordinatorLayout with FloatingActionButton. – geNia Dec 23 '15 at 13:55
  • @androiddeveloper The idea is to place the image below main content and move it programmatically, when the user scrolls the content. – geNia Dec 23 '15 at 13:56
  • Well, it's not what I asked about... :( – android developer Dec 24 '15 at 07:33
  • @androiddeveloper It's what happens in your Contacts app example. – geNia Dec 24 '15 at 16:04