0

I'm trying to get a fullscreen CollapsingToolbar but when I set match_parent to the height of AppBarLayout I'm not able to scroll the ImageView which is inside CollapsingToolbarLayout. I have to leave some space so that I can touch the "white" of the activity (in AppBarLayout I added android:layout-marginBottom:"16dp" ) and only then, after I touched it, I can scroll the ImageView otherwise I can't. This happens everytime I run the app and touch the layout for the first time. So I have to touch the white first and then scroll the image.

Could you help me?

<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/drawer">

<android.support.design.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="16dp"
        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"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginStart="48dp"
            app:expandedTitleMarginEnd="64dp">

            <ImageView
                android:id="@+id/image"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:scaleType="centerCrop"
                android:fitsSystemWindows="true"
                app:layout_collapseMode="parallax"
                android:contentDescription="@null"
                android:src="@drawable/background" />

            <android.support.v7.widget.Toolbar
                android:layout_height="?attr/actionBarSize"
                android:layout_width="match_parent"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_collapseMode="pin"
                app:theme="@style/ToolbarTheme"
                android:id="@+id/toolbar"/>

        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/scroll"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

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

        </FrameLayout>

    </android.support.v4.widget.NestedScrollView>

</android.support.design.widget.CoordinatorLayout>

<com.myapplication.ScrimInsetsFrameLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="304dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:insetForeground="#4000"
    android:clickable="true"
    android:background="#ffffff">

    ...

</com.myapplication.ScrimInsetsFrameLayout>

</android.support.v4.widget.DrawerLayout>

EDIT @PPartisan I've done what you said but here's what I got:

enter image description here

Rick
  • 3,943
  • 6
  • 33
  • 45
  • it doesn't scroll because there's no code inside `CollapsingToolbarLayout` class to handle touches and make it scroll. You can test it using a `200dp` height and try scrolling touching directly on the `CollapsingToolbarLayout` or on the `ScrollView`. The on the scrollview works, on the toolbar it doesn't. The best advice is to change your layout, maybe something that looks like the header inside the ScrollView. – Budius Oct 12 '15 at 11:22
  • I think I won't get the same result. But I see apps like Google play that have a collapsing toolbar and there's no problem on touching it – Rick Oct 12 '15 at 13:53

2 Answers2

3

This isn't a nice solution, but it does work on my test device. It kick starts the scrolling process by explicitly assigning a touch listener to the AppBar that triggers a nested scroll.

First, create a custom class that extends NestedScrollView and add the following method so it look something like this:

public class CustomNestedScrollView extends NestedScrollView {

    private int y;

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

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

    public boolean dispatchHandlerScroll(MotionEvent e) {
        switch (e.getAction()) {
            case MotionEvent.ACTION_DOWN:
                y = (int) e.getY();
                startNestedScroll(2);
                break;
            case MotionEvent.ACTION_MOVE:
                int dY = y - ((int)e.getY());
                dispatchNestedPreScroll(0, dY, null, null);
                dispatchNestedScroll(0, 0, 0, dY, null);
                break;
            case MotionEvent.ACTION_UP:
                stopNestedScroll();
                break;
        }
        return true;
    }
}

Then, inside your Activity class, assign a TouchListener to your AppBarLayout:

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

and remove it when the AppBar collapses fully for the first time:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if (Math.abs(appBarLayout.getY()) == appBarLayout.getTotalScrollRange()) {
        appBarLayout.setOnTouchListener(null);
    }
    return super.dispatchTouchEvent(ev);
}

Edit

Take the following steps to get it up and running:

  • Replace the NestedScrollView in your xml(android.support.v4.widget.NestedScrollView) with the CustomNestedScrollView (which will take the form of com.something.somethingelse.CustomNestedScrollView, depending on where it is in your project).

  • Assign it to a variable in your Activity onCreate()(i.e. CustomScrollView customScrollView = (CustomScrollView) findViewById(R.id.custom_scroll_view_id);)

  • Set up the TouchListener on your appBarLayout as you have done in your edit. Now when you call dispatchHandlerScroll(), it will be on your customNestedScrollView instance.

  • dispatchTouchEvent() is a method you override in your Activity class, so it should be outside the TouchListener

So, for example:

public class MainActivity extends AppCompatActivity {

    private AppBarLayout appBarLayout;
    private CustomNestedScrollView customNestedScrollView;
    //...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //...
        customNestedScrollView = (CustomNestedScrollView) findViewById(R.id.scroll);

        appBarLayout = (AppBarLayout) findViewById(R.id.app_bar_layout);
        appBarLayout.setOnTouchListener(new View.OnTouchListener() {
            @Override
             public boolean onTouch(View v, MotionEvent event) {
                 return customNestedScrollView.dispatchHandlerScroll(event);
             }
        });
    }    

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (Math.abs(appBarLayout.getY()) == appBarLayout.getTotalScrollRange()) {
            appBarLayout.setOnTouchListener(null);
        }
        return super.dispatchTouchEvent(ev);
    }
}

Hope that's cleared things up.

PPartisan
  • 8,173
  • 4
  • 29
  • 48
0

Try to add a tiny margin so the white space below will be almost invisible (you might also want to change white to accent color so the space will not be visible)

Another approach is to set the height of app bar layout dynamically by getting the height of the screen.

EDIT: This might be a focus problem, try to add dummy layout to your main content, that will be focused automatically

    <LinearLayout
        android:layout_width="0px"
        android:layout_height="0px"
        android:focusable="true"
        android:focusableInTouchMode="true" />

or even just add these attributes to your content layout

android:focusable="true"
android:focusableInTouchMode="true"
Ivan V
  • 3,024
  • 4
  • 26
  • 36
  • I've already tried setting marginBottom to 1dp but the problem is that I have to touch the white space to scroll the ImageView (this happens only when I first run the app). – Rick Oct 10 '15 at 18:08
  • So when you run your app 2nd time you don't need to touch "white" to scroll ? – Ivan V Oct 10 '15 at 18:10
  • Nope, forgive my english, everytime I run the app. There's no problem the second time I scroll the ImageView – Rick Oct 10 '15 at 18:15
  • I tried adding _android:focusable="true" android:focusableInTouchMode="true"_ to **AppBarLayout** but I still cannot scroll it – Rick Oct 10 '15 at 18:31
  • Do you have any other idea? – Rick Oct 10 '15 at 19:01
  • Not yet, trying to figure it out – Ivan V Oct 10 '15 at 19:03