带有自定义视图的 CollapsingToolbarLayout
Posted
技术标签:
【中文标题】带有自定义视图的 CollapsingToolbarLayout【英文标题】:CollapsingToolbarLayout with a custom view 【发布时间】:2015-12-29 06:40:42 【问题描述】:我正在尝试使用自定义视图实现 CollapsingToolbarLayout,但我无法做到:
我想做什么(对不起,我不能发布图片,所以它在 imgur 上):
展开后,标题是带有图像和标题的个人资料屏幕
不展开(滚动),图像和标题将在工具栏上
但我看到的一切都没有按预期工作
我是这个和棒棒糖动画的新手,所以如果有人可以帮助我,我将非常感激!
(我没有发布示例代码,因为我没有相关内容)
【问题讨论】:
【参考方案1】:我的解决方案
我有相同的场景要实现,所以我从 dog 示例开始,并对其进行了一些更改,使其与您描述的完全一样。我的代码可以作为该项目的 fork 找到,请参阅 https://github.com/hanscappelle/CoordinatorBehaviorExample
最重要的变化在于布局:
<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_
android:layout_
>
<android.support.design.widget.AppBarLayout
android:id="@+id/main.appbar"
android:layout_
android:layout_
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
>
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/main.collapsing"
android:layout_
android:layout_
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
>
<FrameLayout
android:id="@+id/main.framelayout.title"
android:layout_
android:layout_
android:layout_gravity="bottom"
>
<LinearLayout
android:id="@+id/main.linearlayout.title"
android:layout_
android:layout_
android:layout_gravity="bottom|center_horizontal"
android:orientation="vertical"
android:paddingBottom="@dimen/spacing_small"
>
<TextView
android:layout_
android:layout_
android:layout_gravity="center_horizontal"
android:gravity="bottom|center_horizontal"
android:text="@string/tequila_name"
android:textColor="@android:color/white"
android:textSize="@dimen/textsize_xlarge"
/>
<TextView
android:layout_
android:layout_
android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/spacing_xxsmall"
android:text="@string/tequila_tagline"
android:textColor="@android:color/white"
/>
</LinearLayout>
</FrameLayout>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_
android:layout_
android:scrollbars="none"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
>
<TextView
android:layout_
android:layout_
android:lineSpacingExtra="@dimen/spacing_xsmall"
android:padding="@dimen/spacing_normal"
android:text="@string/lorem"
android:textSize="@dimen/textsize_medium"
/>
</android.support.v4.widget.NestedScrollView>
<android.support.v7.widget.Toolbar
android:id="@+id/main.toolbar"
android:layout_
android:layout_
android:background="@color/primary"
app:layout_anchor="@id/main.collapsing"
app:theme="@style/ThemeOverlay.AppCompat.Dark"
app:title=""
>
<LinearLayout
android:layout_
android:layout_
android:orientation="horizontal"
>
<Space
android:layout_
android:layout_
/>
<TextView
android:id="@+id/main.textview.title"
android:layout_
android:layout_
android:layout_marginLeft="8dp"
android:gravity="center_vertical"
android:text="@string/tequila_title"
android:textColor="@android:color/white"
android:textSize="@dimen/textsize_large"
/>
</LinearLayout>
</android.support.v7.widget.Toolbar>
<de.hdodenhof.circleimageview.CircleImageView
android:layout_
android:layout_
android:layout_gravity="top|center_horizontal"
android:layout_marginTop="@dimen/spacing_normal"
android:src="@drawable/ninja"
app:border_color="@android:color/white"
app:border_
app:finalHeight="@dimen/image_final_width"
app:finalXPosition="@dimen/spacing_small"
app:finalYPosition="@dimen/spacing_small"
app:finalToolbarHeight="?attr/actionBarSize"
app:layout_behavior="saulmm.myapplication.AvatarImageBehavior"
/>
</android.support.design.widget.CoordinatorLayout>
在我优化的 AvatarImageBehaviour 类中,仅将头像从原始位置移动到属性中配置的位置。因此,如果您希望图像从另一个位置移动,只需在布局内移动它即可。当您这样做时,请确保 AppBarLayout 仍然是它的兄弟,否则将不会在代码中找到它。
package saulmm.myapplication;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import android.view.View;
import de.hdodenhof.circleimageview.CircleImageView;
public class AvatarImageBehavior extends CoordinatorLayout.Behavior<CircleImageView>
// calculated from given layout
private int startXPositionImage;
private int startYPositionImage;
private int startHeight;
private int startToolbarHeight;
private boolean initialised = false;
private float amountOfToolbarToMove;
private float amountOfImageToReduce;
private float amountToMoveXPosition;
private float amountToMoveYPosition;
// user configured params
private float finalToolbarHeight, finalXPosition, finalYPosition, finalHeight;
public AvatarImageBehavior(
final Context context,
final AttributeSet attrs)
if (attrs != null)
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AvatarImageBehavior);
finalXPosition = a.getDimension(R.styleable.AvatarImageBehavior_finalXPosition, 0);
finalYPosition = a.getDimension(R.styleable.AvatarImageBehavior_finalYPosition, 0);
finalHeight = a.getDimension(R.styleable.AvatarImageBehavior_finalHeight, 0);
finalToolbarHeight = a.getDimension(R.styleable.AvatarImageBehavior_finalToolbarHeight, 0);
a.recycle();
@Override
public boolean layoutDependsOn(
final CoordinatorLayout parent,
final CircleImageView child,
final View dependency)
return dependency instanceof AppBarLayout; // change if you want another sibling to depend on
@Override
public boolean onDependentViewChanged(
final CoordinatorLayout parent,
final CircleImageView child,
final View dependency)
// make child (avatar) change in relation to dependency (toolbar) in both size and position, init with properties from layout
initProperties(child, dependency);
// calculate progress of movement of dependency
float currentToolbarHeight = startToolbarHeight + dependency.getY(); // current expanded height of toolbar
// don't go below configured min height for calculations (it does go passed the toolbar)
currentToolbarHeight = currentToolbarHeight < finalToolbarHeight ? finalToolbarHeight : currentToolbarHeight;
final float amountAlreadyMoved = startToolbarHeight - currentToolbarHeight;
final float progress = 100 * amountAlreadyMoved / amountOfToolbarToMove; // how much % of expand we reached
// update image size
final float heightToSubtract = progress * amountOfImageToReduce / 100;
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) child.getLayoutParams();
lp.width = (int) (startHeight - heightToSubtract);
lp.height = (int) (startHeight - heightToSubtract);
child.setLayoutParams(lp);
// update image position
final float distanceXToSubtract = progress * amountToMoveXPosition / 100;
final float distanceYToSubtract = progress * amountToMoveYPosition / 100;
float newXPosition = startXPositionImage - distanceXToSubtract;
//newXPosition = newXPosition < endXPosition ? endXPosition : newXPosition; // don't go passed end position
child.setX(newXPosition);
child.setY(startYPositionImage - distanceYToSubtract);
return true;
private void initProperties(
final CircleImageView child,
final View dependency)
if (!initialised)
// form initial layout
startHeight = child.getHeight();
startXPositionImage = (int) child.getX();
startYPositionImage = (int) child.getY();
startToolbarHeight = dependency.getHeight();
// some calculated fields
amountOfToolbarToMove = startToolbarHeight - finalToolbarHeight;
amountOfImageToReduce = startHeight - finalHeight;
amountToMoveXPosition = startXPositionImage - finalXPosition;
amountToMoveYPosition = startYPositionImage - finalYPosition;
initialised = true;
来源
最常见的例子是https://github.com/saulmm/CoordinatorBehaviorExample 列出的狗。这是一个很好的例子,但确实在扩展视图的中间有工具栏,背景图像也会移动。在我的示例中删除了所有内容。
在http://www.devexchanges.info/2016/03/android-tip-custom-coordinatorlayout.html 可以找到另一种解释,但由于在狗示例中也发现了引用的云/海背景图像,因此显然是建立在另一个之上。
我还发现这个 SO 问题获得了赏金,但无法真正找出最终解决方案是什么 Add icon with title in CollapsingToolbarLayout
最后,这应该是一个可以完成工作的工作库。我已经检查过了,但最初的图像没有居中,我宁愿研究我以前看过的狗的例子。见https://github.com/datalink747/CollapsingAvatarToolbar
阅读更多
http://saulmm.github.io/mastering-coordinator http://www.androidauthority.com/using-coordinatorlayout-android-apps-703720/ https://developer.android.com/reference/android/support/design/widget/CoordinatorLayout.html https://guides.codepath.com/android/handling-scrolls-with-coordinatorlayout
【讨论】:
嗨,我在使用layout_behavior
时遇到了问题。如何使用来自不同包的 Behavior 子类?当我从外部包(utils)中使用它时,它会抛出 Class-Not-Found Exception。我使用了完整的包名。但它在同一个包中工作。你能告诉我如何从不同的包中使用它吗?
很好的例子,升级到 androidx 组件仍然有效!以上是关于带有自定义视图的 CollapsingToolbarLayout的主要内容,如果未能解决你的问题,请参考以下文章