【问题标题】:CoordinatorLayout custom behavior with AppBarLayout使用 AppBarLayout 的 CoordinatorLayout 自定义行为
【发布时间】:2017-03-22 11:42:57
【问题描述】:

我正在尝试实现与 Telegram 类似的行为,在设置页面上,即有一个 CircleImage 向上滚动时会转到 Topbar 标题的左侧,向下滚动时会转到中间展开的 AppBarLayout。

我的工作基于这个例子:

https://github.com/saulmm/CoordinatorBehaviorExample

但在这种情况下,原始编码器正在重新创建 Topbar 两次。我不想那样做,顶栏的默认行为是我需要的,而且我想利用汉堡菜单和开箱即用的选项菜单。

这是我的视图层次结构:

DrawerLayout
  |
  |---CoordinatorLayout
       |--AppBarLayout
       |    |-CollapsingToolbarLayout
       |        |-ImageView (backdrop image)
       |        |-Toolbar
       |--NestedScrollView
       |--ImageView (circleimage avatar)

如您所见,我无法将 Toolbar 布局设为 CircleImage 的兄弟,因此我无法在 layoutDependsOn 方法上将它们绑定在一起。我尝试根据 github 存储库上的代码绑定到 AppBarLayout,但老实说,我无法理解原始代码中发生的事情。

【问题讨论】:

标签: android android-coordinatorlayout android-appbarlayout


【解决方案1】:

我的行为与扫罗的行为方式大致相同。最大的不同是我喜欢在我希望圆形图像结束的地方放置一个不可见的视图,例如 Space,然后使用该视图的边界来确定如何移动和调整圆形图像的大小。

public class CollapsingImageBehavior extends CoordinatorLayout.Behavior<View> {

    private final static int X = 0;
    private final static int Y = 1;
    private final static int WIDTH = 2;
    private final static int HEIGHT = 3;

    private int mTargetId;

    private int[] mView;

    private int[] mTarget;

    public CollapsingImageBehavior() {
    }

    public CollapsingImageBehavior(Context context, AttributeSet attrs) {

        if (attrs != null) {
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CollapsingImageBehavior);
            mTargetId = a.getResourceId(R.styleable.CollapsingImageBehavior_collapsedTarget, 0);
            a.recycle();
        }

        if (mTargetId == 0) {
            throw new IllegalStateException("collapsedTarget attribute not specified on view for behavior");
        }
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
        return dependency instanceof AppBarLayout;
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {

        setup(parent, child);

        AppBarLayout appBarLayout = (AppBarLayout) dependency;

        int range = appBarLayout.getTotalScrollRange();
        float factor = -appBarLayout.getY() / range;

        int left = mView[X] + (int) (factor * (mTarget[X] - mView[X]));
        int top = mView[Y] + (int) (factor * (mTarget[Y] - mView[Y]));
        int width = mView[WIDTH] + (int) (factor * (mTarget[WIDTH] - mView[WIDTH]));
        int height = mView[HEIGHT] + (int) (factor * (mTarget[HEIGHT] - mView[HEIGHT]));

        CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) child.getLayoutParams();
        lp.width = width;
        lp.height = height;
        child.setLayoutParams(lp);
        child.setX(left);
        child.setY(top);

        return true;
    }

    private void setup(CoordinatorLayout parent, View child) {

        if (mView != null) return;

        mView = new int[4];
        mTarget = new int[4];

        mView[X] = (int) child.getX();
        mView[Y] = (int) child.getY();
        mView[WIDTH] = child.getWidth();
        mView[HEIGHT] = child.getHeight();

        View target = parent.findViewById(mTargetId);
        if (target == null) {
            throw new IllegalStateException("target view not found");
        }

        mTarget[WIDTH] += target.getWidth();
        mTarget[HEIGHT] += target.getHeight();

        View view = target;
        while (view != parent) {
            mTarget[X] += (int) view.getX();
            mTarget[Y] += (int) view.getY();
            view = (View) view.getParent();
        }

    }
}

这是布局。我发现的一件重要的事情是,圆形图像视图需要设置一个高程,以便它在折叠模式下放置在工具栏的顶部,否则它将位于工具栏的后面并且不显示。

<?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:id="@+id/coordinator_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.krislarson.customcoordinatorlayoutbehavior.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="280dp"
            android:minHeight="108dp"
            android:fitsSystemWindows="true"
            app:title="Abby"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleGravity="center_horizontal"
            app:expandedTitleMarginTop="140dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:id="@+id/background"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:src="@drawable/sunset"
                app:layout_collapseMode="parallax"
                android:scaleType="centerCrop"/>

            <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">

                <Space
                    android:id="@+id/circle_collapsed_target"
                    android:layout_width="40dp"
                    android:layout_height="40dp"/>

            </android.support.v7.widget.Toolbar>


        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_scrolling"/>

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/circle_image_view"
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:src="@drawable/abby"
        android:layout_marginTop="220dp"
        android:layout_gravity="top|center_horizontal"
        android:elevation="8dp"
        app:border_color="@android:color/black"
        app:border_width="2dp"
        app:collapsedTarget="@id/circle_collapsed_target"
        app:layout_behavior="com.krislarson.customcoordinatorlayoutbehavior.CollapsingImageBehavior"/>

</android.support.design.widget.CoordinatorLayout>

您可以在https://github.com/klarson2/CustomCoordinatorLayoutBehavior查看整个演示项目

【讨论】:

  • 我需要稍微调整一下布局,圆形图像在棒棒糖前后的不同位置开始。
  • 什么是 ?? andtools:context="com.krislarson.customcoordinatorlayoutbehavior.ScrollingActivity"> ??
  • 它包括驱动嵌套滚动的滚动视图。如果您在创建新项目时选择“滚动活动”模板,您将获得此 XML 文件 (activity_scrolling) 以及包含 content_scrolling
  • 谢谢,这个回复真棒。你还知道 AppBarLayout 的默认扩展高度是多少吗?我试图正确定位 CircleImage 并且不想对值进行硬编码。类似于 ?attr/actionBarSize 但用于扩展工具栏?
  • 哦,好吧...我现在知道 app:elevation 与 android:elevation 不同。我不会得到那个小时回来。 :(
【解决方案2】:

一种可能性是为您的ToolBar 创建一个自定义视图,并在ToolBar 展开时隐藏红点,并显示一个带有红点的ImageView(当工具栏为崩溃)。

您可以在此答案中查看如何将自定义视图添加到 ToolBarhttps://stackoverflow.com/a/27859966/5052976

完成此操作后,只需创建一个 ImageView,当 ToolBar 展开时可见。

final CollapsingToolbarLayout collapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsingToolbarLayout);
AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appBarLayout);
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
boolean isShow = false;
int scrollRange = -1;

@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
    if (scrollRange == -1) {
        scrollRange = appBarLayout.getTotalScrollRange();
    }
    if (scrollRange + verticalOffset == 0) {
        //show toolbar dot and hide imageview dot
        isShow = true;
    } else if(isShow) {
        //hide toolbar dot and show imageview dot
        isShow = false;
    }
}
});

很遗憾,我现在无法对此进行测试,但我认为它应该可以工作 ;-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-07
    • 2018-09-20
    • 1970-01-01
    • 2016-03-12
    相关资源
    最近更新 更多