I have been using android design support library for collapsing toolbar layout. Everything works fine except that I want to scroll the whole view on scrolling content in collapsingBarlayout
Here's the xml layout :
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.CoordinatorLayout
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="420dp"
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"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginStart="48dp"
app:expandedTitleMarginEnd="64dp"
android:fitsSystemWindows="true">
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.8"
android:fitsSystemWindows="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
/>
<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:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<include layout="@layout/activity_item_detail"
/>
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_vertical_margin"
android:clickable="true"
android:src="@android:drawable/ic_menu_call"
app:layout_anchor="@+id/appbar"
app:layout_anchorGravity="bottom|right|end"
style="@style/floating_action_button"
/>
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="@+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/drawer_header"
app:menu="@menu/drawer"/>
</android.support.v4.widget.DrawerLayout>
Scrolling the content works if touched on anything except viewpager/toolbar. I need the same scroll experience on touching and scrolling vertically on view pager also. Had tried overriding onTouchEvent of view pager to pass ACTION_UP motion event to scroll_view.
nestedScrollView.post(new Runnable() {
@Override
public void run() {
mPager.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
return nestedScrollView.onTouchEvent(event);
} else {
return v.onTouchEvent(event);
}
}
});
}
});
But it doesn't work. Please help with a workaround/any hack that can quickly fix this up.
Find out the view which is receiving the touch event. In this specific case ViewPager is receiving the touch event which we want to override. Once you have the View which is receiving touch event, you can install a Gesture Detector. Take a look at this guide, in particular at the
Detecting a Subset of Supported Gestures
In this way you can manage all the gesture that are performed on the outer view and you can react to the gesture in some way.
Note: when you extend the GestureDetector.SimpleOnGestureListener
remember to override the onDown
method, otherwise you won't get any other event.
I've tested my suggestion on this github project. If you modify the CheeseDetailActivity in this way, you will get the onScroll event called when you scroll inside the cheese image.
public class CheeseDetailActivity extends AppCompatActivity {
public static final String EXTRA_NAME = "cheese_name";
private GestureDetectorCompat mDetector;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
MyGestureListener listener = new MyGestureListener();
mDetector = new GestureDetectorCompat(this, new MyGestureListener());
View root = findViewById(R.id.pager);
root.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return mDetector.onTouchEvent(event);
}
});
Intent intent = getIntent();
final String cheeseName = intent.getStringExtra(EXTRA_NAME);
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
CollapsingToolbarLayout collapsingToolbar =
(CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
collapsingToolbar.setTitle(cheeseName);
loadBackdrop();
}
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;
}
class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
private static final String DEBUG_TAG = "Gestures";
@Override
public boolean onDown(MotionEvent event) {
Log.d(DEBUG_TAG,"onDown: " + event.toString());
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
Log.d(DEBUG_TAG, "onScroll: ");
//Implement functionality you want e.g. horiontal scroll changes viewpager item, vertical scroll collpases the toolbar
return true;
}
}
}
Your pager content needs to have nested scrolling enabled. The easiest way to accomplish this is to just wrap it in a NestedScrollView
:
fragment_image.xml
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="@dimen/detail_backdrop_height"
android:scaleType="centerCrop" />
</android.support.v4.widget.NestedScrollView>
However this causes the parent height of the ImageView
to be indeterminate, so you have to set it to some fixed height.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With