Scroll offscreen view contained in AppBarLayout - android

I am testing the new Support Design Library and I am facing the following problem.
When scrolling to the top the toolbar and imageView views collapse as they are supposed to be but I'd like to scroll the CustomViewPager offscreen too.
I've written a CustomBehavior for CustomViewPager but it doesn't seems to be called, maybe because it is inside the appbar. I can't put it outside the AppBarLayout otherwise will be truncated.
I've managed to hide the CustomViewPager but when it happen the view jumps and doesn't look good hence why I want to scroll it offscreen.
Any suggestion?
<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">
<com.views.NetworkImageViewExt
android:id="#+id/imageViewPostDebate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/holding_image_post_dashboard"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"
android:fitsSystemWindows="true"
/>
<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" />
<ImageView
android:id="#+id/imageViewVideoIcon"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/play_video"
android:layout_gravity="center"
android:fitsSystemWindows="true"
/>
</android.support.design.widget.CollapsingToolbarLayout>
<com.views.CustomViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible"
android:id="#+id/viewPager"
android:fitsSystemWindows="true"
app:layout_behavior="#string/viewpager_scrolling_view_behavior"
/>
</android.support.design.widget.AppBarLayout>
<com.views.FixedRecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/comments_recycle_view"
android:background="#color/white"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
/>
<android.support.design.widget.FloatingActionButton
android:layout_height="wrap_content"
android:layout_width="wrap_content"
app:layout_anchor="#id/post_coordinator_layout"
android:id="#+id/add_comment"
app:layout_anchorGravity="bottom|right|end"
android:src="#drawable/share_icon_xxhdpi"
android:layout_margin="#dimen/view_margin_10"
android:clickable="true"/>
public class CustomViewPagerBehaviour extends CoordinatorLayout.Behavior<CustomViewPager> {
public CustomViewPagerBehaviour(Context context, AttributeSet attrs) {
super();
}
#Override
public boolean layoutDependsOn(CoordinatorLayout parent, CustomViewPager child, View dependency) {
return dependency instanceof FixedRecyclerView || dependency instanceof CollapsingToolbarLayout ||
dependency instanceof AppBarLayout;
}
#Override
public boolean onDependentViewChanged(CoordinatorLayout parent, CustomViewPager child, View dependency) {
if(translationY < -1000){
child.setVisibility(View.GONE);
}else
{
child.setVisibility(View.VISIBLE);
}
return true;
}
}

Related

Get identical behavior of FAB for another custom view inside CoordinatorLayout

I am trying to implement the following UI with a RelativeLayout instead of a FAB. But the collapse of the RelativeLayout does not occur like FAB.
<android.support.design.widget.CoordinatorLayout
android:id="#+id/main_content"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:fitsSystemWindows="true">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
android:fitsSystemWindows="true"
app:expandedTitleMarginStart="48dp"
app:expandedTitleMarginEnd="64dp">
<ImageView
android:id="#+id/backdrop"
android:fitsSystemWindows="true"
app:layout_collapseMode="parallax"
android:src="#drawable/default_img"/>
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
app:layout_collapseMode="pin" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<LinearLayout
android:orientation="vertical"
android:paddingTop="24dp">
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<RelativeLayout
app:layout_anchor="#id/app_bar"
app:layout_anchorGravity="bottom|right|end"
android:id="#+id/cust_fab_container"
app:layout_behavior=".ScrollingBehavior">
<View
android:id="#+id/target"
android:layout_width="200dp"
android:layout_height="200dp"
android:background="#drawable/circle_drawable"
android:visibility="invisible"
android:layout_alignParentRight="true"
android:layout_marginRight="-48dp">
</View>
<rjsv.floatingmenu.floatingmenubutton.FloatingMenuButton
android:id="#+id/my_floating_button"
android:layout_width="65dp"
android:layout_height="65dp">
</rjsv.floatingmenu.floatingmenubutton.FloatingMenuButton>
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
To achieve the FAB behavior I have attached a custom behavior and it animates
but the custom button goes downwards i.e. it does not work as desired
public class ScrollingBehavior extends CoordinatorLayout.Behavior<RelativeLayout>{
private int toolbarHeight;
public ScrollingBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
this.toolbarHeight = Utils.getToolbarHeight(context);
}
#Override
public boolean layoutDependsOn(CoordinatorLayout parent, RelativeLayout layout, View dependency) {
return dependency instanceof AppBarLayout;
}
#Override
public boolean onDependentViewChanged(CoordinatorLayout parent, RelativeLayout layout, View dependency) {
if (dependency instanceof AppBarLayout) {
CoordinatorLayout.LayoutParams lp =
(CoordinatorLayout.LayoutParams) layout.getLayoutParams();
int fabBottomMargin = lp.bottomMargin;
int distanceToScroll = layout.getHeight() + fabBottomMargin;
float ratio = (float)dependency.getY()/(float)toolbarHeight;
layout.setTranslationY(-distanceToScroll * ratio);
}
return true;
}
}
Just had to change the animation logic inside the method onDependentViewChanged and it works.
#Override
public boolean onDependentViewChanged(CoordinatorLayout parent, RelativeLayout layout, View dependency) {
if (dependency instanceof AppBarLayout) {
fab.setTranslationY(-dependency.getScrollY());
}

FloatingActionButton and weird Behavior

I got some strange things happening when using CoordinatorLayout.Behavior with a FloatingActionButton.
Here is a snippet:
public class BottomFloatingActionButtonBehavior extends CoordinatorLayout.Behavior<FloatingActionButton> {
public BottomFloatingActionButtonBehavior() {
}
public BottomFloatingActionButtonBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
return (dependency instanceof BottomNavigation);
}
#Override
public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
if (dependency instanceof BottomNavigation) {
BottomNavigation bottomNavigation = (BottomNavigation) dependency;
int height = bottomNavigation.getNavigationHeight() - bottomNavigation.getBottomInset();
float offset = bottomNavigation.getTranslationY() - height;
child.setTranslationY(offset);
return true;
}
return false;
}
}
When using this behavior i get weird margins added to the button:
Then, when hiding the button and showing again (navigating between fragments) margins increase, but only once (do not get increased after each iteration):
This is my layout:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".Activities.MainActivity">
<android.support.design.widget.CoordinatorLayout
android:id="#+id/layout_coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar_main"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/frame_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<it.sephiroth.android.library.bottomnavigation.BottomNavigation
android:id="#+id/navigation_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:layout_behavior="#string/bbn_appbar_behavior"
app:bbn_entries="#menu/activity_main_navigation" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/button_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
app:borderWidth="0dp"
app:fabSize="normal"
app:layout_behavior="it.sephiroth.android.library.bottomnavigation.BottomFloatingActionButtonBehavior"
app:srcCompat="#drawable/ic_fa_plus_white_24dp"
app:useCompatPadding="true"/>
</android.support.design.widget.CoordinatorLayout>
</layout>
What am i doing wrong? What is this behavior?
The most interesting is that if i change my super class to FloatingActionButton.Behavior then all margins are gone even after switching fragments (show/hide sequence):
But this class controls the snackbar by itself so it won't work for me.
This was tested using latest (and previous also) support lib: 25.2.0 on Nougat and KitKat versions. The difference is - on KitKat there is no "second shift phase". The margins show up from the start.
Try setting android:minWidth and android:minHeight to 0dp.
<android.support.design.widget.FloatingActionButton
android:minWidth="0dp"
android:minHeight="0dp"
android:id="#+id/button_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
app:borderWidth="0dp"
app:fabSize="normal"
app:layout_behavior="it.sephiroth.android.library.bottomnavigation.BottomFloatingActionButtonBehavior"
app:srcCompat="#drawable/ic_fa_plus_white_24dp"
app:useCompatPadding="true"/>

How to extends CoordinatorLayout.Behavior<FloatingActionButton> when FloatingAcitonButton anchored to View

Here is my layout in which ->
1 -> one layout in collapsingToolbarLayout and one View is using to manage this layout
Here is my layout
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/movie.app_bar_layout"
>
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="300dp"
android:id="#+id/movie.toolbar_layout"
app:layout_scrollFlags="enterAlwaysCollapsed|scroll"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="200dp"
android:src="#drawable/poster"
app:layout_collapseMode="parallax"/>
<View
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="#color/colorPrimary"
android:id="#+id/movie.innerview"
android:layout_gravity="bottom"/>
<include
layout="#layout/movie.profile"
android:id="#+id/movie.inner_layout"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<include
layout="#layout/content_scrolling"/>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/ic_media_ff"
app:layout_anchor="#id/movie.innerview"
app:layout_behavior="com.express.entertain.profileapp.ImageBehaviour"
app:layout_anchorGravity="top|right"
android:id="#+id/movie.fab"/>
I am stuck to make behavior ->
1 -> what is the idea behind layoutDependsOn will always return true ?
2-> Then how to fetch behavior in onDependetViewChanged
#Override
public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
return false;
}
#Override
public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
if (dependency instanceof CollapsingToolbarLayout){
}
return false;
}

Hiding a custom view like the FloatingActionButton does in ScrollView

I'm using the example coordinator layour provided in Android Studio and I replaced the FloatingActionButton for a custom view. I've noticed that the FloatingActionButton hides when the app scrolls down using a CollapsingToolbarLayout and I need to replicate that behavior with my custom view.
Here is The XML of the Layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar"
android:layout_width="match_parent"
android:layout_height="#dimen/app_bar_height"
android:fitsSystemWindows="true"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<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/AppTheme.PopupOverlay" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_model" />
<com.github.lzyzsd.circleprogress.CircleProgress
android:id="#+id/day_circle"
android:layout_width="110dp"
android:layout_height="110dp"
android:layout_margin="#dimen/fab_margin"
app:layout_anchor="#id/app_bar"
app:layout_anchorGravity="bottom|end"
custom:circle_prefix_text="$ "
custom:circle_suffix_text=""/>
This is How it looks when it's expanded:
And this is how it looks when it's collapsed:
Do you have any idea how can I replicate the FloatingActionButton behavior and hide the custom view (Circular progress bar) when the toolbar collapses?
Thank you in advance.
public class CircleProgressBehavior extends CoordinatorLayout.Behavior<CircleProgress> {
public CircleProgressBehavior(Context context, AttributeSet attrs) {
...
}
#Override
public boolean layoutDependsOn(CoordinatorLayout parent, CircleImageView child, View dependency) {
...
}
#Override
public boolean onDependentViewChanged(CoordinatorLayout parent, CircleImageView child, View dependency) {
...
}
#Override
private void shouldInitProperties(CircleImageView child, View dependency) {
...
}
}
The XML of Layout
<com.github.lzyzsd.circleprogress.CircleProgress
android:id="#+id/day_circle"
android:layout_width="110dp"
android:layout_height="110dp"
android:layout_margin="#dimen/fab_margin"
app:layout_anchor="#id/app_bar"
app:layout_anchorGravity="bottom|end"
app:layout_behavior=".CircleProgressBehavior"
custom:circle_prefix_text="$ "
custom:circle_suffix_text=""/>
Sample Code on Github

Android Design Support Library FAB in a ViewPager Fragment with Coordinator Layout

I'm trying to get a Floating Action Button from the Android Design Support Library inside a Fragment which is inside a ViewPager. I've 4 tabs and I want the FAB in only one of the Tabs. My layout are as follows:
main_layout.xml
<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.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways" />
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
app:tabIndicatorHeight="3dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
list_fragment_with_fab.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:padding="5dip"
android:background="#color/Transparent_White"
android:fitsSystemWindows="false"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.lucasr.twowayview.widget.TwoWayView
android:id="#+id/clip_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:twowayview_layoutManager="ListLayoutManager" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/add_list_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_margin="16dp"
android:src="#drawable/ic_list_add"
app:layout_anchor="#+id/clip_recycler_view"
app:layout_anchorGravity="bottom|right|end" />
Now the problem is, the FAB does not work as per the design specs. i.e the hiding and showing of the fab doesn't work. Also, the FAB is not at it's initial place when the fragment is activated. I've attached screenshots below to make it more clear.
The in the left image, as you can see, the FAB is off the screen. When I scroll, the Toolbar will hide (think Play Store App) and the tabs remain, that time the FAB will scroll up.
Is this a bug in the Design Support library? Or is my layout incorrect? Also, I want the FAB in only one of the fragments, so adding in the main_layout.xml kinda defeats that purpose.
It's not strictly a bug, but just the way they've implemented it.
It's because of this:
app:layout_behavior="#string/appbar_scrolling_view_behavior"
This behavior doesn't manipulate the size of the ViewPager, it just pushes it off the bottom of the screen when the AppBarLayout is expanded.
Your fragment is filling the entire size of the ViewPager and so correctly aligns the FAB to the bottom right of the ViewPager container; but because the ViewPager container is offset, the bottom right is offscreen.
The "proper" way of using a FloatingActionButton in this context is by having the activity show it - like this:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="bubblebearapps.co.uk.nfcapi.MainActivity">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/appbar_padding_top"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay">
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="#dimen/fab_margin"
android:src="#android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
You then change the FloatingActionButton's size, icon and onClickBehaviour based on what page is shown in the ViewPager using the OnPageChangeListener interface.
To make the FloatingActionButton scroll off the bottom when you're scolling the RecyclerView, you must create a Behaviour! This is one I used in a different project:
public class ScrollOffBottomBehaviour extends CoordinatorLayout.Behavior<View> {
private int mViewHeight;
private ObjectAnimator mAnimator;
public ScrollOffBottomBehaviour(Context context, AttributeSet attrs) {
super();
}
#Override
public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) {
mViewHeight = child.getHeight();
return super.onLayoutChild(parent, child, layoutDirection);
}
#Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child,
View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
if(mAnimator == null || !mAnimator.isRunning()){
int totalScroll = (dyConsumed + dyUnconsumed);
int targetTranslation = totalScroll > 0 ? mViewHeight : 0;
mAnimator = ObjectAnimator.ofFloat(child, "translationY", targetTranslation);
mAnimator.start();
}
}
#Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
}
}
Set this onto your FloatingActionButton with app:layout_behaviour and all should be well...

Categories

Resources