Android L 联系人应用程序如何折叠其工具栏?

Posted

技术标签:

【中文标题】Android L 联系人应用程序如何折叠其工具栏?【英文标题】:How does the Android L contacts app collapse its toolbar? 【发布时间】:2014-12-20 20:01:19 【问题描述】:

我一直在尝试重现 5.0 版的联系人应用程序在滚动列表视图时折叠工具栏的方式。

Gallery of screenshots demonstrating the desired interaction 注意工具栏的分阶段折叠,其中显示搜索+最后一个联系人,淡出最后一个联系人,折叠最后一个联系人,折叠搜索,只留下选项卡。

到目前为止,我在 LinearLayout 中的 recyclerview 上方有一个工具栏,该工具栏用作操作栏,而不是独立的。

我不知道如何拦截recyclerview上的touch事件,使其收缩工具栏,然后将滚动事件返回给recyclerview。我试着把整个东西放在一个滚动视图中,但是recyclerview无法正确计算它的高度并且没有显示任何内容。我尝试在 recyclerview 上覆盖 onscroll,发现它只会在滚动事件开始时通知我,并为我提供第一个可见的卡片 ID。

看起来正确但我无法终生工作的方式是这样的:

getSupportActionBar().setHideOnContentScrollEnabled(true);

返回:

 Caused by: java.lang.UnsupportedOperationException: Hide on content scroll is not supported in this action bar configuration.

使用传统的操作栏,在其下方放置一个工具栏,并设置 hideoncontentscrollenabled 也不起作用,滚动从未触发操作栏上的隐藏方法。

-- 编辑-- 我能够让 hideOnContentScrollEnabled 在带有传统操作栏的列表视图上工作,但行为与联系人应用程序不同。这显然不是他们使用的方法——它只是在列表视图上发生 fling 事件时触发操作栏上的 .hide() ,这与联系人应用程序明显不同,后者将工具栏与滚动事件一起拖动。 -- /编辑 --

所以我放弃了那条路线,并将 fill_parent 放在 cardview 的高度上,并在工具栏上设置了一个折叠动画。但是如何触发它,让它跟随触摸事件,然后将触摸事件返回给recyclerview呢?

activity_main.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:orientation="vertical"
    >

    <android.support.v7.widget.Toolbar
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/toolbar"
        android:layout_
        android:layout_
        android:minHeight="?android:attr/actionBarSize"
        android:background="@color/colorPrimary"
        />

    <fragment android:name="me.myapplication.FragmentTab"
          android:id="@+id/tab_fragment"
          android:layout_
          android:layout_ />
</LinearLayout>

fragment_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:padding="8dp"
    android:background="#eeeeee"
    >

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_
        android:layout_
        />

</LinearLayout>

styles.xml

...
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
...

MainActivity.java

Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);

// Disable the logo in the actionbar, as per material guidelines
toolbar.getMenu().clear();
toolbar.setTitle("My toolbar");
setSupportActionBar(toolbar);

【问题讨论】:

Google I/O 2014 应用在其会话视图中具有类似的功能。您可能会在那里找到一些想法。 谢谢,我查看了源代码和效果,但是iosched应​​用程序是不同类型的效果,并且以不同的方式实现。当 onScroll 被调用时,它基本上会在操作栏上设置一种“隐藏”类型的动画效果,它只占用第一块项目并且不能真正跟踪你的手指。可以通过 setHideOnContentScrollEnabled() 应用相同的效果。然而,联系人应用程序似乎在将滚动事件返回到可滚动视图之前向上滚动整个视口。 想不通-如果您不尝试拦截 ListView / RecyclerView 触摸事件,而是使用 GestureDetector 覆盖您的视图并将其移动时触摸事件路由到正确的小部件以缩小怎么办/ 适当地滚动它们?只是一个想法,根本没有尝试过。 找到解决方案了吗?我对同样的事情感兴趣.. 【参考方案1】:

我还没有调查源代码,但这家伙似乎让生活变得轻松而富有启发性。

https://github.com/ksoichiro/Android-ObservableScrollView

编辑

Google 刚刚发布了Android Design Library。请看一下,因为它包含折叠工具栏的所有效果等等。

【讨论】:

@DalvikVM 谢谢你,我试过了,效果很好!【参考方案2】:

好吧,我不知道他们是怎么做到的,但是……你为什么不看看源代码呢?对我们来说幸运的是,Contacts 应用程序仍然是 Android L 上的开源应用程序(其他应用程序不如 Contacts 幸运,例如 Mail,它不再在 L 上工作;或 Keyboard,自他们的专有软件推出以来,他们不再更新谷歌键盘)。

无论如何,这是我认为您应该查看的源代码: https://github.com/android/platform_packages_apps_contacts/blob/master/src%2Fcom%2Fandroid%2Fcontacts%2Factivities%2FActionBarAdapter.java

注意第 311 行中的方法 update(boolean skipAnimation),它调用 animateTabHeightChange(int start, int end)(第 437 行)。

我的猜测是所有的魔法都发生在那里;-)

【讨论】:

【参考方案3】:

截至 2015 年 6 月,您可以通过新设计支持库的所谓 CollapsingToolbarLayout 来实现您想要的效果。

根据示例代码here,我认为:

搜索卡片视图是工具栏的子视图 未接来电卡片视图属于折叠工具栏,collapseMode 属性设置为 pin

<android.support.design.widget.AppBarLayout
    android:id="@+id/appbar"
    android:layout_
    android:layout_
    android:fitsSystemWindows="true"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <android.support.design.widget.CollapsingToolbarLayout
        android:layout_
        android:layout_
        android:minHeight="?attr/actionBarSize"
        android:fitsSystemWindows="true"
        app:layout_scrollFlags="scroll|enterAlwaysCollapsed|enterAlways">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_
            android:layout_
            android:background="?attr/colorPrimary"
            android:fitsSystemWindows="false"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:layout_collapseMode="pin"
            app:layout_scrollFlags="scroll|enterAlways">

            <!-- Search layout -->
            <android.support.v7.widget.CardView   
            </android.support.v7.widget.CardView>

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

        <!-- Last call card view-->
        <android.support.v7.widget.CardView
            app:layout_collapseMode="pin">               
        </android.support.v7.widget.CardView>

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

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

<LinearLayout
    android:layout_
    android:layout_
    android:orientation="vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <android.support.design.widget.TabLayout
        android:id="@+id/tabs"
        android:layout_
        android:layout_
        android:background="@color/primary_color"
        app:layout_scrollFlags="scroll"/>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_
        android:layout_ />

</LinearLayout>

【讨论】:

我的问题在这里,你能弄清楚是什么问题吗:***.com/questions/30913211/…【参考方案4】:

现在不需要第三方库! Android 正式提供库。您可以折叠工具栏并进行许多其他调整。

查看android-developer's blog

别忘了在你的build.gradle 文件中添加这个依赖项。

compile 'com.android.support:design:22.2.0'

【讨论】:

【参考方案5】:

我发现这个库似乎可以满足您的需求:https://github.com/kmshack/Android-ParallaxHeaderViewPager 和这个https://github.com/flavienlaurent/NotBoringActionBar

您可以播放视频查看行为:https://www.youtube.com/watch?v=sCP-b0a1x5Y

这可能不是使用 ToolBar 执行此操作的“新”标准方式,但通过检查代码可能会给您一个想法。它似乎在滚动内容上附加了一个 OnScrollListener,然后触发栏大小的更改。

【讨论】:

【参考方案6】:

对我来说https://mzgreen.github.io/2015/06/23/How-to-hideshow-Toolbar-when-list-is-scrolling%28part3%29/ 有帮助。可在此处找到源代码:https://github.com/mzgreen/HideOnScrollExample/tree/master/app/src/main。

布局中的 RecycleView 应如下所示:

<android.support.v7.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_
    android:layout_
    android:layout_gravity="fill_vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />

请注意,启动应用程序后会出现 2 个工具栏(操作栏和工具栏)。所以在你的activity.java中你应该这样写:

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    // Hide ActionBar.
    supportRequestWindowFeature(WindowCompat.FEATURE_ACTION_BAR);
    getSupportActionBar().hide();
    setContentView(R.layout.your_activity_layout);
    ...

自定义工具栏如下所示:https://***.com/a/26548766/2914140。我的意思是,它没有标题和任何其他元素,因此您可以将它们添加到布局中。

【讨论】:

【参考方案7】:

Android 的联系人应用没有简单的即插即用解决方案,您可以在自己的应用中使用。

它做了一个完整的实现,基本上就像你从头开始实现它一样。对于上下文,在查看代码之前,请记住视图的布局方式:

https://github.com/android/platform_packages_apps_contacts/blob/lollipop-release/res/layout/quickcontact_activity.xml

MultiShrinkScroller 是一个 FrameLayout 中间滚动行为,但主要的东西是在一个 LinearLayout 中,因此降低较高视图的高度将向上“滚动”较低的视图。

实现的关键文件是这个:

https://github.com/android/platform_packages_apps_contacts/blob/lollipop-release/src/com/android/contacts/widget/MultiShrinkScroller.java

public void scrollTo(int x, int y) 
    final int delta = y - getScroll();
    boolean wasFullscreen = getScrollNeededToBeFullScreen() <= 0;
    if (delta > 0) 
        scrollUp(delta);
     else 
        scrollDown(delta);
    
    updatePhotoTintAndDropShadow();
    updateHeaderTextSizeAndMargin();
    //... other stuff


private void scrollUp(int delta) 

    // Collapse higher views first
    if (getTransparentViewHeight() != 0) 
        final int originalValue = getTransparentViewHeight();
        setTransparentViewHeight(getTransparentViewHeight() - delta);
        setTransparentViewHeight(Math.max(0, getTransparentViewHeight()));
        delta -= originalValue - getTransparentViewHeight();
    

    // Shrink toolbar as needed
    final ViewGroup.LayoutParams toolbarLayoutParams
            = mToolbar.getLayoutParams();
    if (toolbarLayoutParams.height > getFullyCompressedHeaderHeight()) 
        final int originalValue = toolbarLayoutParams.height;
        toolbarLayoutParams.height -= delta;
        toolbarLayoutParams.height = Math.max(toolbarLayoutParams.height,
                getFullyCompressedHeaderHeight());
        mToolbar.setLayoutParams(toolbarLayoutParams);
        delta -= originalValue - toolbarLayoutParams.height;
    

    // Finally, scroll content if nothing left to shrink
    mScrollView.scrollBy(0, delta);

updatePhotoTintAndDropShadow();updateHeaderTextSizeAndMargin(); 在折叠时处理色调和文本的变化,使其变成常规 ActionBar/ToolBar 的外观。

您可以获取 MultiShrinkScroller 文件本身并对其进行调整以供您自己使用,但现在可能有更简单的实现(包括来自 Android 设计库的那些)。

【讨论】:

以上是关于Android L 联系人应用程序如何折叠其工具栏?的主要内容,如果未能解决你的问题,请参考以下文章

如何在expandablelistview中折叠组视图上方和下方的所有子视图?

工具栏折叠时如何使用动画调整搜索视图宽度 [ANDROID]

如何在android中制作折叠工具栏?

Android 中的折叠底栏(如 Google 音乐)

带有折叠工具栏的 RecyclerView 中的 Android 字母快速滚动视图

如何向嵌套在折叠工具栏中的 ImageView 添加渐变