I have CoordinatorLayout and following items inside it:
AppBarLayout with collapsable toolbar;
NestedScrollView with some content
I want to programmatically scroll my NestedScrollView up until Collapsable Toolbar is collapsed.
I tried the code like this:
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
if (behavior != null) {
behavior.onNestedPreScroll(coordinatorLayout, appBarLayout, nestedScrollView, 0, 1000, new int[2]);
}
But it just scrolls up and collapses the AppBar layout itself and NestedScrollView remains on its place.
So,the question is how to scroll NestedScrollView up and made Collapsable Toolbar to collapse?
I know the issue related somehow with Coordinator Layout's behavior, but I can't realize what is missed.
Here is the exact layout:
<android.support.design.widget.CoordinatorLayout
android:id="#+id/event_coordinator_layout"
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"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<!-- some content -->
<android.support.v7.widget.Toolbar
android:id="#+id/quick_return_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:id="#+id/nested_scroll_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<!-- some content -->
</android.support.v4.widget.NestedScrollView>
CollapsingToolbarLayout is collapsed base on AppBarLayout offseting tops and bottom of its children. You are offseting it properly with calling behavior nested pre scroll method. NestedScrollView needs to be scrolled by the same amount too:
int targetScroll = mNestedScrollView.getScrollY() + 1000;
mNestedScrollView.scrollTo(0,targetScroll);
mNestedScrollView.setSmoothScrollingEnabled(true);
ViewCompat.setNestedScrollingEnabled(mNestedScrollView, false);
final int currentScrollY = mNestedScrollView.getScrollY();
ViewCompat.postOnAnimationDelayed(mNestedScrollView, new Runnable() {
int currentY = currentScrollY;
#Override
public void run() {
if(currentScrollY == mNestedScrollView.getScrollY()){
ViewCompat.setNestedScrollingEnabled(mNestedScrollView, true);
return;
}
currentY = mNestedScrollView.getScrollY();
ViewCompat.postOnAnimation(mNestedScrollView, this);
}
}, 10);
Related
I'm using AppBarLayout with CollapsingToolbarLayout that can change its height when the user scroll screen. Also, I have fragments under AppBarLayout. One of the fragment has a custom bottom navigation bar 1. And when CollapsingToolbarLayout is fully opened I can't see Bottom Nav Bar for this fragment. I want to pin it somehow.2
I tried to use layout_behavior="#string/appbar_scrolling_view_behavior" not on fragment but on view in this fragment but it didn't work.
Main.xml
<android.support.v4.widget.DrawerLayout>
<android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.AppBarLayout
android:layout_height="#dimen/app_bar_height">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/toolbar_layout"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:toolbarId="#+id/toolbar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:gravity="center_vertical|start"
app:layout_collapseMode="pin"
app:navigationIcon="#mipmap/burger"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/content_frame"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.design.widget.CoordinatorLayout>
</android.support.v4.widget.DrawerLayout>
some_fragment.xml
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--This view I want to pin-->
<View
android:id="#+id/bottom_navigation_bar"
android:layout_width="match_parent"
android:layout_height="63dp"
android:layout_alignParentBottom="true"
android:orientation="vertical">
</View>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/bottom_navigation_bar"
android:layout_alignParentTop="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</RelativeLayout>
I managed to find some strange solution for this. This code is for Xamarin Android C#. I just made the bottom margin according to AppBarLayout offset
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.home_view);
var appBar = FindViewById<AppBarLayout>(Resource.Id.app_bar);
appBar.AddOnOffsetChangedListener(this);
}
public void OnOffsetChanged(AppBarLayout appBarLayout, int verticalOffset)
{
var minHeight = Resources.GetDimension(Resource.Dimension.app_bar_min_height);
var fragment = SupportFragmentManager.FindFragmentById(Resource.Id.content_frame);
if (fragment is DashboardView) {
var layout = fragment.View.FindViewById<RelativeLayout>(Resource.Id.dashboard_layout);
var param = new FrameLayout.LayoutParams(LayoutParams.MatchParent, LayoutParams.WrapContent);
param.SetMargins(0, 0, 0, verticalOffset + (int)minHeight);
layout.LayoutParameters = param;
}
}
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
}
}
Yesterday I am playing with CoordinatorLayout with TabView
1) What is my target ?
CoordinatorLayout with TabView
When I scroll up at that time One View As show in .GIF move down.
and Stick on the Top of the TabView (inside AppBar).
2) Where I reached ?
CoordinatorLayout with TabView with pretty scrolling.
TabView with Appbar Stop Scrolling At Top after Then Scroll RecyclerView.
3) Where I stuck ?
When I scroll Up One View Scroll Down but TabView Stick At Top not like 1st gif.
4) Code snippet
Xml file
<android.support.design.widget.AppBarLayout
android:id="#+id/main.appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<!--- ADD TAB_LAYOUT HERE -->
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/main.collapsing"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll">
<ImageView
android:id="#+id/main.backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
android:src="#drawable/abc"
app:layout_collapseMode="none" />
<!-- ADD ANY THING THAT GETS SCROLLED ALL THE WAY UP WITH TOOLBAR -->
</android.support.design.widget.CollapsingToolbarLayout>
<!-- our tablayout to display tabs -->
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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" />
Java file (move upper view down code)
AppBarLayout ab = (AppBarLayout) findViewById(R.id.main_appbar);ab.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
#Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
int ScrollStart = (ab.getHeight() - tabLayout.getHeight() - llTop.getHeight() - llTop.getHeight());
int scrollStop = (ab.getHeight() - tabLayout.getHeight() - llTop.getHeight());
if ((-verticalOffset) > ScrollStart && (-verticalOffset) < scrollStop) {
llTop.setVisibility(View.VISIBLE);
llTop.setTranslationY(((-verticalOffset) - ScrollStart) - llTop.getHeight());
Log.e("point", "" + ((-verticalOffset) - ScrollStart));
} else if ((-verticalOffset) >= scrollStop) {
llTop.setVisibility(View.VISIBLE);
} else {
llTop.setVisibility(View.INVISIBLE);
}
}
});
It's tricky little bit..
just try to setMinimumHeight of your CollapsingToolbarLayout like this way and do let me know.
CollapsingToolbarLayout layoutCollapsing = (CollapsingToolbarLayout) rootView.findViewById(R.id.layoutCollapsing);
layoutCollapsing.setMinimumHeight(120);
here calculate your minimum height as per your need and set it in place of setMinimumHeight(120) value.
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);
}