Reputation: 7179
In my application I have a collapsing Toolbar. If I start a specific Fragment I want to collapse the Toolbar so it behaves like a "normal" one and that the user can not expend it by himself. Here is my layout which I use for my Toolbar:
<android.support.design.widget.AppBarLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/appBarLayout"
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:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:titleEnabled="false"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:src="@drawable/drawer_background"
app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
android:layout_width="match_parent"
android:layout_height="172dp"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"
android:minHeight="100dp" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolBar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|enterAlways" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
I also can collapse the layout from code like so:
appBarLayout.setExpanded(false, false);
final AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams();
params.setScrollFlags(0);
collapsingToolbarLayout.setLayoutParams(params);
But this does not help. If the user swipes down from the Toolbar it will expand.
Do you have any ideas why?
Upvotes: 16
Views: 6585
Reputation: 1
the simplest thing to do is to extend the class AppBarLayout.Behavior
public class AppBarBehavior extends AppBarLayout.Behavior {
private boolean locked;
public AppBarBehavior() {
super();
}
public AppBarBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onStartNestedScroll(@NonNull CoordinatorLayout parent, @NonNull AppBarLayout child, @NonNull View directTargetChild, View target, int nestedScrollAxes, int type) {
if (locked) return false; // Lock when content scrolled
else return super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes, type);
}
@Override
public boolean onTouchEvent(@NonNull CoordinatorLayout parent, @NonNull AppBarLayout child, @NonNull MotionEvent ev) {
if (locked) return false; // Lock when appBar swiped
else return super.onTouchEvent(parent, child, ev);
}
public void lock(boolean locked) {
this.locked = locked;
}
}
Then set new layout_behavior in XML
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/main.appbar"
android:layout_width="match_parent"
android:layout_height="200dp"
android:fitsSystemWindows="false"
app:layout_behavior="<full path to package>.AppBarBehavior">
And now you can manage locking with:
AppBarLayout appBar = findViewById(R.id.main_appbar);
appBar.setExpanded(false, true); // collapse appBar
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBar.getLayoutParams();
AppBarBehavior behavior = (AppBarBehavior) params.getBehavior();
behavior.lock(true); // lock appBar
Upvotes: 0
Reputation: 9009
Well try setting some parameters to toolBar, tabLayout programatically, I have ViewPager
changing flags on onPageSelected(int)
@Override
public void onPageSelected(int position) {
AppBarLayout.LayoutParams params = new AppBarLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
if (position == 3) {//listen for scrolls only for Fragment 3
params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);
toolBar.setLayoutParams(params);//hide as per scroll
params = new AppBarLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);
tabLayout.setLayoutParams(params);//always visible
} else {
appBarLayout.setExpanded(false, true);
params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED);
toolBar.setLayoutParams(params);//don't listen to scrolls
tabLayout.setLayoutParams(params);//dont listen to scrolls
}
}
Use/Set above flags as you required. AppBarLayout.LayoutParams
Upvotes: 1
Reputation: 96
None of the provided solutions worked for me except this one. With this solution, i can easily manage the state of collapsing toolbar. This will prevent expanding/enable collapsing of collapsing toolbar and set title for it.
public void lockAppBar(boolean locked,String title) {
if(locked){
appBarLayout.setExpanded(false, true);
int px = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80, getResources().getDisplayMetrics());
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)appBarLayout.getLayoutParams();
lp.height = px;
appBarLayout.setLayoutParams(lp);
collapsingToolbarLayout.setTitleEnabled(false);
toolbar.setTitle(title);
}else{
appBarLayout.setExpanded(true, false);
appBarLayout.setActivated(true);
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
lp.height = (int) getResources().getDimension(R.dimen.toolbarExpandHeight);
collapsingToolbarLayout.setTitleEnabled(true);
collapsingToolbarLayout.setTitle(title);
}
}
Upvotes: 2
Reputation: 3119
The core problem is that there is no CollapsingToolbarLayout.lock();
method up until now (v23.2.1 of support design). Hopefully, this feature will be included in a future version. Until then, I'm suggesting the following workaround:
You can collapse and lock your toolbar with:
appbar.setExpanded(false,false);
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)appbar.getLayoutParams();
lp.height = (int) getResources().getDimension(R.dimen.toolbar_height);
and unlock it with:
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)appbar.getLayoutParams();
lp.height = (int) getResources().getDimension(R.dimen.nav_header_height);
However, with the above code a problem occurs:
when forcefully collapsing CoordinatorLayout the title of our Toolbar is gone and CollapsingToolbarLayout.setTitle(CharSequence title);
no longer works. To fix that we add a TextView in our Toolbar and manipulate its visibility accordingly. (we want it "gone" in a fragment that has its toolbar 'unlocked' and "visible" in a fragment that has its toolbar 'locked'.
We have to set TextView's android:textAppearance
to be the same with CollapsingToolbarLayout's app:collapsedTitleTextAppearance
to be consistent and avoid disrupting the user with different toolbar text sizes and colors.
In summary, with an interface like this:
public interface ToolbarManipulation {
void collapseToolbar();
void expandToolbar();
void setTitle(String s);
}
implemantations like these:
@Override
public void collapseToolbar(){
appbar.setExpanded(false,false);
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)appbar.getLayoutParams();
lp.height = (int) getResources().getDimension(R.dimen.toolbar_height);
toolbarCollapsedTitle.setVisibility(View.VISIBLE);
}
@Override
public void expandToolbar() {
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)appbar.getLayoutParams();
lp.height = (int) getResources().getDimension(R.dimen.nav_header_height);
toolbarCollapsedTitle.setVisibility(View.GONE);
}
@Override
public void setTitle(String s) {
collapsingToolbarLayout.setTitle(s);
toolbarCollapsedTitle.setText(s);
collapsingToolbarLayout.invalidate();
toolbarCollapsedTitle.invalidate();
}
and main xml like this:
....
<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"
app:collapsedTitleTextAppearance="@style/CollapsedAppBar"
>
<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_collapseMode="pin"
app:popupTheme="@style/AppTheme.PopupOverlay"
>
<TextView
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:visibility="gone"
android:layout_gravity="center_vertical|start"
android:gravity="center_vertical|start"
android:id="@+id/toolbar_collapsed_title"
android:textAppearance="@style/CollapsedAppBar"
/>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
......
you can lock and unlock your Toolbar as you like. Your fragments should call these functions in their onResume();
I've uploaded an example implementation here.
Note: This is just a workaround and obviously not the cleanest solution. We're waiting for a newer version of com.android.support to resolve this.
Upvotes: 21
Reputation: 2319
Do findViewById(R.id.image_view).setVisibility(View.GONE);
where image_view
is the id of the imageView in the collapsing toolbar. But if you want to do it for a specific fragment I suggest calling the same using fragment- activity communication.
Upvotes: 2
Reputation: 7183
Try to change the height of the AppBar. It works for me.
public void lockAppBar() {
int appbarHeight = (int)getResources().getDimension(R.dimen.your_fixed_appbar_height);
getView().findViewById(R.id.my_appbar).getLayoutParams().height = appbarHeight;
}
Upvotes: 2
Reputation: 2077
I'm not exactly sure if this is what you are looking for
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
behavior.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
@Override
public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
return false;
}
});
Upvotes: 13