具有自定义视图的Android CollapsingToolbarLayout

时间:2015-06-17 08:30:12

标签: android android-support-library material-design android-collapsingtoolbarlayout

我正在关注Cheesesquare示例项目以了解新的设计材料库。

我想知道是否有办法使用带有ImageView,标题和副标题的自定义视图(如电报),而不是使用CollapsingToolbarLayout小部件提供的简单标题。

感谢。

3 个答案:

答案 0 :(得分:20)

我遇到了同样的问题,花了很多时间试图找到解决方案。我的解决方案是在CollapsingToolbarLayout中添加折叠视图(ImageView和TextView),然后处理代码中的转换。这样,它比从CollapsingToolbarLayout扩展更灵活,更简单。

首先,您需要使用视差属性在CollapsingToolbarLayout内添加视图:

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingTop:"80dp"
            android:src="@drawable/icon"
            app:layout_collapseMode="parallax"
            app:layout_collapseParallaxMultiplier="0.8"/> //set vertical transition here

然后在OnOffsetchangeListner

的帮助下设置视图的缩放比例
  private static final float SCALE_MINIMUM=0.5f;
  appBarLayout.setOnWorkingOffsetChange(new  ControllableAppBarLayout.OnWorkingOffsetChange() {
        @Override
        public void onOffsetChange(int offSet, float collapseDistance) {
            imageView.setScaleX(1 + (collapseDistance * SCALE_MINIMUM));
            imageView.setScaleY(1 + (collapseDistance * SCALE_MINIMUM));

            textView.setScaleX(1 + (collapseDistance * SCALE_MINIMUM));
            textView.setScaleY(1 + (collapseDistance * SCALE_MINIMUM));

            // You can also setTransitionY/X, setAlpha, setColor etc.
        }
    });

默认情况下,默认offsetChangedListener对我来说无法正常工作(您可能仍应首先尝试使用默认侦听器),因此我使用https://gist.github.com/blipinsk/3f8fb37209de6d3eea99中的ControllableAppBarLayout并添加了以下内容:

private OnWorkingOffsetChange onWorkingOffsetChange;

@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int i) {
    if (!isInEditMode()) {
        onWorkingOffsetChange.onOffsetChange(i, (float) i / appBarLayout.getTotalScrollRange());
    }
}

public void setOnWorkingOffsetChange(OnWorkingOffsetChange listener) {
    this.onWorkingOffsetChange = listener;
}

public interface OnWorkingOffsetChange {
    void onOffsetChange(int offSet, float collapseDistance);
}

唯一的问题是,你需要设置      app:contentScrim="#00000000"(透明) 对于CollapsingToolbarLayout,您的视图在折叠工具栏时仍然可见。如果你真的需要折叠背景效果,我相信你可以通过在OffsetChangeListener中设置背景ImageView的alpha来“伪造”它。 ;)

答案 1 :(得分:2)

从小部件本身似乎没有办法直接启用它,就像可以将自定义视图添加到工具栏一样。

您可以尝试执行的操作是打开CollapsingToolbarLayout.class的来源,并查看CollapsingTextHelper.class如何用于设置标题。您可以尝试通过从CollapsingToolbarLayout扩展来制作自己的小部件。

如果您之前没有创建自定义组件/视图,这些链接可以帮助您创建自定义组件/视图: Custom ViewsCustom Components

我还没有尝试过,但实际上我正在考虑尝试实现您正在寻找的类似解决方案。到目前为止,我会遵循的步骤:

  1. attrs.xml
  2. 中为字幕设置创建自定义属性
  3. 通过扩展原始版本来创建自己的MyCollapsingToolbarLayout
  4. 确保在构造函数中调用super,以便原始组件保持不变。
  5. 通过向您的组件添加新的subtitleTextHelper来创建CollapsingTextHelper
  6. 覆盖onDraw以实际绘制字幕。
  7. 使用您的字幕属性更新包含CollapingsToolbarLayout的布局(默认样式等,可能是固定的字幕文字)。
  8. 在包含Activity的{​​{1}}中应用更改。 (将CollapsingToolbar转换为CollapsingToolbarlayout,设置字幕,额外的自定义设置等。)
  9. 交叉手指,测试。
  10. 现在去看看吧。

答案 2 :(得分:2)

稍微编辑克里斯托弗的回答,以展示如何让自定义视图在崩溃时不会消失:

首先,您需要使用视差属性在CollapsingToolbarLayout内添加视图:

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingTop:"80dp"
            android:src="@drawable/icon"
            app:layout_collapseMode="parallax"
            app:layout_collapseParallaxMultiplier="0.8"/> //set vertical transition here

而是以编程方式添加自定义视图,它在崩溃时不会消失。例如,这是一个包含标题和副标题的视图:

    final FrameLayout frameLayout = new FrameLayout(mActivity);
    FrameLayout.LayoutParams frameLayoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
            FrameLayout.LayoutParams.MATCH_PARENT);
    frameLayout.setLayoutParams(frameLayoutParams);


    // Create new LinearLayout
    final LinearLayout linearLayout = new LinearLayout(mActivity);
    frameLayoutParams =new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, dpToPixels(78));
    frameLayoutParams.gravity = Gravity.BOTTOM;
    linearLayout.setLayoutParams(frameLayoutParams);
    linearLayout.setOrientation(LinearLayout.VERTICAL);


    // Add textviews
    final TextView textView1 = new TextView(mActivity);
    LinearLayout.LayoutParams linearLayoutParams =new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
            LinearLayout.LayoutParams.WRAP_CONTENT);
    frameLayoutParams.gravity = Gravity.BOTTOM;
    textView1.setLayoutParams(linearLayoutParams);
    textView1.setText("Title");
    textView1.setTextColor(ContextCompat.getColor(mActivity, R.color.colorWhite));
    textView1.setTextSize(TypedValue.COMPLEX_UNIT_SP, 40);
    linearLayout.addView(textView1);


    final TextView textView2 = new TextView(mActivity);
    linearLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
            LinearLayout.LayoutParams.WRAP_CONTENT);
    textView2.setLayoutParams(linearLayoutParams);
    textView2.setText("Subtitle");
    textView2.setTextColor(ContextCompat.getColor(mActivity, R.color.colorWhite));
    textView2.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
    linearLayout.addView(textView2);

    frameLayout.addView(linearLayout);


    collapsingToolbar.addView(frameLayout);
    final float SCALE_MIN=0.4f;
    AppBarLayout appBarLayout = (AppBarLayout) mActivity.findViewById(R.id.appBarLayout);
    appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
        @Override
        public void onOffsetChanged(AppBarLayout appBarLayout, int offSet) {
            float collapsedRatio = (float) offSet / appBarLayout.getTotalScrollRange();
            linearLayout.setScaleX(1 + (collapsedRatio * SCALE_MIN));
            linearLayout.setScaleY(1 + (collapsedRatio * SCALE_MIN));
            FrameLayout.LayoutParams frameLayoutParams =new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, dpToPixels(78));
            frameLayoutParams.gravity = Gravity.BOTTOM;
            frameLayoutParams.setMargins(Math.round(dpToPixels(48) * (1+collapsedRatio)), 0, 0, Math.round(dpToPixels(15) * collapsedRatio));
            linearLayout.setLayoutParams(frameLayoutParams);
            // You can also setTransitionY/X, setAlpha, setColor etc.
        }
    });

/////

float lastCollapsedRatio = -2;

////

private int dpToPixels(int padding_in_dp){
    final float scale = getResources().getDisplayMetrics().density;
    int padding_in_px = (int) (padding_in_dp * scale + 0.5f);
    return padding_in_px;
}