Android ClassAndroid葵花宝典Android效果/自定义

【Android】这效果,我没法描述

2017-08-05  本文已影响3015人  带心情去旅行

前言

最近接到一个需求,这需求让我表示很尴尬。(下面是一些废话)
要求的效果是这样的,顶部有部分悬浮,接着是一些布局,在下面是几个可切换的Tab页面,然后滚动的时候~~吧啦吧啦吧啦吧啦~~ 还是直接看图吧

效果
主要就是顶部和Tab的悬浮,还有就是被顶掉的那个效果。

听到要实现这样的效果,我抽屉那把砍产品专用菜刀已经蠢蠢欲动了。

思路

先说说实现的思路吧,上面的效果大致可以分成两个部分:

拆分完毕,接下来就是实现了

实现

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFF">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#FFF">

        <LinearLayout
            android:id="@+id/ll"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:id="@+id/header"
                android:layout_width="match_parent"
                android:layout_height="260dp"
                android:scaleType="centerCrop"
                android:src="@drawable/bg_header"/>
        </LinearLayout>

        <android.support.design.widget.TabLayout
            android:id="@+id/table_layout"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="#FBDD9C"
            app:tabGravity="fill"
            app:tabIndicatorColor="#5f00"
            app:tabIndicatorHeight="4dp"
            app:tabMode="fixed"
            app:tabSelectedTextColor="#FFFFFF"
            app:tabTextColor="#FFFFFF"/>
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/vp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>

layout_scrollFlags:AppBarLayout供Children View使用的属性,一共有五种值:scroll,enterAlways,enterAlwaysCollapsed,snap,exitUntilCollapsed。具体的使用可以参考Android 详细分析AppBarLayout的五种ScrollFlags
(CoordinatorLayout、AppBarLayout的详细用法我就不多说了)

然后,只要在Java代码中为ViewPager添加几个列表Fragment就能看到以下的效果(注意:列表不可以是ListView,需要用RecyclerView

效果

到目前为止,效果已经实现了大半。最后值需要实现“被顶走”的效果就好了。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#FFF">

        <android.support.design.widget.AppBarLayout
            android:id="@+id/app_bar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#FFF">

            <LinearLayout
                android:id="@+id/ll"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                app:layout_scrollFlags="scroll|exitUntilCollapsed">

                <View
                    android:layout_width="match_parent"
                    android:layout_height="50dp"/>

                <ImageView
                    android:id="@+id/header"
                    android:layout_width="match_parent"
                    android:layout_height="260dp"
                    android:scaleType="centerCrop"
                    android:src="@drawable/bg_header"/>
            </LinearLayout>

            <android.support.design.widget.TabLayout
                android:id="@+id/table_layout"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:background="#FBDD9C"
                app:tabGravity="fill"
                app:tabIndicatorColor="#5f00"
                app:tabIndicatorHeight="4dp"
                app:tabMode="fixed"
                app:tabSelectedTextColor="#FFFFFF"
                app:tabTextColor="#FFFFFF"/>
        </android.support.design.widget.AppBarLayout>

        <android.support.v4.view.ViewPager
            android:id="@+id/vp"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
    </android.support.design.widget.CoordinatorLayout>

    <TextView
        android:id="@+id/sticky_view"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:textColor="#FFFFFF"
        android:text="除了悬浮 我还会动"
        android:gravity="center"
        android:textSize="16sp"
        android:background="#39b9e9"/>
</FrameLayout>

在原有的基础上,套了个FrameLayout,顶部的悬浮部分可以通过FrameLayout来实现。这样也导致下面的布局被盖住了一部分,因此在LinearLayout中加了与悬浮部分相同高度的空View

布局是完成了,那个“被顶走”的效果怎么实现呢?这时候只要在MainActivity中对AppBarLayout的滚动进行监听即可。

    @BindView(R.id.app_bar)
    AppBarLayout mAppBar;
    @BindView(R.id.sticky_view)
    View mStickyView;
    @BindView(R.id.header)
    View mHeader;

    private void setAppBarListener() {
        mAppBar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                //头部高度(除去被顶部覆盖的部分)
                int minScrollHeight = mHeader.getMeasuredHeight();
                int margin = minScrollHeight + verticalOffset;
                margin = margin > 0 ? 0 : margin;
                FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mStickyView.getLayoutParams();
                layoutParams.topMargin = margin;
                mStickyView.setLayoutParams(layoutParams);
            }
        });
}

这里通过AppBarLayout滚动的进行监听(向上滚动时,verticalOffset值的变化为:0、-1 、-2 ... -n-1、-n)来计算margin值。通过改变topMargin,实现“被顶走”的效果。
再看一眼效果:

效果

敲到这里,我才默默的收起了那把砍产品专用菜刀。

Tips

mAblAppBar.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> {
   if (verticalOffset == 0) {
      swipeLayout.setEnabled(true);
   } else {
       if (!swipeLayout.isRefreshing()) {
          swipeLayout.setEnabled(false);
       }
   }
});

源码地址

Github

以上有错误之处,感谢指出

上一篇下一篇

猜你喜欢

热点阅读