展开/折叠棒棒糖工具条动画(Telegram app)

时间:2021-03-26 15:32:10

I'm trying to figure out how the expand/collapse animation of the toolbar is done. If you have a look at the Telegram app settings, you will see that there is a listview and the toolbar. When you scroll down, the toolbar collapse, and when you scroll up it expands. There is also the animation of the profile pic and the FAB. Does anyone have any clue on that? Do you think they built all the animations on top of it? Maybe I'm missing something from the new APIs or the support library.

我试图弄清楚工具栏的扩展/崩溃动画是如何完成的。如果您查看Telegram应用程序设置,您将看到有一个listview和工具栏。当你向下滚动时,工具栏会崩溃,当你向上滚动时,它会扩展。也有个人简介图片和FAB的动画。有人知道吗?你认为他们在上面做了所有的动画吗?也许我在新的api或支持库中漏掉了一些东西。

I noticed the same behaviour on the Google calendar app, when you open the Spinner (I don't think it's a spinner, but it looks like): The toolbar expands and when you scroll up, it collapse.

我注意到谷歌日历应用程序上也有同样的行为,当你打开旋转器(我不认为它是旋转器,但它看起来像):工具栏扩展,当你向上滚动时,它就会崩溃。

Just to clearify: I don't need the QuickReturn method. I know that probably Telegram app is using something similar. The exact method that I need is the Google Calendar app effect. I've tried with

为了澄清:我不需要快速返回方法。我知道可能Telegram应用也在使用类似的东西。我需要的确切方法是谷歌日历应用程序效果。我试过了,

android:animateLayoutChanges="true"

and the expand method works pretty well. But obviously, If I scroll up the ListView, the toolbar doesn't collapse.

展开法很有效。但显然,如果我向上滚动ListView,工具栏不会崩溃。

I've also thought about adding a GestureListener but I want to know if there are any APIs or simpler methods of achieving this.

我也考虑过添加一个GestureListener,但我想知道是否有任何api或更简单的方法来实现这一点。

If there are none, I think I will go with the GestureListener. Hopefully to have a smooth effect of the Animation.

如果没有的话,我想我会用手势示意的。希望能有一个平滑的动画效果。

Thanks!

谢谢!

4 个解决方案

#1


105  

Edit :

编辑:

Since the release of the Android Design support library, there's an easier solution. Check joaquin's answer

自从Android设计支持库发布以来,有了一个更简单的解决方案。检查华金的回答

--

- - -

Here's how I did it, there probably are many other solutions but this one worked for me.

这是我怎么做的,可能有很多其他的解但是这个对我有用。

  1. First of all, you have to use a Toolbar with a transparent background. The expanding & collapsing Toolbar is actually a fake one that's under the transparent Toolbar. (you can see on the first screenshot below - the one with the margins - that this is also how they did it in Telegram).

    首先,您必须使用具有透明背景的工具栏。扩展和折叠工具栏实际上是透明工具栏下面的一个伪工具栏。(你可以在下面的第一张截图中看到这也是他们在电报中所做的)。

    We only keep the actual Toolbar for the NavigationIcon and the overflow MenuItem.

    我们只保留导航图标和溢出菜单项的实际工具栏。

    展开/折叠棒棒糖工具条动画(Telegram app)

  2. Everything that's in the red rectangle on the second screenshot (ie the fake Toolbar and the FloatingActionButton) is actually a header that you add to the settings ListView (or ScrollView).

    在第二个屏幕快照的红色矩形中(即伪工具栏和FloatingActionButton)的所有内容实际上都是添加到设置列表视图(或ScrollView)的标题。

    So you have to create a layout for this header in a separate file that could look like this :

    因此,你必须在一个单独的文件中为这个头创建一个布局:

     <!-- The headerView layout. Includes the fake Toolbar & the FloatingActionButton -->
    
     <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <RelativeLayout
            android:id="@+id/header_container"
            android:layout_width="match_parent"
            android:layout_height="@dimen/header_height"
            android:layout_marginBottom="3dp"
            android:background="@android:color/holo_blue_dark">
    
            <RelativeLayout
                android:id="@+id/header_infos_container"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:padding="16dp">
    
                <ImageView
                    android:id="@+id/header_picture"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_marginRight="8dp"
                    android:src="@android:drawable/ic_dialog_info" />
    
                <TextView
                    android:id="@+id/header_title"
                    style="@style/TextAppearance.AppCompat.Title"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_toRightOf="@+id/header_picture"
                    android:text="Toolbar Title"
                    android:textColor="@android:color/white" />
    
                <TextView
                    android:id="@+id/header_subtitle"
                    style="@style/TextAppearance.AppCompat.Subhead"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_below="@+id/header_title"
                    android:layout_toRightOf="@+id/header_picture"
                    android:text="Toolbar Subtitle"
                    android:textColor="@android:color/white" />
    
            </RelativeLayout>
        </RelativeLayout>
    
        <FloatingActionButton
            android:id="@+id/header_fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|right"
            android:layout_margin="10dp"
            android:src="@drawable/ic_open_in_browser"/>
    
    </FrameLayout>
    

    (Note that you can use negative margins/padding for the fab to be straddling on 2 Views)

    (注意,可以使用负边距/填充使fab跨在两个视图上)

  3. Now comes the interesting part. In order to animate the expansion of our fake Toolbar, we implement the ListView onScrollListener.

    现在有趣的部分来了。为了使我们的伪工具栏的扩展具有动画效果,我们实现了ListView onScrollListener。

    // The height of your fully expanded header view (same than in the xml layout)
    int headerHeight = getResources().getDimensionPixelSize(R.dimen.header_height);
    // The height of your fully collapsed header view. Actually the Toolbar height (56dp)
    int minHeaderHeight = getResources().getDimensionPixelSize(R.dimen.action_bar_height);
    // The left margin of the Toolbar title (according to specs, 72dp)
    int toolbarTitleLeftMargin = getResources().getDimensionPixelSize(R.dimen.toolbar_left_margin);
    // Added after edit
    int minHeaderTranslation;
    
    private ListView listView;
    
    // Header views
    private View headerView;
    private RelativeLayout headerContainer;
    private TextView headerTitle;
    private TextView headerSubtitle;
    private FloatingActionButton headerFab;
    
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View rootView = inflater.inflate(R.layout.listview_fragment, container, false);
        listView = rootView.findViewById(R.id.listview);
    
        // Init the headerHeight and minHeaderTranslation values
    
        headerHeight = getResources().getDimensionPixelSize(R.dimen.header_height);
        minHeaderTranslation = -headerHeight + 
            getResources().getDimensionPixelOffset(R.dimen.action_bar_height);
    
        // Inflate your header view
        headerView = inflater.inflate(R.layout.header_view, listview, false);
    
        // Retrieve the header views
        headerContainer = (RelativeLayout) headerView.findViewById(R.id.header_container);
        headerTitle = (TextView) headerView.findViewById(R.id.header_title);
        headerSubtitle = (TextView) headerView.findViewById(R.id.header_subtitle);
        headerFab = (TextView) headerView.findViewById(R.id.header_fab);;
    
        // Add the headerView to your listView
        listView.addHeaderView(headerView, null, false);
    
        // Set the onScrollListener
        listView.setOnScrollListener(this);        
    
        // ...
    
        return rootView;
    }
    
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState)
    {
        // Do nothing
    }
    
    
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
    {
        Integer scrollY = getScrollY(view);
    
        // This will collapse the header when scrolling, until its height reaches
        // the toolbar height
        headerView.setTranslationY(Math.max(0, scrollY + minHeaderTranslation));
    
        // Scroll ratio (0 <= ratio <= 1). 
        // The ratio value is 0 when the header is completely expanded, 
        // 1 when it is completely collapsed
        float offset = 1 - Math.max(
            (float) (-minHeaderTranslation - scrollY) / -minHeaderTranslation, 0f);
    
    
        // Now that we have this ratio, we only have to apply translations, scales,
        // alpha, etc. to the header views
    
        // For instance, this will move the toolbar title & subtitle on the X axis 
        // from its original position when the ListView will be completely scrolled
        // down, to the Toolbar title position when it will be scrolled up.
        headerTitle.setTranslationX(toolbarTitleLeftMargin * offset);
        headerSubtitle.setTranslationX(toolbarTitleLeftMargin * offset);
    
        // Or we can make the FAB disappear when the ListView is scrolled 
        headerFab.setAlpha(1 - offset);
    }
    
    
    // Method that allows us to get the scroll Y position of the ListView
    public int getScrollY(AbsListView view)
    {
        View c = view.getChildAt(0);
    
        if (c == null)
            return 0;
    
        int firstVisiblePosition = view.getFirstVisiblePosition();
        int top = c.getTop();
    
        int headerHeight = 0;
        if (firstVisiblePosition >= 1)
            headerHeight = this.headerHeight;
    
        return -top + firstVisiblePosition * c.getHeight() + headerHeight;
    }
    

Note that there are some parts of this code I didn't test, so feel free to highlight mistakes. But overall, I'm know that this solution works, even though I'm sure it can be improved.

请注意,这段代码中有一些部分我没有进行测试,所以请随意突出错误。但总的来说,我知道这个解决方案是有效的,尽管我确信它可以改进。

EDIT 2:

编辑2:

There were some mistakes in the code above (that I didn't test until today...), so I changed a few lines to make it work :

上面的代码中有一些错误(直到今天我才进行测试…),所以我修改了几行代码以使其工作:

  1. I introduced another variable, minHeaderTranslation, which replaced minHeaderHeight;
  2. 我引入了另一个变量,minHeaderTranslation,它代替了minHeaderHeight;
  3. I changed the Y translation value applied to the header View from :

    我将应用于header视图的Y平移值从:

        headerView.setTranslationY(Math.max(-scrollY, minHeaderTranslation));
    

    to :

    :

        headerView.setTranslationY(Math.max(0, scrollY + minHeaderTranslation));
    

    Previous expression wasn't working at all, I'm sorry about that...

    之前的表达根本没用,我很抱歉……

  4. The ratio calculation also changed, so that it now evolves from the bottom the toolbar (instead of the top of the screen) to the full expanded header.

    比率计算也发生了变化,因此它现在从底部的工具栏(而不是屏幕的顶部)演变为完整的展开标题。

#2


25  

Also check out CollapsingTitleLayout written by Chris Banes in Android team: https://plus.google.com/+ChrisBanes/posts/J9Fwbc15BHN

还可以看看ChrisBanes在Android团队中写的:https://plus.google.com/+ChrisBanes/posts/J9Fwbc15BHN

展开/折叠棒棒糖工具条动画(Telegram app)

Code: https://gist.github.com/chrisbanes/91ac8a20acfbdc410a68

代码:https://gist.github.com/chrisbanes/91ac8a20acfbdc410a68

#3


8  

Use design support library http://android-developers.blogspot.in/2015/05/android-design-support-library.html

使用设计支持库http://android- developers.blogspot.in5/05/android -design-support-library.html

include this in build.gradle

包括在build.gradle

compile 'com.android.support:design:22.2.0'    
compile 'com.android.support:appcompat-v7:22.2.+'

for recycler view include this also

对于回收商来说也包括这个

compile 'com.android.support:recyclerview-v7:22.2.0' 

    <!-- AppBarLayout allows your Toolbar and other views (such as tabs provided by TabLayout) 
    to react to scroll events in a sibling view marked with a ScrollingViewBehavior.-->
    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true">

        <!-- specify tag app:layout_scrollFlags -->
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways"/>

        <!-- specify tag app:layout_scrollFlags -->
        <android.support.design.widget.TabLayout
            android:id="@+id/tabLayout"
            android:scrollbars="horizontal"
            android:layout_below="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways"/>

        <!--  app:layout_collapseMode="pin" will help to pin this view at top when scroll -->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:text="Title"
            android:gravity="center"
            app:layout_collapseMode="pin" />

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

    <!-- This will be your scrolling view. 
    app:layout_behavior="@string/appbar_scrolling_view_behavior" tag connects this features -->
    <android.support.v7.widget.RecyclerView
        android:id="@+id/list"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

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

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

Your activity should extend AppCompatActivity

您的活动应该扩展AppCompatActivity

public class YourActivity extends AppCompatActivity {

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

        //set toolbar
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }

}

Your app theme should be like this

你的应用主题应该是这样的

    <resources>
            <!-- Base application theme. -->   
            <style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
            </style>
    </resources>

#4


1  

This is my implementation:

这是我的实现:

collapsedHeaderHeight and expandedHeaderHeight are defined somewhere else, with the function getAnimationProgress I can get the Expand/Collapse progress, base on this value I do my animation and show/hide the real header.

折叠头高度和扩展头高度是在其他地方定义的,通过函数getAnimationProgress,我可以得到扩展/折叠进度,基于这个值,我做动画并显示/隐藏真正的头。

  listForumPosts.setOnScrollListener(new AbsListView.OnScrollListener() {

        /**
         * @return [0,1], 0 means header expanded, 1 means header collapsed
         */
        private float getAnimationProgress(AbsListView view, int firstVisibleItem) {
            if (firstVisibleItem > 0)
                return 1;

            // should not exceed 1
            return Math.min(
                    -view.getChildAt(0).getTop() / (float) (expandedHeaderHeight - collapsedHeaderHeight), 1);
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            // at render beginning, the view could be empty!
            if (view.getChildCount() > 0) {
                float animationProgress = getAnimationProgress(view, firstVisibleItem);
                imgForumHeaderAvatar.setAlpha(1-animationProgress);
                if (animationProgress == 1) {
                    layoutForumHeader.setVisibility(View.VISIBLE);
                } else {
                    layoutForumHeader.setVisibility(View.GONE);
                }
            }
        }

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            // do nothing
        }

    }

#1


105  

Edit :

编辑:

Since the release of the Android Design support library, there's an easier solution. Check joaquin's answer

自从Android设计支持库发布以来,有了一个更简单的解决方案。检查华金的回答

--

- - -

Here's how I did it, there probably are many other solutions but this one worked for me.

这是我怎么做的,可能有很多其他的解但是这个对我有用。

  1. First of all, you have to use a Toolbar with a transparent background. The expanding & collapsing Toolbar is actually a fake one that's under the transparent Toolbar. (you can see on the first screenshot below - the one with the margins - that this is also how they did it in Telegram).

    首先,您必须使用具有透明背景的工具栏。扩展和折叠工具栏实际上是透明工具栏下面的一个伪工具栏。(你可以在下面的第一张截图中看到这也是他们在电报中所做的)。

    We only keep the actual Toolbar for the NavigationIcon and the overflow MenuItem.

    我们只保留导航图标和溢出菜单项的实际工具栏。

    展开/折叠棒棒糖工具条动画(Telegram app)

  2. Everything that's in the red rectangle on the second screenshot (ie the fake Toolbar and the FloatingActionButton) is actually a header that you add to the settings ListView (or ScrollView).

    在第二个屏幕快照的红色矩形中(即伪工具栏和FloatingActionButton)的所有内容实际上都是添加到设置列表视图(或ScrollView)的标题。

    So you have to create a layout for this header in a separate file that could look like this :

    因此,你必须在一个单独的文件中为这个头创建一个布局:

     <!-- The headerView layout. Includes the fake Toolbar & the FloatingActionButton -->
    
     <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <RelativeLayout
            android:id="@+id/header_container"
            android:layout_width="match_parent"
            android:layout_height="@dimen/header_height"
            android:layout_marginBottom="3dp"
            android:background="@android:color/holo_blue_dark">
    
            <RelativeLayout
                android:id="@+id/header_infos_container"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:padding="16dp">
    
                <ImageView
                    android:id="@+id/header_picture"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_marginRight="8dp"
                    android:src="@android:drawable/ic_dialog_info" />
    
                <TextView
                    android:id="@+id/header_title"
                    style="@style/TextAppearance.AppCompat.Title"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_toRightOf="@+id/header_picture"
                    android:text="Toolbar Title"
                    android:textColor="@android:color/white" />
    
                <TextView
                    android:id="@+id/header_subtitle"
                    style="@style/TextAppearance.AppCompat.Subhead"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_below="@+id/header_title"
                    android:layout_toRightOf="@+id/header_picture"
                    android:text="Toolbar Subtitle"
                    android:textColor="@android:color/white" />
    
            </RelativeLayout>
        </RelativeLayout>
    
        <FloatingActionButton
            android:id="@+id/header_fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|right"
            android:layout_margin="10dp"
            android:src="@drawable/ic_open_in_browser"/>
    
    </FrameLayout>
    

    (Note that you can use negative margins/padding for the fab to be straddling on 2 Views)

    (注意,可以使用负边距/填充使fab跨在两个视图上)

  3. Now comes the interesting part. In order to animate the expansion of our fake Toolbar, we implement the ListView onScrollListener.

    现在有趣的部分来了。为了使我们的伪工具栏的扩展具有动画效果,我们实现了ListView onScrollListener。

    // The height of your fully expanded header view (same than in the xml layout)
    int headerHeight = getResources().getDimensionPixelSize(R.dimen.header_height);
    // The height of your fully collapsed header view. Actually the Toolbar height (56dp)
    int minHeaderHeight = getResources().getDimensionPixelSize(R.dimen.action_bar_height);
    // The left margin of the Toolbar title (according to specs, 72dp)
    int toolbarTitleLeftMargin = getResources().getDimensionPixelSize(R.dimen.toolbar_left_margin);
    // Added after edit
    int minHeaderTranslation;
    
    private ListView listView;
    
    // Header views
    private View headerView;
    private RelativeLayout headerContainer;
    private TextView headerTitle;
    private TextView headerSubtitle;
    private FloatingActionButton headerFab;
    
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View rootView = inflater.inflate(R.layout.listview_fragment, container, false);
        listView = rootView.findViewById(R.id.listview);
    
        // Init the headerHeight and minHeaderTranslation values
    
        headerHeight = getResources().getDimensionPixelSize(R.dimen.header_height);
        minHeaderTranslation = -headerHeight + 
            getResources().getDimensionPixelOffset(R.dimen.action_bar_height);
    
        // Inflate your header view
        headerView = inflater.inflate(R.layout.header_view, listview, false);
    
        // Retrieve the header views
        headerContainer = (RelativeLayout) headerView.findViewById(R.id.header_container);
        headerTitle = (TextView) headerView.findViewById(R.id.header_title);
        headerSubtitle = (TextView) headerView.findViewById(R.id.header_subtitle);
        headerFab = (TextView) headerView.findViewById(R.id.header_fab);;
    
        // Add the headerView to your listView
        listView.addHeaderView(headerView, null, false);
    
        // Set the onScrollListener
        listView.setOnScrollListener(this);        
    
        // ...
    
        return rootView;
    }
    
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState)
    {
        // Do nothing
    }
    
    
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
    {
        Integer scrollY = getScrollY(view);
    
        // This will collapse the header when scrolling, until its height reaches
        // the toolbar height
        headerView.setTranslationY(Math.max(0, scrollY + minHeaderTranslation));
    
        // Scroll ratio (0 <= ratio <= 1). 
        // The ratio value is 0 when the header is completely expanded, 
        // 1 when it is completely collapsed
        float offset = 1 - Math.max(
            (float) (-minHeaderTranslation - scrollY) / -minHeaderTranslation, 0f);
    
    
        // Now that we have this ratio, we only have to apply translations, scales,
        // alpha, etc. to the header views
    
        // For instance, this will move the toolbar title & subtitle on the X axis 
        // from its original position when the ListView will be completely scrolled
        // down, to the Toolbar title position when it will be scrolled up.
        headerTitle.setTranslationX(toolbarTitleLeftMargin * offset);
        headerSubtitle.setTranslationX(toolbarTitleLeftMargin * offset);
    
        // Or we can make the FAB disappear when the ListView is scrolled 
        headerFab.setAlpha(1 - offset);
    }
    
    
    // Method that allows us to get the scroll Y position of the ListView
    public int getScrollY(AbsListView view)
    {
        View c = view.getChildAt(0);
    
        if (c == null)
            return 0;
    
        int firstVisiblePosition = view.getFirstVisiblePosition();
        int top = c.getTop();
    
        int headerHeight = 0;
        if (firstVisiblePosition >= 1)
            headerHeight = this.headerHeight;
    
        return -top + firstVisiblePosition * c.getHeight() + headerHeight;
    }
    

Note that there are some parts of this code I didn't test, so feel free to highlight mistakes. But overall, I'm know that this solution works, even though I'm sure it can be improved.

请注意,这段代码中有一些部分我没有进行测试,所以请随意突出错误。但总的来说,我知道这个解决方案是有效的,尽管我确信它可以改进。

EDIT 2:

编辑2:

There were some mistakes in the code above (that I didn't test until today...), so I changed a few lines to make it work :

上面的代码中有一些错误(直到今天我才进行测试…),所以我修改了几行代码以使其工作:

  1. I introduced another variable, minHeaderTranslation, which replaced minHeaderHeight;
  2. 我引入了另一个变量,minHeaderTranslation,它代替了minHeaderHeight;
  3. I changed the Y translation value applied to the header View from :

    我将应用于header视图的Y平移值从:

        headerView.setTranslationY(Math.max(-scrollY, minHeaderTranslation));
    

    to :

    :

        headerView.setTranslationY(Math.max(0, scrollY + minHeaderTranslation));
    

    Previous expression wasn't working at all, I'm sorry about that...

    之前的表达根本没用,我很抱歉……

  4. The ratio calculation also changed, so that it now evolves from the bottom the toolbar (instead of the top of the screen) to the full expanded header.

    比率计算也发生了变化,因此它现在从底部的工具栏(而不是屏幕的顶部)演变为完整的展开标题。

#2


25  

Also check out CollapsingTitleLayout written by Chris Banes in Android team: https://plus.google.com/+ChrisBanes/posts/J9Fwbc15BHN

还可以看看ChrisBanes在Android团队中写的:https://plus.google.com/+ChrisBanes/posts/J9Fwbc15BHN

展开/折叠棒棒糖工具条动画(Telegram app)

Code: https://gist.github.com/chrisbanes/91ac8a20acfbdc410a68

代码:https://gist.github.com/chrisbanes/91ac8a20acfbdc410a68

#3


8  

Use design support library http://android-developers.blogspot.in/2015/05/android-design-support-library.html

使用设计支持库http://android- developers.blogspot.in5/05/android -design-support-library.html

include this in build.gradle

包括在build.gradle

compile 'com.android.support:design:22.2.0'    
compile 'com.android.support:appcompat-v7:22.2.+'

for recycler view include this also

对于回收商来说也包括这个

compile 'com.android.support:recyclerview-v7:22.2.0' 

    <!-- AppBarLayout allows your Toolbar and other views (such as tabs provided by TabLayout) 
    to react to scroll events in a sibling view marked with a ScrollingViewBehavior.-->
    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true">

        <!-- specify tag app:layout_scrollFlags -->
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways"/>

        <!-- specify tag app:layout_scrollFlags -->
        <android.support.design.widget.TabLayout
            android:id="@+id/tabLayout"
            android:scrollbars="horizontal"
            android:layout_below="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways"/>

        <!--  app:layout_collapseMode="pin" will help to pin this view at top when scroll -->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:text="Title"
            android:gravity="center"
            app:layout_collapseMode="pin" />

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

    <!-- This will be your scrolling view. 
    app:layout_behavior="@string/appbar_scrolling_view_behavior" tag connects this features -->
    <android.support.v7.widget.RecyclerView
        android:id="@+id/list"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

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

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

Your activity should extend AppCompatActivity

您的活动应该扩展AppCompatActivity

public class YourActivity extends AppCompatActivity {

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

        //set toolbar
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }

}

Your app theme should be like this

你的应用主题应该是这样的

    <resources>
            <!-- Base application theme. -->   
            <style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
            </style>
    </resources>

#4


1  

This is my implementation:

这是我的实现:

collapsedHeaderHeight and expandedHeaderHeight are defined somewhere else, with the function getAnimationProgress I can get the Expand/Collapse progress, base on this value I do my animation and show/hide the real header.

折叠头高度和扩展头高度是在其他地方定义的,通过函数getAnimationProgress,我可以得到扩展/折叠进度,基于这个值,我做动画并显示/隐藏真正的头。

  listForumPosts.setOnScrollListener(new AbsListView.OnScrollListener() {

        /**
         * @return [0,1], 0 means header expanded, 1 means header collapsed
         */
        private float getAnimationProgress(AbsListView view, int firstVisibleItem) {
            if (firstVisibleItem > 0)
                return 1;

            // should not exceed 1
            return Math.min(
                    -view.getChildAt(0).getTop() / (float) (expandedHeaderHeight - collapsedHeaderHeight), 1);
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            // at render beginning, the view could be empty!
            if (view.getChildCount() > 0) {
                float animationProgress = getAnimationProgress(view, firstVisibleItem);
                imgForumHeaderAvatar.setAlpha(1-animationProgress);
                if (animationProgress == 1) {
                    layoutForumHeader.setVisibility(View.VISIBLE);
                } else {
                    layoutForumHeader.setVisibility(View.GONE);
                }
            }
        }

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            // do nothing
        }

    }