【译文】AppBarLayout的越界滚动行为

很不幸,Youtube音乐应用在我们国家不可使用,我尝试着通过各种盗版网站来获取该应用,但我仍然无法看到在这个应用上发生了什么。感谢这位redditor,在我的请求下,他在/r/materialdesign打开了一个thread并且发表一段录制的视频,我才有机会看到这个行为。

Youtube视频app的真实截图,可能的行为

根据我所看到的,我首先想到的就是专辑封面是放到一个AppBarLayout里面,并且在滚动区域拖到边界的时候尺寸会发生变化。让我们假定这个
猜想是正确的并且用“Behavior”这个术语表示它。依鄙人之见,如果我的猜想是正确的,谷歌应该会在Material Design文档的滚动部分提供一个越界滚动的使用说明。

我们的目标就是保证AppBarLayout.Behavior的完整性,在此基础上再创建一个扩展的行为。因此:

public class OverscrollScalingViewAppBarLayoutBehavior extends AppBarLayout.ScrollingViewBehavior

因为这是默认的AppBarLayout.Behavior,所以建议只有在依赖视图是AppBarLayout的时候起作用。

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

接下来,我们需要获取想要在拖到边界时要改变尺寸的视图的一个实例。最好的方法就是在onLayoutChild()方法中获取:

@Override
public boolean onLayoutChild(CoordinatorLayout parent ....) {
    boolean superLayout = super.onLayoutChild(parent, abl, layoutDirection);
    if (mTargetScalingView == null) {
        mTargetScalingView = parent.findViewByTag(TAG);
        if(mTargetScalingView != null){
             mScaleImpl.obtainInitialValues();
         }
     }
    return superLayout;
}

而且我们需要保证只有在垂直滚动的时候起作用:

@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout,... int nestedScrollAxes) {
    return nestedScrollAxes == View.SCROLL_AXIS_VERTICAL;
}

如果我们先前没有在程序中显示设置,会设置ViewScaler为默认的Scaler。

在内容滚动的瞬间,真正重要的问题就有头绪了。CoordinatorLayout.Behavior提供了一个onNestedScroll()
方法,当滚动进行的时候这个方法会被调用,并且当内容滚动到边界的时候也会调用。最后两个参数dyUnconsumed和dxUnconsumed提供了
未被该行为的目标视图填满的像素值。

这个方法对我们实现尺寸改变来说太重要了。所以我列出了哪些情况需要改变尺寸,哪些情况不需要:

需要改变尺寸

  1. 存在未填满的像素,如dyUnconsumed小于0
  2. AppBarLayout是展开的,getTopAndBottomOffset() >= mScaleImpl.getInitialParentBottom()

不需要改变尺寸

  1. AppBarLayout中没有子视图可以改变尺寸
  2. 有填充的像素,如dyConsumed不等于
@Override
public void onNestedScroll(CoordinatorLayout ... int dxUnconsumed, int dyUnconsumed) {
    if (mTargetScalingView == null || dyConsumed != 0) {
        mScaleImpl.cancelAnimations();
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
        return;
    }

    if (dyUnconsumed < 0 && getTopAndBottomOffset() >= mScaleImpl.getInitialParentBottom()) {
        int absDyUnconsumed = Math.abs(dyUnconsumed);
        mTotalDyUnconsumed += absDyUnconsumed;
        mTotalDyUnconsumed = Math.min(mTotalDyUnconsumed, mTotalTargetDyUnconsumed);
        mScaleImpl.updateViewScale();
    } else {
        mTotalDyUnconsumed = 0;
        mScaleImpl.setShouldRestore(false);
        if (dyConsumed != 0) {
            mScaleImpl.cancelAnimations();
        }
        super.onNestedScroll(coordinatorLayout, .... dxUnconsumed, dyUnconsumed);
    }
}

当嵌套的overscroll停止的时候,我们需要将视图的边界和大小重置到它们的原始值。

@Override
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target) {
    mScaleImpl.retractScale();
    super.onStopNestedScroll(coordinatorLayout, child, target);

}

ViewScaler

这个类实现了AppBarLayout应该如何改变它的底部以及视图应该
如何改变尺寸的逻辑。大多数行为都依赖累积的未填充的像素。我们可以为最大累积值设置一个约束值,这样可以很容的找到要如何改变AppBarLayout
底部和改变视图的尺寸。ParentScaler是ViewScaler的父类,它能让AppBarLayout近乎平滑的改变尺寸。我就不在这里贴大量
代码了,如果你有兴趣,可以从这里获取代码

Bonus

大神们,这里有个MatrixScaler类,我没有时间去完成它。如果想要改变尺寸的视图是ImageView,并且设置了ScaleType为MATRIX,这个类将可以用使用矩阵的方式来改变图像的尺寸。

Demo

时间: 2024-08-02 04:51:41

【译文】AppBarLayout的越界滚动行为的相关文章

滚动和点击:哪一个对用户的体验更加友好?

点击和滚动,哪一个对用户更友好?这是一个设计师在设计页面浏览过程时必须考虑的问题.使用点击,给用户一堆链接并把他们带到新的页面;使用滚动,则把所有内容按区块展示在一个单一的页面上. 许多年前,这个问题最简单的回答就是使用点击.通常的考虑是,如果你使得你的你的页面过长,那么用户只会去看去读上半部分而可能只是扫一眼.甚至是忽略下半部分.而今,这有了一些变化,许多用户可以毫无问题的从头滚到尾.相比点击滚动现在变得越来越自然.因为用户的行为一直在变化着,设计师需要在他们的设计里考虑到这些问题. 无论是滚

“无限滚动加载”适用于你的产品吗?

在家一天天宅着,倒仍然能对周六周日有清晰的概念,也真是个奇迹. 今天带来一篇关于无限滚动加载的简短译文.其实这事儿,以前在微博上也吐过一阵的槽,印象最深的就是有次在一个什么网站上想点页脚里的"关于我们",真心点不着,每每要点的时候上面自动加载的内容就顶下来,没完没了...当时就愤恨的琢磨着你们要这页脚有毛用啊?这次看到这篇文章,觉得里面有不少能引起自己共鸣的内容,所以拿过来做,希望也能给各位朋友带来些有用的东西吧.走着. 这里进入译文.怎样通过更友好的方式来呈现一系列的数据内容,包括文

webview- WebView如何获取当前滚动的位置,如何滚动到指定位置

问题描述 WebView如何获取当前滚动的位置,如何滚动到指定位置 WebView如何获取当前滚动的位置,如何滚动到指定位置,类似下图中,如果点击某一层的回复刷新数据后,希望再次滚动到当前楼层 解决方案 消息返回当前值,然后写cookies.下次加载时直接cookies读取设置. 解决方案二: ListView滚动指定位置AppbarLayout 自动滚动到指定位置

玩转AppBarLayout实现更酷炫的顶部栏_Android

上一篇文章<CoordinateLayout的使用如此简单 >对CoordinateLayout的使用做了讲解,今天我们再讲解常常与其一起使用的几个View:AppBarLayout.CollapsingToolbarLayout以及Toolbar.一下子出现3个陌生的View,是不是觉得很慌张~,很多人都写了这几个布局的使用,但是他们却没有有针对性的单独讲解每个View的作用以及如何使用,我看的很多文章都是一上来就把AppBarLayout.CollapsingToolbarLayout以及

Android Material Design之CoordinatorLayout+AppBarLayout实现上滑隐藏ToolBar

http://blog.csdn.net/u010687392/article/details/46852565 版权声明:本文为博主原创文章,未经博主允许不得转载.转载注明出处:Sunzxyong ok,今天继续更新Material Design系列!!! 废话不说,先看看效果图吧: 好了,现在来讲讲上图是怎么实现的吧!讲之前先讲讲几个控件: CoordinatorLayout  该控件也是Design包下的一个控件,然而这个控件可以被称为Design包中最复杂.功能最强大的控件:Coordi

Android支持横行滚动的ListView控件

前言 ListView是一个纵向滚动的列表视图,也有朋友嵌套HorizontalScrollView来实现,比如这里,但在ListView的API中明确指明了两者不可同时使用,参考ListView的中文API这里.本文分享一种办法,以方便有此需求的朋友.   声明 欢迎转载,但请保留文章原始出处:)  博客园:http://www.cnblogs.com 农民伯伯: http://over140.cnblogs.com   Android中文翻译组:http://androidbox.sinaa

Material Design学习之 Dialog(顺便把前两天AppBarLayout没讲的部分提一提)

转载请注明出处:王亟亟的大牛之路 继续之前的MD系列的内容,今天说Dialog,不知道还能翻几篇,反正这一系列都说完了话就找点别的内容整整. Dialogs (提示框)用于提示用户作一些决定,或者是完成某个任务时需要的一些其它额外的信息. Dialog可以是用一种 取消/确定 的简单应答模式,也可以是自定义布局的复杂模式,比如说一些文本设置或者是文本输入 . 官方的呈现,像这样 Dialog 包含了一个标题(可选),内容 ,事件. 标题:主要是用于简单描述下选择类型.它是可选的,要需要的时候赋值

android开发之横向滚动/竖向滚动的ListView(固定列头)_Android

由于项目需要,我们需要一个可以横向滚动的,又可以竖向滚动的 表格.而且又要考虑大数据量(行)的展示视图.经过几天的研究终于搞定,做了一个演示.贴图如下:  开发之横向滚动/竖向滚动的ListView(固定列头)_Android-横向滚动listview">       好吧.让我们看思路是什么样的:   1. 上下滚动直接使用 listView来实现. 2. 左右滚动使用HorizontalScrollView,来处理滚动.我写一个类MyHScrollView继承 自它.     2.1

Android仿淘宝商品浏览界面图片滚动效果_Android

用手机淘宝浏览商品详情时,商品图片是放在后面的,在第一个ScrollView滚动到最底下时会有提示,继续拖动才能浏览图片.仿照这个效果写一个出来并不难,只要定义一个Layout管理两个ScrollView就行了,当第一个ScrollView滑到底部时,再次向上滑动进入第二个ScrollView.效果如下: 需要注意的地方是:       1.如果是手动滑到底部需要再次按下才能继续往下滑,自动滚动到底部则不需要       2.在由上一个ScrollView滑动到下一个ScrollView的过程中