Show toolbar when view pager is swiped. [CoordinatorLayout] - android

in my app I am using a viewpager with 3 fragments. In two of those I have recuclerviews. I took advatngage of the new Coordinator layout and made my toolbar hides/shows when scrolling on a recyclerview. My problem is the following Say the user is scrolling on a recyclerview list in fragment A and thus the toolbar is hidden. After that, the user performs a swipe and goes to fragment B which does not have a recycle view to scroll so the toolbar can appear again. Is there a way I can alter the layout_behaviout so that when the user swipes on the view pager the toolbar to be shown?
NOTE: IF it is possible, I want to achieve that only using XML.
This is my main_layput xml code:
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:fab="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.studentsins.lust.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
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:popupTheme="#style/AppTheme.PopupOverlay"
app:layout_scrollFlags="scroll|enterAlways" />
<android.support.design.widget.TabLayout
android:id="#+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/NavigationTab"/>
</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"/>
<include layout="#layout/content_main"/>
<com.getbase.floatingactionbutton.FloatingActionsMenu
android:id="#+id/floatingActionMenu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
fab:fab_addButtonColorNormal="#color/blood_orange"
fab:fab_addButtonColorPressed="#color/dirtyWhite"
fab:fab_addButtonPlusIconColor="#color/dirtyWhite"
fab:fab_addButtonSize = "normal"
fab:fab_labelStyle="#style/menu_labels_style"
fab:fab_labelsPosition="left"
app:layout_anchor="#id/viewpager"
app:layout_anchorGravity="bottom|end">
<com.getbase.floatingactionbutton.FloatingActionButton
android:id="#+id/createPlanBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
fab:fab_colorNormal="#color/blood_orange"
fab:fab_title="Create a plan"
fab:fab_size="normal"
app:fab_icon="#drawable/ic_event_white_48dp"
fab:fab_colorPressed="#color/dirtyWhite"/>
<com.getbase.floatingactionbutton.FloatingActionButton
android:id="#+id/changeStatusBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
fab:fab_colorNormal="#color/blood_orange"
fab:fab_size="normal"
app:fab_icon="#drawable/ic_textsms_white_48dp"
fab:fab_title="Change status"
fab:fab_colorPressed="#color/dirtyWhite"/>
</com.getbase.floatingactionbutton.FloatingActionsMenu>
</android.support.design.widget.CoordinatorLayout>

You should be able to do this using the ViewPager.OnPageChangedListener and based on the page u are on which u can get from the onPageSelected(int position) method that is part of the listener. Hope this is what u are looking for.

I was able to achieve this by referencing the AppBarLayout and calling the "setExtended" method like that:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//Make sure that the fab is visible when scrolling the pages...
MainActivity.mFloatingActionsMenu.animate()
.setDuration(150)
.translationY(0);
//show the toolbar
expandToolbar();
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
my expandToolbar method:
public void expandToolbar(){
//setExpanded(boolean expanded, boolean animate)
AppBarLayout appBarLayout = (AppBarLayout)findViewById(R.id.appBarLayouy);
appBarLayout.setExpanded(true, true);
}

Related

Slide up panel like in stock Dialer on Nexus phones

In my app, when user clicks on a contact icon, I want to display contact's information in a slide, that appears from bottom and can be swiped up to cover the whole screen, or swiped down to dissapear.
I tried to use the SlidingUpPanel from umano, but I couldn't make it work as I need, because it was not designed for that.
Is there some library for that?
This is called a BottomSheet in Android. You can create your own bottom sheet simply using a view as a Child of a coordinator layout.
Add to your app build.gradle:
dependencies{
compile 'com.android.support:design:24.1.1'
}
And then use these classes to create your own:
BottomSheetDialogFragment
BottomSheetDialog
BottomSheetBehavior
BottomSheetBehavior.BottomSheetCallback
Here is an overly simplified demo to show how to make a FrameLayout act as a bottom sheet, you can replace the contents of the FrameLayout with a Fragment and pass information to it as needed. (in your case whichever contact was clicked):
The layout:
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.sample.bottomsheetsample.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
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:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.kdotj.bottomsheetsample.MainActivity"
tools:showIn="#layout/activity_main">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
</RelativeLayout>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
android:src="#android:drawable/ic_dialog_email" />
<!-- Notice a few things:
app:layout_behavior="#string/bottom_sheet_behavior" required to act as bottom sheet
app:behavior_peekHeight="244dp" this is the collapsed state height
app:behavior_hideable="true" lets you swipe to dismiss the sheet
android:elevation="#dimen/design_appbar_elevation" puts the sheet over the action bar
-->
<FrameLayout
android:id="#+id/fl_bottomSheet"
app:layout_behavior="#string/bottom_sheet_behavior"
app:behavior_peekHeight="244dp"
app:behavior_hideable="true"
android:elevation="#dimen/design_appbar_elevation"
android:background="#777"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.AppCompatTextView
android:layout_gravity="center|top"
android:text="Hello, Bottom Sheet!"
android:padding="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
</android.support.design.widget.CoordinatorLayout>
the Activity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FrameLayout frameLayout = (FrameLayout) findViewById(R.id.fl_bottomSheet);
final BottomSheetBehavior behavior = BottomSheetBehavior.from(frameLayout);
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
//... Handle the state changes
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
//.. handle sliding if you want to
}
});
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
});
}
}

Fixed view in ViewPager's content layout, under CoordinatorLayout

My app has an Activity with TabLayout, and 3 Fragments. In Activity's layout, I have CoordinatorLayout with ViewPager. I need to animate toolbar as well.
Now In Fragments layout, I need to put a fixed TextView at the bottom.
Given below is the XML of activity and fragment.
I am facing the problem that this fixed TextView in Fragment's
layout is going under the bottom navigation bar and is scrolling also,
that I don't want.
How can achieve this ?
activity.xml
<?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/clMain"
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/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|snap"
app:popupTheme="#style/AppTheme.PopupOverlay">
<TextView
android:id="#+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/toolbar"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorWhite"
android:orientation="vertical">
<android.support.v4.widget.NestedScrollView
android:id="#+id/rlParent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
android:layout_weight="1"
android:fitsSystemWindows="true"
android:orientation="vertical">
</android.support.v4.widget.NestedScrollView>
<TextView
android:id="#+id/tvConfirmOrder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorDarkGreen"
android:gravity="center"
android:padding="10dp"
android:text="#string/confirm_order"
android:textColor="#color/colorWhite"
android:textSize="18sp"
android:textStyle="bold"></TextView>
</LinearLayout>
As you want this bottom fixed TextView for each fragment, it can be solved by transferring your TextView to activity.xml and adding a custom behavior to it.
So, firstly, create a class that represents custom behavior:
public class FixedBottomViewBehavior extends CoordinatorLayout.Behavior<View> {
public FixedBottomViewBehavior() {
}
public FixedBottomViewBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
//making our bottom view depends on ViewPager (or whatever that have appbar_scrolling_view_behavior behavior)
return dependency instanceof ViewPager;
}
#Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
if (ViewCompat.isLaidOut(parent)) {
//attach our bottom view to the bottom of CoordinatorLayout
child.setY(parent.getBottom() - child.getHeight());
//set bottom padding to the dependency view to prevent bottom view from covering it
dependency.setPadding(dependency.getPaddingLeft(), dependency.getPaddingTop(),
dependency.getPaddingRight(), child.getHeight());
}
return false;
}
}
There is no magic here, we're just making our bottom view dependent on some view with appbar_scrolling_view_behavior (in our case it's ViewPager) and then attaching it to the bottom of CoordinatorLayout and setting some padding to dependency.
Secondly, change your activity.xml, by adding your TextView there:
<?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/clMain"
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="wrap_content"
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|snap"
app:popupTheme="#style/AppTheme.PopupOverlay">
<TextView
android:id="#+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/toolbar"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<TextView
android:id="#+id/tvConfirmOrder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#color/colorDarkGreen"
android:gravity="center"
android:padding="10dp"
android:text="#string/confirm_order"
android:textColor="#color/colorWhite"
android:textSize="18sp"
android:textStyle="bold"
app:layout_behavior="your.package.name.FixedBottomViewBehavior" />
</android.support.design.widget.CoordinatorLayout>
Make sure you've removed your TextView from fragment.xml. Don't forget also to change your.package.name.FixedBottomViewBehavior to your package name exactly.
Voila! That should work like a charm with proper toolbar animation and fixed view at the bottom.
In addition: if you don't know how to pass your OnClick event to your fragments you can follow this way in your Activity:
public interface OnConfirmOrderClickListener {
void onConfirmOrderClick(View v);
}
public Fragment getActiveFragment() {
String name = makeFragmentName(pager.getId(), pager.getCurrentItem());
return getSupportFragmentManager().findFragmentByTag(name);
}
public String makeFragmentName(int viewId, int index) {
return "android:switcher:" + viewId + ":" + index;
}
tvConfirmOrder.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment current = getActiveFragment();
if (current instanceof OnConfirmOrderClickListener)
((OnConfirmOrderClickListener) current).onConfirmOrderClick(v);
}
});
Don't forget to make your fragments implements OnConfirmOrderClickListener. Hope that helps!
For those who want the button to appear only in one fragment, it's possible to use onPageChangeListener of ViewPager to make the button scroll with the ViewPager
viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
updateButtonPosition(position, positionOffsetPixels);
}
});
//Move the button according to the tab you want it to be fixed.
//Here is the 3rd tab of a 3 tab viewPager, for instance
private void updateButtonPosition(int position, int positionOffsetPixels) {
int fixedRewardXPos;
if (position == 0) {
fixedRewardXPos = viewPager.getWidth() * 2 - positionOffsetPixels;
} else if (position == 1) {
fixedRewardXPos = viewPager.getWidth() - positionOffsetPixels;
} else {
fixedRewardXPos = -positionOffsetPixels;
}
//Add getLeft() to keep the button to its former position in it's fragment
aButton.setX(fixedRewardXPos + aButton.getLeft());
}

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...

Offset in Google Map View when used with TabLayout and CoordinatorLayout

I have a TabLayout and a ViewPager with scrolling behavior.
In the ViewPager, there are two layouts: -
(RecyclerView + ProgressBar)
Google Map View
1) When the tab is at RecyclerView, the tabLayout will scroll/hide away when the Recycler view is scrolled. This part is working as expected.
2) However, when the tab is at the Google Map View, the whole view is shifted down.
the Zoom buttons and google copyright info is out of view. (See image below). When the scrolling behavior is commented off, the map is shown correctly, but recyclerView no longer hides the tablayout.
Is there a way to show the map correctly and at the same time allow the tablayout to be hidden when the recyclerview is displayed?
The following is the xml for the coordinatorLayout
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
style="#style/TabLayoutTheme"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="4dp"
android:theme="#style/TabLayoutTheme"
app:layout_scrollFlags="scroll|enterAlways"
app:tabSelectedTextColor="#color/primary_text" />
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
Remove the scrolling view behavior from XML and add it dynamically when other than MapFragment is selected.After update changes your xml should look like below.
Your Xml File
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
style="#style/TabLayoutTheme"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="4dp"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.design.widget.CoordinatorLayout>
In your activity which are handling tabs.Add "addOnPageCahgeListener" like below.Where you will turn on/off layout-behaviour on the basis of selected tab
mTabLayout = (TabLayout) findViewById(R.id.tab_layout);
appBarLayout = (AppBarLayout) findViewById(R.id.appbar_layout);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
switch (position) {
case 0:
turnOffTabLayoutScrolling();
break;
case 1:
turnOnTabLayoutScrolling();
break;
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
Code to Turn off/on scrolling
public void turnOffTabLayoutScrolling() {
//turn off scrolling
AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) mTabLayout.getLayoutParams();
toolbarLayoutParams.setScrollFlags(0);
CoordinatorLayout.LayoutParams appBarLayoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
appBarLayoutParams.setBehavior(null);
appBarLayout.setLayoutParams(appBarLayoutParams);
}
public void turnOnTabLayoutScrolling() {
//turn on scrolling
AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) mTabLayout.getLayoutParams();
toolbarLayoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);
mTabLayout.setLayoutParams(toolbarLayoutParams);
CoordinatorLayout.LayoutParams appBarLayoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
appBarLayoutParams.setBehavior(new AppBarLayout.Behavior());
appBarLayout.setLayoutParams(appBarLayoutParams);
}
If you are facing problem following the guide line below is the link of complete TabLayout Sample with map on one tab.
https://www.dropbox.com/s/z5gu45b55juuhsv/TabLayoutSample.zip
This is the adaptation from Waleed Sarwar's answer that I eventually used.
Sometimes, the app take a few seconds to redraw the map correctly, but it works for my purpose.
XML:
I left the layout_behavior in ViewPager intact
I removed the layoutScroll flags in TabLayout
xml file:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
style="#style/TabLayoutTheme"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="4dp"
android:theme="#style/TabLayoutTheme"
app:tabSelectedTextColor="#color/primary_text" />
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
for the codes, this i what i used: -
I added "setExpanded(true)" when in the 'non-scrolling' page
this forces the tablayout to always be displayed on page change (regardless of wether it was previously hidden)
method is in support library V23
I didn't use appbarLayout (CoordinatorLayout.LayoutParams) in my codes (seem to still work)
I implemented viewPager.addOnPageChangeListener verbatim.
Codes: -
private void turnTabLayoutScrolling(boolean onScrolling) {
AppBarLayout.LayoutParams toolbarLayoutParams
= (AppBarLayout.LayoutParams) tabLayout.getLayoutParams();
if (onScrolling) {
toolbarLayoutParams.setScrollFlags(
AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
| AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);
}else{
toolbarLayoutParams.setScrollFlags(0);
appbarLayout.setExpanded(true);
}
tabLayout.setLayoutParams(toolbarLayoutParams);
}

Toolbar not showing with swipe to refresh

I'm trying to implement collapsing tollbar with swipe to refresh and recyclerview.
When I'm trying to scroll (when recyclerview has only one item) toolbar collapse,
but when I'm trying to scroll down to show toolbar, it's impossible because swipe down causes swipe to refresh. When recyclerview has more item it works perfectly.
Link to gif with problem
<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:elevation="1dp"
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"
android:elevation="1dp"
android:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/activity_main_swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<android.support.v7.widget.RecyclerView
android:id="#+id/cities_list"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</android.support.v4.widget.SwipeRefreshLayout>
<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="16dp"
android:elevation="1dp"
android:onClick="addCity"
android:src="#drawable/ic_plus_white_36dp"
app:borderWidth="0dp" />
Update: This bug has been fixed in the version 23.1.1 of support library
You can set onOffsetChanged listener for your AppBarLayout and prevent to swipe refreshing until AppBarLayout layout offset 0.
This is good example :
https://gist.github.com/blackcj/001a90c7775765ad5212
I managed it by adding the following implementation of OnOffsetChangedListener in fragment:
#Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (collapsingToolbarLayout.getHeight() + verticalOffset < 2 * ViewCompat.getMinimumHeight(collapsingToolbarLayout)) {
swipeRefreshLayout.setEnabled(false);
} else {
swipeRefreshLayout.setEnabled(true);
}
}
#Override
public void onResume() {
super.onResume();
appBarLayout.addOnOffsetChangedListener(this);
}
#Override
public void onPause() {
super.onPause();
appBarLayout.removeOnOffsetChangedListener(this);
}

Categories

Resources