What I want to achieve is something similar to an CollapsingToolbar. I've got the below layout for my activity.
The item inside the AppBarLayout can be of variable height. Therefore I was trying to set minHeight of the item programmatically, from within the onPreDraw() method of ViewTreeObserver.OnPreDrawListener.
However setting the minHeight programmatically does not seem to have any effect. The AppBarLayout does scroll off the screen completely. Setting the minHeight directly inside the XML yields the expected result and stops the AppBarLayout from scrolling off screen.
Am I missing something, or is it not possible to set the minHeight programmatically?
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="false"
>
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay"
>
<androidx.constraintlayout.widget.ConstraintLayout android:id="#+id/header" >
// Header of variable height
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView android:id="#+id/rv_items"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
clContent.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
clContent.getViewTreeObserver().removeOnPreDrawListener(this);
int minHeight = calculateMinHeight();
clHeader.setMinHeight(minHeight);
return false;
}
});
}
Try to use setMinimumHeight(minHeight) instead - this should solve the problem.
AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.app_bar);
appBarLayout.setMinimumHeight(100);
Have you tried this?
Related
When using an AppBarLayout with the standard ScrollingViewBehavior, the AppBarLayout's sibling will by default be the height of the CoordinatorLayout and the sibling's bottom will be offscreen by the height of the AppBarLayout.
In my use case, the NestedScrollView is merely a vehicle to allow for the collapsing of the toolbar, while displaying another scrollable view (fragment in this case) beneath the collapsible toolbar. The fragment is the one who contains the bottom-pinned view (FAB in this case)
Pictures below demonstrate the issue I am describing, and the code supplied is the basic XML which causes the issue.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
android:id="#+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.design.widget.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:id="#+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<LinearLayout
android:id="#+id/fragmentHolder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
The solution I found to this issue involves 2 parts.
Add padding equal to the height of the AppBarLayout to the BOTTOM of the NestedScrollView. In my case because the AppBarLayout only contained a Toolbar, the height was ?attr/actionBarSize.
android:paddingBottom="?attr/actionBarSize"
Adding a custom AppBarLayout.OnOffsetChangedListener to the AppBarLayout which changes the height of the NestedScrollView as the toolbar is collapsed.
class ScrollingOffsetFixListener(
private val nestedScrollView: NestedScrollView
): AppBarLayout.OnOffsetChangedListener {
private var originalHeight = 0
private var firstOffset = true
override fun onOffsetChanged(layout: AppBarLayout?, offset: Int) {
if(firstOffset) {
firstOffset = false
originalHeight = nestedScrollView.measuredHeight
}
val params = nestedScrollView.layoutParams
params.height = originalHeight + (offset * -1)
nestedScrollView.layoutParams = params
}
}
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):
while this is what I'd like to have when scrolling to the bottom (taken from contacts app) :
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:
And this is how it behaves with the bug of not blocking the scrolling:
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
What can I do in order to make the scrolling stop when there is no more content to show at the bottom?
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.
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)
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:
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!
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.
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);
}
I am currently developing an app wherein I need the feature to hide the toolbar on scrolling down (like Google+). I am facing issues with it's rendering of toolbar on scroll. Here is how it looks now -
I want the toolbar to simply hide on scroll down, but here the view is partially covering the toolbar and after that only toolbar is hiding.
This is the layout code -
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="org.step.main.MainActivity">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbarone"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?attr/actionBarSize"
android:clipToPadding="false"
tools:context=".MainActivity"
/>
</FrameLayout>
And here is the Activity code -
mRecyclerView = (RecyclerView) findViewById(R.id.list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.setOnScrollListener(new HidingScrollListener() {
#Override
public void onHide() {
hideViews();
}
#Override
public void onShow() {
showViews();
}
});
private void hideViews() {
mToolbar.animate().translationY(-mToolbar.getHeight()).setInterpolator(new AccelerateInterpolator(2));
}
private void showViews() {
mToolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2));
}
Can someone explain why is this happening?
I got it after reading this line on FrameLayout doc -
"Child views are drawn in a stack, with the most recently added child on top."
So, I interchanged the position of Toolbar and RecyclerView and it worked. Here, Toolbar is rendered after RecyclerView, so it is higher in the stack.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="org.step.main.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?attr/actionBarSize"
android:clipToPadding="false"
tools:context=".MainActivity"
/>
<android.support.v7.widget.Toolbar
android:id="#+id/toolbarone"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"/>
</FrameLayout>
to make a scrolling animation background is not filled, what am I doing wrong?
I am using
- DrawerLayout
- V7 toolbar
- Pager
- SwipeRefreshLayout
- RecyclerView
Activity
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar" />
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"></FrameLayout>
Fragment pager container
<RelativeLayout 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:orientation="vertical">
<com.squidit.squid.ui.widget.SlidingTabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="2dp"
android:background="#color/primaryColor"/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Fragment content
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/missionSwipeRefresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Scroll hide
private void hideViews() {
mToolbar.animate().translationY(-mToolbar.getHeight()).setInterpolator(new DecelerateInterpolator(2));
container.animate().translationY(-mToolbar.getHeight()).setInterpolator(new DecelerateInterpolator(2)).start();
}
Problem:
container rises to the top, but the space occupied by it previously on the bottom is without filling
Ilustration:
https://drive.google.com/open?id=0B-Vxv0Qpz2dqcWp5eDVRbmd3czQ&authuser=0
I had almost the same problem.
After hiding toolbar and status bar my layout looks like
http://i62.tinypic.com/qowvgi.png.
EDIT:
You may noticed that translation is not the same as moving view out.
To resize your layout with animation set LayoutParams.height on desired inside ValueAnimator.
mToolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
toolbarHeight = mToolbar.getHeight();
and finally
ValueAnimator anim = ValueAnimator.ofInt(toolbarHeight, 0);
anim.setDuration(1000);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
mToolbar.getLayoutParams().height = value.intValue();
mToolbar.requestLayout();
}
});
anim.start();
The code above hides toolbar affecting main layout to expand itself. Idea given from THAT QUESTION.
Also make sure that you are using fitsSystemWindows in layout which is about to be resize.
android:fitsSystemWindows = "true"