带有自定义视图的 CollapsingToolbarLayout [英] CollapsingToolbarLayout with a custom view

查看:33
本文介绍了带有自定义视图的 CollapsingToolbarLayout的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用自定义视图实现 CollapsingToolbarLayout,但我无法做到:

我想做什么(抱歉,我不能发布图片,所以它在 imgur 上):

展开后,标题是带有图片和标题的个人资料屏幕

未展开(滚动时),图片和标题将在工具栏上

但是我看到的一切都没有像我预期的那样工作

我是这个和棒棒糖动画的新手,所以如果有人能帮助我,我将不胜感激!

(我不发布示例代码,因为我没有与发布相关的内容)

解决方案

我的解决方案

我有同样的场景要实现,所以我从狗的例子开始,并做了一些改变,让它像你描述的那样工作.我的代码可以作为该项目的一个分支找到,请参阅

最重要的变化在于布局:

在我优化的 AvatarImageBehaviour 类中,只将头像从原始位置移动到属性中配置的位置.因此,如果您希望图像从另一个位置移动,只需在布局内移动它.这样做时,请确保 AppBarLayout 仍然是它的兄弟,否则在代码中找不到它.

package saulmm.myapplication;导入 android.content.Context;导入 android.content.res.TypedArray;导入 android.support.design.widget.AppBarLayout;导入 android.support.design.widget.CoordinatorLayout;导入 android.util.AttributeSet;导入 android.view.View;导入 de.hdodenhof.circleimageview.CircleImageView;公共类 AvatarImageBehavior 扩展了 CoordinatorLayout.Behavior{//根据给定的布局计算私人 int startXPositionImage;私人 int startYPositionImage;私人 int startHeight;私人 int startToolbarHeight;私有布尔初始化 = 假;私人浮动 amountOfToolbarToMove;私有浮点量 amountOfImageToReduce;私人浮动 amountToMoveXPosition;私人浮动 amountToMoveYPosition;//用户配置参数私人浮动 finalToolbarHeight,finalXPosition,finalYPosition,finalHeight;公共头像图像行为(最终的上下文上下文,最终属性集属性){如果(属性!= 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();}}@覆盖public boolean layoutDependsOn(最终的 CoordinatorLayout 父级,最后的 CircleImageView 孩子,最终视图依赖){返回 AppBarLayout 的依赖实例;//如果你想让另一个兄弟依赖依赖}@覆盖公共布尔 onDependentViewChanged(最终的 CoordinatorLayout 父级,最后的 CircleImageView 孩子,最终视图依赖){//使子(化身)与依赖项(工具栏)的大小和位置发生变化,使用布局中的属性进行初始化initProperties(子项,依赖项);//计算依赖移动的进度float currentToolbarHeight = startToolbarHeight + dependency.getY();//工具栏的当前展开高度//不要低于配置的最小计算高度(它确实通过了工具栏)currentToolbarHeight = currentToolbarHeight <最终工具栏高度?finalToolbarHeight : 当前工具栏高度;最终浮动量AlreadyMoved = startToolbarHeight - currentToolbarHeight;最终浮动进度 = 100 * amountAlreadyMoved/amountOfToolbarToMove;//我们达到了多少%的扩展//更新图片大小最终 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);//更新图片位置最终浮点距离XToSubtract = 进度* amountToMoveXPosition/100;最终浮动距离YToSubtract = progress * amountToMoveYPosition/100;float newXPosition = startXPositionImage - distanceXToSubtract;//newXPosition = newXPosition <结束位置?endXPosition : newXPosition;//不要越过结束位置child.setX(newXPosition);child.setY(startYPositionImage - distanceYToSubtract);返回真;}私有无效initProperties(最后的 CircleImageView 孩子,最终视图依赖){如果(!初始化){//表单初始布局startHeight = child.getHeight();startXPositionImage = (int) child.getX();startYPositionImage = (int) child.getY();startToolbarHeight = dependency.getHeight();//一些计算字段amountOfToolbarToMove = startToolbarHeight - finalToolbarHeight;amountOfImageToReduce = startHeight - finalHeight;amountToMoveXPosition = startXPositionImage - finalXPosition;amountToMoveYPosition = startYPositionImage - finalYPosition;初始化 = 真;}}}

来源

最常见的例子是 https://github.com/saulmm/CoordinatorBehaviorExample.这是一个很好的例子,但确实在展开视图中间有工具栏,背景图像也会移动.在我的示例中删除了所有内容.

另一种解释见 http://www.devexchanges.info/2016/03/android-tip-custom-coordinatorlayout.html 但由于引用了云/海背景图像,在狗的例子中也发现了一个明显建立在另一个之上.

我还发现了这个 SO 问题并获得了赏金,但无法真正找出最终解决方案是什么 在CollapsingToolbarLayout中添加带有标题的图标

最后,这应该是一个可以完成工作的工作库.我已经检查过了,但最初的图像没有居中,我宁愿研究我以前看过的狗的例子.请参阅 https://github.com/datalink747/CollapsingAvatarToolbar

更多阅读

http://saulmm.github.io/mastering-coordinatorhttp://www.androidauthority.com/using-coordinatorlayout-android-apps-703720/https://developer.android.com/reference/android/support/design/widget/CoordinatorLayout.htmlhttps://guides.codepath.com/android/handling-scrolls-with-coordinatorlayout

I'm trying to implement the CollapsingToolbarLayout with a custom view, but I'm unable to do it :

What I want to do (sorry I can't post images so it's on imgur) :

Expanded, the header is a profile screen with image and title

Not expanded (on scroll), the image and title will be on the toolbar

But everything I saw wasn't working as I expected

I'm new to this and lollipop animations so if someone could help me I'll be very grateful !

(I don't post sample code because I don't have something relevant to post)

解决方案

My Solution

I had the same scenario to implement so I started with the dog example and made some changes for it to work exactly like you describe. My code can be found as a fork on that project, see https://github.com/hanscappelle/CoordinatorBehaviorExample

Most important changes are in the 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.support.design.widget.AppBarLayout
    android:id="@+id/main.appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    >

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/main.collapsing"
        android:layout_width="match_parent"
        android:layout_height="@dimen/expanded_toolbar_height"
        app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
        >

        <FrameLayout
            android:id="@+id/main.framelayout.title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            >

            <LinearLayout
                android:id="@+id/main.linearlayout.title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom|center_horizontal"
                android:orientation="vertical"
                android:paddingBottom="@dimen/spacing_small"
                >

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    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_width="wrap_content"
                    android:layout_height="wrap_content"
                    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_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: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_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="@color/primary"
    app:layout_anchor="@id/main.collapsing"
    app:theme="@style/ThemeOverlay.AppCompat.Dark"
    app:title=""
    >

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        >

        <Space
            android:layout_width="@dimen/image_final_width"
            android:layout_height="@dimen/image_final_width"
            />

        <TextView
            android:id="@+id/main.textview.title"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            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_width="@dimen/image_width"
    android:layout_height="@dimen/image_width"
    android:layout_gravity="top|center_horizontal"
    android:layout_marginTop="@dimen/spacing_normal"
    android:src="@drawable/ninja"
    app:border_color="@android:color/white"
    app:border_width="@dimen/border_width"
    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>

And in the AvatarImageBehaviour class that I optimised for only moving the avatar from the original position to the position configured in the attributes. So if you want the image to move from another location just move it within the layout. When you do so make sure the AppBarLayout is still a sibling of it or it won't be found in code.

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;
    }
}
}

Sources

Most common example is the one with the dog listed at https://github.com/saulmm/CoordinatorBehaviorExample . It's a good example but indeed has the toolbar in the middle of the expanded view with a backdrop image that also moves. All that was removed in my example.

Another explanation is found at http://www.devexchanges.info/2016/03/android-tip-custom-coordinatorlayout.html but since that cloud/sea backdrop image referenced there is also found in the dog example one is clearly build on top of the other.

I also found this SO question with a bounty awarded but couldn't really find out what the final solution was Add icon with title in CollapsingToolbarLayout

And finally this should be a working library that does the work. I've checked it out but the initial image wasn't centered and I rather worked on the dog example that I had looked at before. See https://github.com/datalink747/CollapsingAvatarToolbar

More to read

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

这篇关于带有自定义视图的 CollapsingToolbarLayout的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆