android - 具有多个捕捉点的 CoordinatorLayout

标签 android android-animation android-coordinatorlayout android-collapsingtoolbarlayout android-nestedscrollview

这里我有一个相当复杂的动画,可以使用 CoordinatorLayout 以简单的方式解决(我相信) .它有 3 个状态:

  1. 初始(左侧屏幕)- 标题 View 完全显示(橙色 背景):工具栏,灰色 roundrect(它实际上是一张照片) 加上下面的一些其他 View (TextViews、RatingBar 等)
  2. 向上滚动内容(中间 屏幕)- roundrect 正在放大,其上有一个不断变化的绿色前景 alpha 级别,因此它在滚动时变为绿色(好吧,在这些屏幕上并不明显。绿色背景实际上是一个放大的 roundrect,上面有一个绿色前景,而且是标题背景变成绿色而不是橙色的原因)
  3. 再次滚动(右侧屏幕)- 标题的其余部分应向上滚动

向下滚动内容应该会相应地以相反的方式显示 View 。

CoordinatorLayout states

我有一些使用 CoordinatorLayout 的经验,但我真的不确定我是否理解如何处理 2 个 anchor 。我了解滚动标志的工作原理以及用于缩放(第 2 页)和更改前景 alpha 的工作原理我需要一个自定义 Behavior实现,但现在我不明白我该如何在一个复杂的环境中处理所有这些。

到目前为止我找到的是Saúl Molinero's tutorial还有this tutorial with examples .

所以对于这里的糟糕描述,请深表歉意,我当然会更新我的问题,当我在这个问题上取得一些成功时会添加源代码,但现在我很乐意得到一些提示或教程我错过了。希望有人在项目中有类似的东西。

这是我的 test repo使用代码和 here是我的 layout.xml 文件的链接。

最佳答案

只需设置滚动标志即可获得两个捕捉点,如下所示:

<android.support.design.widget.CollapsingToolbarLayout
    ...stuff...
    app:layout_scrollFlags="scroll|enterAlways|snap">

因此,完全展开是一个停止点,仅显示工具栏是第二个停止点。当进一步 ScrollView 时,工具栏消失。这就是您希望向上滚动时的工作方式。

现在,当应用栏完全折叠时,向下滚动时应用栏将立即开始显示。这并不奇怪,因为这就是 enterAlways 所做的。如果内容的顶部已经滚出 View ,那么在应用栏完全展开之前您将不会再次看到它。所以,如果这是您想要的行为,我们就到此为止。

但是,我认为您想要的是上面概述的退出行为,但具有不同的进入行为。如果按如下方式设置滚动标志,您将获得延迟进入行为:

<android.support.design.widget.CollapsingToolbarLayout
    ...stuff...
    app:layout_scrollFlags="scroll|snap">

这只是删除了 enterAlways 标志。使用这些滚动标志,应用栏将不会重新出现(一旦折叠),直到内容顶部可见并将应用栏“拉”入 View 。

因此,一个解决方案(可能有很多)是编写一个将附加到 AppBarLayout 的新行为,一些代码将更改一次滚动标志应用栏已完全折叠并在再次打开时将它们改回原样。这样您就可以将行为更改为您想要的,并且仍然使用 Android 机制来确定 View 级别的特定操作。这可以在自定义 View 或 Activity 中完成 - 无论您可以访问应用栏的滚动状态和滚动标志。它也可以在行为中完成,但这可能不是最好的地方。

哦,正如您所发现的,捕捉在 API 26 上是卡顿的。


这是这个概念的一个实现。为简单起见,实现在一个 Activity 中:

enter image description here

滚动 Activity .java

public class ScrollingActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scrolling);

        final AppBarLayout appBar = (AppBarLayout) findViewById(R.id.app_bar);

        appBar.post(new Runnable() {
            @Override
            public void run() {
                CollapsingToolbarLayout toolbarLayout =
                    (CollapsingToolbarLayout) findViewById(R.id.toolbar_layout);
                setupAppBar(appBar, toolbarLayout);
            }
        });
    }

    private void setupAppBar(AppBarLayout appBar, final CollapsingToolbarLayout toolbarLayout) {
        // Scroll range is positive but offsets are negative. Make signs agree for camparisons.
        final int mScrollRange = -appBar.getTotalScrollRange();

        appBar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            private boolean mAppBarCollapsed = false;

            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                if (verticalOffset == mScrollRange) { // App bar just collapsed
                    mAppBarCollapsed = true;
                    AppBarLayout.LayoutParams lp =
                        (AppBarLayout.LayoutParams) toolbarLayout.getLayoutParams();
                    int flags = lp.getScrollFlags()
                        & ~AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS;
                    lp.setScrollFlags(flags);
                    toolbarLayout.setLayoutParams(lp);
                } else if (mAppBarCollapsed) { // App bar is opening back up
                    mAppBarCollapsed = false;
                    AppBarLayout.LayoutParams lp =
                        (AppBarLayout.LayoutParams) toolbarLayout.getLayoutParams();
                    int flags = lp.getScrollFlags()
                        | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS;
                    lp.setScrollFlags(flags);
                    toolbarLayout.setLayoutParams(lp);
                }
            }
        });
    }
}

关于android - 具有多个捕捉点的 CoordinatorLayout,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46163699/

相关文章:

android - 如何在 iOS(AVFoundation 或其他第 3 方库)中使用 HLS 时移功能,如 Android 中的 ExoPlayer?

android - 具有多个过滤器或多个广播接收器的广播接收器?

android - 新 Android 代码的属性动画与 View 动画

Android:将 Activity 上下文获取到数组适配器类中

android - 将闪烁添加到自定义 ListView 项目?

java - 在 OpenCv4Android 中存储测试数据

android - 如何获取OpenGL在移动设备中使用的内存总量?

android - 如何在整个应用程序中使用自定义工具栏

Android map 无法在 CollapsingToolbarLayout 中正确滚动

android - 停止 ViewPager 内的 NestedScrollView 处理水平滚动