Am I able to set the title of a CollapsingToolbarLayout via the setTitle method?
Is there also a way to set a subtitle?
If you want the subtitle to go to Toolbar when the AppBar is fully collapsed you should create your custom CoordinatorLayout.Behaviour Like this: Github Guide
But if you just want a smaller text behind the title when the AppBar is expanded you can try this layout:
<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:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="300dp"
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:expandedTitleMarginBottom="160dp"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/quila2"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textColor="#android:color/white"
android:layout_marginBottom="32dp"
android:layout_marginEnd="64dp"
android:layout_marginStart="48dp"
app:layout_collapseMode="parallax"
android:layout_gravity="bottom"
android:text="Lorem Ipsum Iran Lorem Ipsum Iran Lorem Ipsum Iran Lorem Ipsum Iran Lorem Ipsum Iran Lorem Ipsum Iran Lorem Ipsum Iran Lorem Ipsum Iran "/>
<android.support.v7.widget.Toolbar
android:id="#+id/anim_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="match_parent"
android:scrollbars="none"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:lineSpacingExtra="8dp"
android:text="#string/lorem"
android:textSize="18sp"/>
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:clickable="true"
android:src="#drawable/abc_ic_search_api_mtrl_alpha"
app:layout_anchor="#+id/appbar"
app:layout_anchorGravity="bottom|right|end" />
</android.support.design.widget.CoordinatorLayout>
Notice that here I set the AppBar height as 300dp and the app:expandedTitleMarginBottom is 160dp so the title won't go down and conflict with the out subtitle. In this example you should set CollapsingToolbarTitle dynamically in the runtime with collapsingToolbarTitle.setTitle("My Title"); method.
The result will be something like this:
Subtitle support in a CollapsingToolbarLayout is a feature that I also long for, so I created a library collapsingtoolbarlayout-subtitle:
Use it like you would on any CollapsingToolbarLayout, just add subtitle attribute on it:
<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:layout_width="match_parent"
android:layout_height="wrap_content">
<com.hendraanggrian.widget.SubtitleCollapsingToolbarLayout
android:id="#+id/subtitlecollapsingtoolbarlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentScrim="?colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:subtitle="CollapsingToolbarLayout"
app:title="Subtitle">
<!-- collapsing toolbar content goes here -->
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
app:layout_collapseMode="pin"/>
</com.hendraanggrian.widget.SubtitleCollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<!-- content goes here -->
</android.support.design.widget.CoordinatorLayout>
Try something like this, it work for me
I have created custom ViewBehavior
#Override
public boolean layoutDependsOn(CoordinatorLayout parent, HeaderView child, View dependency) {
return dependency instanceof AppBarLayout;
}
#Override
public boolean onDependentViewChanged(CoordinatorLayout parent, HeaderView child, View dependency) {
shouldInitProperties(child, dependency);
int maxScroll = ((AppBarLayout) dependency).getTotalScrollRange();
float percentage = Math.abs(dependency.getY()) / (float) maxScroll;
float childPosition = dependency.getHeight()
+ dependency.getY()
- child.getHeight()
- (getToolbarHeight() - child.getHeight()) * percentage / 2;
childPosition = childPosition - mStartMarginBottom * (1f - percentage);
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) child.getLayoutParams();
lp.leftMargin = (int) (percentage * mEndMargintLeft) + mStartMarginLeft;
lp.rightMargin = mMarginRight;
child.setLayoutParams(lp);
child.setY(childPosition);
...
return true;
}
and this my layout
<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:fitsSystemWindows="true"
>
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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="wrap_content"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
>
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
android:src="#drawable/img_nature"
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"
>
<include
android:id="#+id/toolbar_header_view"
layout="#layout/header_view"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_marginRight="#dimen/header_view_end_margin_right"
android:visibility="gone"
/>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:id="#+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
...
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<include
android:id="#+id/float_header_view"
layout="#layout/header_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="com.subtitlebehavoir.harcopro.simple.ViewBehavior"
/>
</android.support.design.widget.CoordinatorLayout>
ViewHeader layout:
<?xml version="1.0" encoding="utf-8"?>
<com.subtitlebehavoir.harcopro.simple.HeaderView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<!-- Title -->
<TextView
android:id="#+id/header_view_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:textSize="18sp"
/>
<!-- Subtitle -->
<TextView
android:id="#+id/header_view_sub_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:textSize="16sp"
/>
</com.subtitlebehavoir.harcopro.simple.HeaderView>
Here is the modified version of Harco's implmentation (this) given above which will also change the size of title as we expand and collapse the layout.
ViewBehavior.java
public class ViewBehavior extends CoordinatorLayout.Behavior<HeaderView> {
private static final float MAX_SCALE = 0.5f;
private Context mContext;
private int mStartMarginLeft;
private int mEndMargintLeft;
private int mMarginRight;
private int mStartMarginBottom;
private boolean isHide;
public ViewBehavior(Context context, AttributeSet attrs) {
mContext = context;
}
#Override
public boolean layoutDependsOn(CoordinatorLayout parent, HeaderView child, View dependency) {
return dependency instanceof AppBarLayout;
}
#Override
public boolean onDependentViewChanged(CoordinatorLayout parent, HeaderView child, View dependency) {
shouldInitProperties(child, dependency);
int maxScroll = ((AppBarLayout) dependency).getTotalScrollRange();
float percentage = Math.abs(dependency.getY()) / (float) maxScroll;
// Set scale for the title
float size = ((1 - percentage) * MAX_SCALE) + 1;
child.setScaleXTitle(size);
child.setScaleYTitle(size);
// Set position for the header view
float childPosition = dependency.getHeight()
+ dependency.getY()
- child.getHeight()
- (getToolbarHeight() - child.getHeight()) * percentage / 2;
childPosition = childPosition - mStartMarginBottom * (1f - percentage);
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) child.getLayoutParams();
lp.leftMargin = (int) (percentage * mEndMargintLeft) + mStartMarginLeft;
lp.rightMargin = mMarginRight;
child.setLayoutParams(lp);
child.setY(childPosition);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
if (isHide && percentage < 1) {
child.setVisibility(View.VISIBLE);
isHide = false;
} else if (!isHide && percentage == 1) {
child.setVisibility(View.GONE);
isHide = true;
}
}
return true;
}
private void shouldInitProperties(HeaderView child, View dependency) {
if (mStartMarginLeft == 0)
mStartMarginLeft = mContext.getResources().getDimensionPixelOffset(R.dimen.header_view_start_margin_left);
if (mEndMargintLeft == 0)
mEndMargintLeft = mContext.getResources().getDimensionPixelOffset(R.dimen.header_view_end_margin_left);
if (mStartMarginBottom == 0)
mStartMarginBottom = mContext.getResources().getDimensionPixelOffset(R.dimen.header_view_start_margin_bottom);
if (mMarginRight == 0)
mMarginRight = mContext.getResources().getDimensionPixelOffset(R.dimen.header_view_end_margin_right);
}
public int getToolbarHeight() {
int result = 0;
TypedValue tv = new TypedValue();
if (mContext.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
result = TypedValue.complexToDimensionPixelSize(tv.data, mContext.getResources().getDisplayMetrics());
}
return result;
}
}
HeaderView.java
public class HeaderView extends LinearLayout {
#Bind(R.id.header_view_title)
TextView title;
#Bind(R.id.header_view_sub_title)
TextView subTitle;
public HeaderView(Context context) {
super(context);
}
public HeaderView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public HeaderView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public HeaderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
ButterKnife.bind(this);
}
public void bindTo(String title) {
bindTo(title, "");
}
public void bindTo(String title, String subTitle) {
hideOrSetText(this.title, title);
hideOrSetText(this.subTitle, subTitle);
}
private void hideOrSetText(TextView tv, String text) {
if (text == null || text.equals(""))
tv.setVisibility(GONE);
else
tv.setText(text);
}
public void setScaleXTitle(float scaleXTitle) {
title.setScaleX(scaleXTitle);
title.setPivotX(0);
}
public void setScaleYTitle(float scaleYTitle) {
title.setScaleY(scaleYTitle);
title.setPivotY(30);
}
}
I also had the same issue. In the end I made a LinearLayout that contains the title and subtitle and then set the expandedTitleTextAppearance to be transparent - effectively hiding the Toolbar title when the Layout is expanded. Using this approach the toolbar collapses over the LinearLayout and in the end only shows the title in the collapsed state.
The full xml is here:
<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="#dimen/series_detail_header_height"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<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:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:expandedTitleTextAppearance="#style/TransparentText"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_collapseMode="parallax">
<ImageView
android:id="#+id/image_view"
android:layout_width="match_parent"
android:layout_height="#dimen/series_detail_header_image_height"
android:scaleType="centerCrop"/>
<LinearLayout
android:id="#+id/header_text_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="?attr/colorPrimary"
android:gravity="center_vertical"
android:minHeight="#dimen/series_detail_text_layout_height"
android:orientation="vertical"
android:paddingLeft="20dp"
android:paddingRight="10dp"
android:paddingTop="10dp">
<TextView
android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="My title"
android:textColor="#android:color/white"
android:textSize="24sp"/>
<TextView
android:id="#+id/subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:textSize="17sp"/>
</LinearLayout>
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#drawable/shape_toolbar_black_gradient"
app:layout_collapseMode="pin"/>
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="top"
app:layout_collapseMode="pin"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/show_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:paddingTop="#dimen/toolbar_height"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/></android.support.design.widget.CoordinatorLayout>
Make sure that your style also extends TextAppearance or the app will crash if your Design Support Library is v22.2.0 :
<style name="TransparentText" parent="#android:style/TextAppearance">
<item name="android:textColor">#00666666</item>
</style>
This bug appears to be fixed in v22.2.1 (https://code.google.com/p/android/issues/detail?id=178674):
Here is the modified version of Harco's implementation (this) with title and subtitle centred when expanded.
activity_main.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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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="wrap_content"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
android:src="#drawable/img_nature"
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">
<include
android:id="#+id/toolbar_header_view"
layout="#layout/header_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="#dimen/header_view_end_margin_right"
android:visibility="gone" />
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:id="#+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<include
android:id="#+id/float_header_view"
layout="#layout/header_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_behavior="com.subtitlebehavoir.harcopro.simple.ViewBehavior" />
</android.support.design.widget.CoordinatorLayout>
dimens.xml
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="header_view_end_margin_left">56dp</dimen>
<dimen name="header_view_end_margin_right">14dp</dimen>
<dimen name="header_view_start_margin_bottom">14dp</dimen>
</resources>
header_view.xml
<?xml version="1.0" encoding="utf-8"?>
<com.subtitlebehavoir.harcopro.simple.HeaderView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<!-- Title -->
<TextView
android:id="#+id/header_view_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:textColor="#android:color/white"
android:textSize="18sp" />
<!-- Subtitle -->
<TextView
android:id="#+id/header_view_sub_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/header_view_title"
android:maxLines="1"
android:textColor="#android:color/white"
android:textSize="16sp" />
</com.subtitlebehavoir.harcopro.simple.HeaderView>
HeaderView.java
public class HeaderView extends RelativeLayout {
#Bind(R.id.header_view_title)
TextView title;
#Bind(R.id.header_view_sub_title)
TextView subTitle;
Context context;
public HeaderView(Context context) {
super(context);
this.context = context;
}
public HeaderView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
public HeaderView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public HeaderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
this.context = context;
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
ButterKnife.bind(this);
}
public void bindTo(String title) {
bindTo(title, "");
}
public void bindTo(String title, String subTitle) {
hideOrSetText(this.title, title);
hideOrSetText(this.subTitle, subTitle);
}
private void hideOrSetText(TextView tv, String text) {
if (text == null || text.equals(""))
tv.setVisibility(GONE);
else
tv.setText(text);
}
public void setScaleXTitle(float scaleXTitle) {
title.setScaleX(scaleXTitle);
title.setPivotX(0);
}
public void setScaleYTitle(float scaleYTitle) {
title.setScaleY(scaleYTitle);
title.setPivotY(30);
}
public TextView getTitle() {
return title;
}
public TextView getSubTitle() {
return subTitle;
}
}
and ViewBehavior.java
public class ViewBehavior extends CoordinatorLayout.Behavior<HeaderView> {
private static final float MAX_SCALE = 0.5f;
private Context mContext;
private int mStartMarginLeftTitle;
private int mStartMarginLeftSubTitle;
private int mEndMargintLeft;
private int mMarginRight;
private int mStartMarginBottom;
private boolean isHide;
public ViewBehavior(Context context, AttributeSet attrs) {
mContext = context;
}
#Override
public boolean layoutDependsOn(CoordinatorLayout parent, HeaderView child, View dependency) {
return dependency instanceof AppBarLayout;
}
#Override
public boolean onDependentViewChanged(CoordinatorLayout parent, HeaderView child, View dependency) {
shouldInitProperties(child, dependency);
int maxScroll = ((AppBarLayout) dependency).getTotalScrollRange();
float percentage = Math.abs(dependency.getY()) / (float) maxScroll;
// Set scale for the title
float size = ((1 - percentage) * MAX_SCALE) + 1;
child.setScaleXTitle(size);
child.setScaleYTitle(size);
// Set position for the header view
float childPosition = dependency.getHeight()
+ dependency.getY()
- child.getHeight()
- (getToolbarHeight() - child.getHeight()) * percentage / 2;
childPosition = childPosition - mStartMarginBottom * (1f - percentage);
child.setY(childPosition);
// Set Margin for title
RelativeLayout.LayoutParams lpTitle = (RelativeLayout.LayoutParams) child.getTitle().getLayoutParams();
lpTitle.leftMargin = (int) ((mStartMarginLeftTitle) - (percentage * (mStartMarginLeftTitle - mEndMargintLeft)));
if (lpTitle.leftMargin < 20) {
lpTitle.leftMargin = 20;
}
lpTitle.rightMargin = mMarginRight;
child.getTitle().setLayoutParams(lpTitle);
// Set Margin for subtitle
RelativeLayout.LayoutParams lpSubTitle = (RelativeLayout.LayoutParams) child.getSubTitle().getLayoutParams();
lpSubTitle.leftMargin = (int) ((mStartMarginLeftSubTitle) - (percentage * (mStartMarginLeftSubTitle - mEndMargintLeft)));
if (lpSubTitle.leftMargin < 20) {
lpSubTitle.leftMargin = 20;
}
lpSubTitle.rightMargin = mMarginRight;
child.getSubTitle().setLayoutParams(lpSubTitle);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
if (isHide && percentage < 1) {
child.setVisibility(View.VISIBLE);
isHide = false;
} else if (!isHide && percentage == 1) {
child.setVisibility(View.GONE);
isHide = true;
}
}
return true;
}
private void shouldInitProperties(HeaderView child, View dependency) {
if (mStartMarginLeftTitle == 0)
mStartMarginLeftTitle = getStartMarginLeftTitle(child);
if (mStartMarginLeftSubTitle == 0)
mStartMarginLeftSubTitle = getStartMarginLeftSubTitle(child);
if (mEndMargintLeft == 0)
mEndMargintLeft = mContext.getResources().getDimensionPixelOffset(R.dimen.header_view_end_margin_left);
if (mStartMarginBottom == 0)
mStartMarginBottom = mContext.getResources().getDimensionPixelOffset(R.dimen.header_view_start_margin_bottom);
if (mMarginRight == 0)
mMarginRight = mContext.getResources().getDimensionPixelOffset(R.dimen.header_view_end_margin_right);
}
public int getStartMarginLeftTitle(HeaderView headerView) {
TextView title = headerView.getTitle();
DisplayMetrics displaymetrics = new DisplayMetrics();
WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(displaymetrics);
int width = displaymetrics.widthPixels;
int stringWidth = getStingWidth(title);
int marginLeft = (int) ((width / 2) - ((stringWidth + (stringWidth * MAX_SCALE)) / 2));
return marginLeft;
}
public int getStartMarginLeftSubTitle(HeaderView headerView) {
TextView subTitle = headerView.getSubTitle();
DisplayMetrics displaymetrics = new DisplayMetrics();
WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(displaymetrics);
int width = displaymetrics.widthPixels;
int stringWidth = getStingWidth(subTitle);
int marginLeft = ((width / 2) - (stringWidth / 2));
return marginLeft;
}
public int getStingWidth(TextView textView) {
Rect bounds = new Rect();
Paint textPaint = textView.getPaint();
textPaint.getTextBounds(textView.getText().toString(), 0, textView.getText().toString().length(), bounds);
return bounds.width();
}
public int getToolbarHeight() {
int result = 0;
TypedValue tv = new TypedValue();
if (mContext.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
result = TypedValue.complexToDimensionPixelSize(tv.data, mContext.getResources().getDisplayMetrics());
}
return result;
}
}
i managed to make it using MotionLayout in your activity.xml make the following
<androidx.constraintlayout.motion.widget.MotionLayout 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"
app:layoutDescription="#xml/motion_scene_collapsing_toolbar_with_subtitle"
tools:context=".CollapsingToolbarWithSubtitleActivity">
<ImageView
android:id="#+id/toolbar_image_expanded"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="?attr/colorPrimary"
android:contentDescription="#null"
android:scaleType="centerCrop"
android:src="#drawable/img1" />
<!-- transformPivotX and transformPivotY is to move text horizontal
or vertical in it's own boundaries when the text is smaller than it's boundaries-->
<TextView
android:id="#+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is title"
android:textColor="#color/white"
android:textSize="30sp"
android:transformPivotX="0sp"
android:transformPivotY="25sp" />
<TextView
android:id="#+id/toolbar_sub_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
android:text="This is sub title"
android:textColor="#color/white"
android:textSize="20sp"
android:transformPivotX="6sp"
android:transformPivotY="0sp" />
<!-- you can put any thing here ex (RecyclerView or Image or .... any thing).-->
<TextView
android:id="#+id/tv_remaining_body"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="remaining body what ever it is"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/toolbar_image_expanded" />
</androidx.constraintlayout.motion.widget.MotionLayout>
and then for #xml/motion_scene_collapsing_toolbar_with_subtitle add the following
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ConstraintSet android:id="#+id/expanded">
<Constraint
android:id="#+id/toolbar_image_expanded"
android:layout_height="200dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<CustomAttribute
app:attributeName="imageAlpha"
app:customIntegerValue="255" />
</Constraint>
<Constraint
android:id="#+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginBottom="42dp"
android:scaleX="1.0"
android:scaleY="1.0"
app:layout_constraintBottom_toBottomOf="#+id/toolbar_image_expanded"
app:layout_constraintStart_toStartOf="parent" />
<Constraint
android:id="#+id/toolbar_sub_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleX="1.0"
android:scaleY="1.0"
app:layout_constraintStart_toStartOf="#+id/toolbar_title"
app:layout_constraintTop_toBottomOf="#+id/toolbar_title" />
</ConstraintSet>
<ConstraintSet android:id="#+id/collapsed">
<Constraint
android:id="#+id/toolbar_image_expanded"
android:layout_height="?attr/actionBarSize"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<CustomAttribute
app:attributeName="imageAlpha"
app:customIntegerValue="0" />
</Constraint>
<Constraint
android:id="#+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginBottom="0dp"
android:scaleX="0.7"
android:scaleY="0.7"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#id/toolbar_image_expanded" />
<Constraint
android:id="#+id/toolbar_sub_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleX="0.7"
android:scaleY="0.7"
app:layout_constraintBottom_toBottomOf="#id/toolbar_image_expanded"
app:layout_constraintStart_toStartOf="#id/toolbar_title"
app:layout_constraintTop_toBottomOf="#+id/toolbar_title" />
</ConstraintSet>
<Transition
app:constraintSetEnd="#id/collapsed"
app:constraintSetStart="#id/expanded">
<OnSwipe
app:dragDirection="dragUp"
app:touchAnchorId="#id/tv_remaining_body"
app:touchAnchorSide="top" />
</Transition>
</MotionScene>
and if you want to know more about MotionLayout
visit this https://codelabs.developers.google.com/codelabs/motion-layout/#0
Related
I got help from links and other links but it didn't help me and my problem was not solved
MY PROBLEM: I have ViewPager with 3 Fragment that 2 of them contain RecycleView with dynamic data!
Now the ViewPage gets the biggest height !!!! I want to set the height of the fragment as the original size!
my code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
style="#style/CardStyle"
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">
<com.duolingo.open.rtlviewpager.RtlViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_marginTop="#dimen/default_margin_double"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/tab_layout" />
<com.google.android.material.tabs.TabLayout
android:id="#+id/tab_layout"
style="#style/TabbedCard"
android:layout_width="match_parent"
android:layout_height="#dimen/tabbed_card_tab_layout_height"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tabGravity="fill"
app:tabMode="scrollable"
app:tabPaddingTop="#dimen/default_margin_half"
app:tabTextAppearance="#style/investTab" />
</androidx.constraintlayout.widget.ConstraintLayout>
and one of my fragment that contains RecyclerView :
<LinearLayout 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="wrap_content"
android:layout_gravity="center"
android:scrollbarStyle="insideOverlay"
android:orientation="vertical"
tools:context=".mvvm.screens.investment.view.fragment.tabs.RequestListFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/account_list"
style="#style/InvestmentRecyclerView"
android:scrollbarStyle="insideOverlay"
tools:listitem="#layout/investment_request_item"
android:paddingBottom="#dimen/default_margin"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
android:id="#+id/loading"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateTint="?attr/cardTitle"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<include
android:id="#+id/view_error"
layout="#layout/view_error"
android:visibility="gone" />
<include
android:id="#+id/view_empty"
layout="#layout/no_investment_found"
android:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
Finally, I Create custom class from ViewPager like this :
public class WrappedHeightTabbedCardViewPager extends NonSwipeableViewPager {
private int currentPagePosition = 0;
public WrappedHeightTabbedCardViewPager(#NonNull Context context) {
super(context);
}
public WrappedHeightTabbedCardViewPager(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
View child = getChildAt(currentPagePosition);
if (child != null) {
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
heightMeasureSpec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY);
}
if (heightMeasureSpec != 0) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void reMeasureCurrentPage(int position) {
currentPagePosition = position;
requestLayout();
}
}
Good morning everyone!
I'm facing a scrolling issue in my app. I have a Coordinator Layout and a Listview. I want the top layout to be collapsing when I scroll in my listview.
I searched and found that this is not possible without a NestedScrollView so I added one.
The problem is that when I scroll, only the coordinator layout is scrolling.
As an example, when I scroll to the down, the listview is stuck like that:
I also tried to set the layout_height of my Listview to match_parent but it doesn't change anything.
Here is my code:
main.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:fitsSystemWindows="true"
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/ActionBarNoShadowLight"
android:fitsSystemWindows="true"
app:elevation="0dp">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_height="match_parent"
android:layout_width="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginStart="48dp"
app:expandedTitleMarginEnd="64dp"
android:fitsSystemWindows="true">
<ImageView
android:id="#+id/mainImage"
android:layout_width="175dp"
android:layout_height="175dp"
android:layout_marginTop="50dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:scaleType="fitCenter"
app:srcCompat="#drawable/ic_document"
android:fitsSystemWindows="true"
app:layout_collapseMode="parallax" />
<android.support.v7.widget.Toolbar
android:id="#+id/edit_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/BackgroundWhite"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:id="#+id/scroll"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:clipToPadding="false"
android:scrollbars="none"
android:fillViewport="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ListView
android:id="#+id/lstTask"
android:layout_height="match_parent"
android:layout_width="fill_parent"
android:nestedScrollingEnabled="true"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:divider="#null"
/>
<ImageView
android:id="#+id/empty"
android:layout_height="200dp"
android:layout_width="200dp"
android:layout_marginTop="50dp"
android:scaleType="fitCenter"
android:gravity="center"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
app:srcCompat="#drawable/bg_notasks" />
</FrameLayout>
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fabAdd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="#dimen/fab_margin"
android:src="#drawable/ic_plus" />
</android.support.design.widget.CoordinatorLayout>
Thanks a lot for your future help,
Clément.
Create a NonScrollListView class like below
public class NonScrollListView extends ListView{
public NonScrollListView(Context context) {
super(context);
}
public NonScrollListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NonScrollListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
}
}
And in your xml add layout behaviour
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/ll_pro_profile_reviews"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:orientation="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<com.vanitee.services.home.customer.shops.detail.reviews.NonScrollExpandableListView
android:id="#+id/rcv_pro_profile_reviews"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/spacing_8"/>
</android.support.v4.widget.NestedScrollView>
And finally in your code where you initialize your listView you need to disable nested scrolling
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
listView.setNestedScrollingEnabled(false);
} else {
ViewCompat.setNestedScrollingEnabled(listView, false);
}
Just help you to convert Ayush Khare's code to C#, if this can help you, you could mark
#Ayush Khare's answer.
public class NonScrollListView : ListView
{
public NonScrollListView(Context context) : base(context)
{
}
public NonScrollListView(Context context, IAttributeSet attrs) : base(context, attrs)
{
}
public NonScrollListView(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
{
}
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int heightMeasureSpec_custom = MeasureSpec.MakeMeasureSpec(int.MaxValue >> 2, MeasureSpecMode.AtMost);
base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
ViewGroup.LayoutParams params2 = LayoutParameters;
params2.Height = MeasuredHeight;
}
}
Disable nested scrolling :
if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop)
{
listView.NestedScrollingEnabled = false;
}
else
{
ViewCompat.SetNestedScrollingEnabled(listView, false);
}
I have a very simple scenario involving a NestedScrollView and LinearLayout where I want the LinearLayout to translate as the NestedScrollView scrolls up. Here is the layout in picture:(the concerned child view is the second last LinearLayout with the Id of linearlayout )
<?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"
tools:context="com.example.snapsboardmainpage.MainActivity"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp">
<android.support.v4.widget.NestedScrollView
android:id="#+id/nested_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/linearLayout3"
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="vertical"
android:layout_gravity="top"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="0dp"
android:layout_marginRight="0dp"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginLeft="0dp"
app:layout_constraintLeft_toLeftOf="parent">
</LinearLayout>
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="0dp"
android:layout_height="112dp"
android:orientation="vertical"
android:background="#android:color/holo_green_light"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/linearLayout3">
</LinearLayout>
<android.support.v4.view.ViewPager
android:id="#+id/id_viewpager_photosvideos_albums"
android:layout_width="0dp"
android:layout_height="1000dp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/linearLayout1">
<android.support.design.widget.TabLayout
android:id="#+id/id_tab_photosvideos_albums"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top">
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.design.widget.TabLayout>
</android.support.v4.view.ViewPager>
</android.support.constraint.ConstraintLayout>
</android.support.v4.widget.NestedScrollView>
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="vertical"
android:layout_gravity="top"
app:layout_behavior="com.example.snaps.TopActionBarBehavior"
android:background="#android:color/holo_blue_light">
</LinearLayout>
<LinearLayout
android:id="#+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="56dp"
android:orientation="vertical"
android:layout_gravity="bottom"
android:background="#android:color/holo_orange_light">
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
And, the concerned behavior(TopActionBarBehavior) as follows:
public class TopActionBarBehavior extends CoordinatorLayout.Behavior<LinearLayout> {
private static final String TAG = "TopActionBarBehavior";
private int thresholdScrollDistance;
private int mNestedScrollViewInitialTop;
public TopActionBarBehavior() {
}
public TopActionBarBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean layoutDependsOn(CoordinatorLayout parent, LinearLayout child, View dependency) {
return dependency instanceof NestedScrollView;
}
#Override
public boolean onDependentViewChanged(CoordinatorLayout parent, LinearLayout child, View dependency) {
// Translate the child view as per the NestedScrollView
int currentNestedScrollViewTop = dependency.getTop();
// Have we scrolled up?
if(currentNestedScrollViewTop > mNestedScrollViewInitialTop){
// Translate the child view by the same distance
child.setTranslationY(currentNestedScrollViewTop - mNestedScrollViewInitialTop);
}
return true;
}
#Override
public boolean onLayoutChild(CoordinatorLayout parent, LinearLayout child, int layoutDirection) {
View topBar = parent.findViewById(R.id.linearLayout);
int topBarHeight = topBar.getHeight();
View nestedScrollView = parent.findViewById(R.id.nested_container);
mNestedScrollViewInitialTop = nestedScrollView.getTop();
View profileBar = parent.findViewById(R.id.linearLayout1);
int profileBarHeight = profileBar.getHeight();
View dummyTopBarUnderlay = parent.findViewById(R.id.linearLayout3);
int dummyTopBarHeight = dummyTopBarUnderlay.getHeight();
View tabLayout = parent.findViewById(R.id.id_tab_photosvideos_albums);
int tabLayoutHeight = tabLayout.getHeight();
thresholdScrollDistance = profileBarHeight + dummyTopBarHeight + tabLayoutHeight;
return super.onLayoutChild(parent, child, layoutDirection);
}
}
I tried debugging and layoutDependsOn() is getting called as it should be but onDependentViewChanged() is getting called only once.
Finally found the answer after countless hours of debugging. My NestedScrollView wasn't actually moving at all; it's content was moving the whole time which didn't trigger this method. For scroll events, we can tap onto the onNested*() methods in the Behavior class. Simple.
I am trying to add a fragment on Activity which is having a custom view.
private void loadMonitorPage(){
fragmentManager = getFragmentManager();
MonitorFragment monitorFragment = new MonitorFragment();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.MainContentFrameLayout,monitorFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
Here MainContentFrameLayout is the second block I have mentioned in First image.
This is my Fragment Layout xml(fragment_monitor)
<LinearLayout 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"
android:background="#color/colorContentApp"
tools:context="fragments.MonitorFragment">
<monitorView.GridView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorAccent"
/>
</LinearLayout>
instead of this Custom View is covering the full screen
This is my CustomView Class
public class GridView extends View {
private Paint mgridpaint;
private float mGridViewWidth;
private float mGridViewHeight;
private Canvas mGridCanvas;
public GridView(Context context) {
super(context);
}
public GridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public GridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// TODO: consider storing these as member variables to reduce
// allocations per draw cycle.
int paddingLeft = getPaddingLeft();
int paddingTop = getPaddingTop();
int paddingRight = getPaddingRight();
int paddingBottom = getPaddingBottom();
int contentWidth = getWidth() - paddingLeft - paddingRight;
int contentHeight = getHeight() - paddingTop - paddingBottom;
mgridpaint = new Paint();
mgridpaint.setColor(Color.rgb(0,255,0));
mGridCanvas = canvas;
mGridViewWidth = contentWidth;
mGridViewHeight = contentHeight;
//drawGrid();
}
}
This is my parent Layout. Second FrameLayout where I am adding this Fragment
<LinearLayout 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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.mactrical.mindoter.MainActivity"
android:weightSum="10"
android:orientation="vertical"
tools:showIn="#layout/app_bar_main">
<FrameLayout
android:id="#+id/ECGDetailsFrameLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1.5"
android:background="#color/colorHeaderApp">
</FrameLayout>
<FrameLayout
android:id="#+id/MainContentFrameLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="8">
</FrameLayout>
<FrameLayout
android:id="#+id/ECGFooterFrameLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:background="#color/colorFooterApp">
</FrameLayout>
</LinearLayout>
Please help me!!!!! :-(
I figured out the problem
Here in this layout I had to use 0dp for my height instead of wrap_content
<LinearLayout 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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.mactrical.mindoter.MainActivity"
android:weightSum="10"
android:orientation="vertical"
tools:showIn="#layout/app_bar_main">
<FrameLayout
android:id="#+id/ECGDetailsFrameLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.5"
android:background="#color/colorHeaderApp">
</FrameLayout>
<FrameLayout
android:id="#+id/MainContentFrameLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="8">
</FrameLayout>
<FrameLayout
android:id="#+id/ECGFooterFrameLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.5"
android:background="#color/colorFooterApp">
</FrameLayout>
</LinearLayout>
I want to build a collapsing Toolbar with views add to CollapsingToolBarLayout dynamically. so i need to set AppBarLayout wrap_content.
Then i create a phone & tablet module in android studio 2.2 and select "Scrolling Activity".
i got a page like this:
and then i changed the height of AppBarLayout from#dimen/app_bar_height to wrap_content
<?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="demo.billy.com.test_design.ScrollingActivity">
<android.support.design.widget.AppBarLayout android:id="#+id/app_bar"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:fitsSystemWindows="true" android:theme="#style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout android:id="#+id/toolbar_layout"
android:layout_width="match_parent" android:layout_height="match_parent"
android:fitsSystemWindows="true" app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<android.support.v7.widget.Toolbar android:id="#+id/toolbar"
android:layout_width="match_parent" android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin" app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_scrolling" />
<android.support.design.widget.FloatingActionButton android:id="#+id/fab"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_margin="#dimen/fab_margin" app:layout_anchor="#id/app_bar"
app:layout_anchorGravity="bottom|end" app:srcCompat="#android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
now the page is like below:
ToolBar is covered by system statusbar. It looks like fitSystemWindow="true" does not work.
i change fitSystemWindow to "false" on AppBarLayout, if there is only one child in CollaspingToolBarLayout, it looks like works. but, when i add an imageView to CollapsintToolBarLayout, statusbar background is not transparent.
<?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="demo.billy.com.test_design.ScrollingActivity">
<android.support.design.widget.AppBarLayout android:id="#+id/app_bar"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:fitsSystemWindows="false" android:theme="#style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout android:id="#+id/toolbar_layout"
android:layout_width="match_parent" android:layout_height="match_parent"
android:fitsSystemWindows="true" app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="#+id/image_collapsing"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.5"
android:scaleType="centerCrop"
android:src="#drawable/img"
/>
<android.support.v7.widget.Toolbar android:id="#+id/toolbar"
android:layout_width="match_parent" android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin" app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_scrolling" />
<android.support.design.widget.FloatingActionButton android:id="#+id/fab"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_margin="#dimen/fab_margin" app:layout_anchor="#id/app_bar"
app:layout_anchorGravity="bottom|end" app:srcCompat="#android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
what i need to do is:
ToolBar must not be covered by system statusbar
CollapsingToolbarLayout may has only one child: ToolBar
CollapsingToolbarLayout may has many children: ToolBar + ImageView + etc...
is there anyone help me?
my own solution:
override CollapsingToolbarLayout.onMeasure(), add status_bar_height to layout height if necessary:
public class MyCollapsingToolbarLayout extends CollapsingToolbarLayout {
public MyCollapsingToolbarLayout(Context context) {
super(context);
}
public MyCollapsingToolbarLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyCollapsingToolbarLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Toolbar toolbar = null;
int otherHeight = 0;
//calculate max visible toolbar height
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
if (view instanceof Toolbar) {
toolbar = (Toolbar) view;
} else if(view.getVisibility() != GONE) {
otherHeight = Math.max(otherHeight, view.getHeight());
}
}
if (toolbar != null) {
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
final int paddingWidth = getPaddingLeft() + getPaddingRight();
final int paddingHeight = getPaddingTop() + getPaddingBottom();
int height = paddingHeight;
LayoutParams lp = (LayoutParams) toolbar.getLayoutParams();
final int marginWidth = lp.rightMargin + lp.leftMargin;
final int marginHeight = lp.topMargin + lp.bottomMargin;
toolbar.measure(
getChildMeasureSpec(widthMeasureSpec, paddingWidth + marginWidth, lp.width),
getChildMeasureSpec(heightMeasureSpec, paddingHeight + marginHeight, lp.height)
);
int toolbarHeight = toolbar.getMeasuredHeight() + marginHeight;
height += toolbarHeight;
height += getStatusBarHeight();
if (height > otherHeight) {
setMeasuredDimension((modeWidth == MeasureSpec.EXACTLY) ? sizeWidth : getWidth()
, (modeHeight == MeasureSpec.EXACTLY) ? sizeHeight : height);
}
}
}
private int getStatusBarHeight() {
Resources res = Resources.getSystem();
int resId = res.getIdentifier("status_bar_height", "dimen", "android");
if (resId > 0) {
return res.getDimensionPixelSize(resId);
}
return 0;
}
}