Android控件显示/隐藏时添加动画:ViewSwitcher

来源:互联网 发布:口罩行业数据 编辑:程序博客网 时间:2024/06/12 23:35

需求描述:整个页面有一个头布局和内容显示布局,头布局会根据下面内容区域的上下滑动来隐藏或显示(隐藏或显示时均有动画)。
内容布局可以是任何可以上下滑动的布局。当头布局隐藏时,整个页面都要可以显示内容,所以内容布局高度需match_parent。
这里写图片描述

实现思路:
1.将头布局用ViewSwitcher(ViewSwitcher最多两个子View)包裹,另外在ViewSwitcher中添加一个高度为0dp的布局跟这个头布局进行交替显示。

@Override    public void addView(View child, int index, ViewGroup.LayoutParams params) {        if (getChildCount() >= 2) {            throw new IllegalStateException("Can't add more than 2 views to a ViewSwitcher");        }        super.addView(child, index, params);    }

2.可以在ViewSwitcher中设置动画。

3.内容布局设置滚动监听,根据上下滑动的偏移量来控制ViewSwitcher具体显示哪个子View。

代码实现:

布局文件

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent">    <android.support.v7.widget.RecyclerView        android:id="@+id/rv_movie"        android:layout_width="match_parent"        android:layout_height="match_parent"/>    <com.example.customview.MyViewSwitcher        android:id="@+id/viewswitch"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_below="@id/head"        android:inAnimation="@anim/slide_in_top"        android:outAnimation="@anim/slide_out_top"        android:persistentDrawingCache="animation">        <LinearLayout            android:id="@+id/ll_head"            android:layout_width="match_parent"            android:layout_height="200dp"            android:background="@color/white"            android:gravity="center">            <TextView                android:gravity="center"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:paddingBottom="6dp"                android:paddingTop="6dp"                android:textColor="@color/colorTitle2"                android:textSize="@dimen/text_size_14"                android:text="头布局" />        </LinearLayout>        <!--高度为0的空布局-->        <View            android:layout_width="match_parent"            android:layout_height="0dp" />    </com.example.customview.MyViewSwitcher></RelativeLayout>

动画文件
slide_in_top.xml

<?xml version="1.0" encoding="utf-8"?><translate xmlns:android="http://schemas.android.com/apk/res/android"    android:duration="300"    android:fromYDelta="-100%p"    android:interpolator="@android:anim/decelerate_interpolator"    android:toYDelta="0" />

slide_out_top.xml

<?xml version="1.0" encoding="utf-8"?><translate xmlns:android="http://schemas.android.com/apk/res/android"    android:duration="300"    android:fromYDelta="0"    android:interpolator="@android:anim/accelerate_interpolator"    android:toYDelta="-100%p" />

自定义ViewSwitcher:MyViewSwitcher
在MyViewSwitcher中封装了具体显示哪个子View的方法

public class MyViewSwitcher extends ViewSwitcher {    /**     * 真正的头布局     */    private View firstChildView;    /**     * 高度为0的空布局     */    private View secondChildView;    private static final int DELTA = 400;//根据具体情况设置值的大小    /**     * y方向偏移量总和     */    private int DY = 0;    public MyViewSwitcher(Context context) {        this(context, null);    }    public MyViewSwitcher(Context context, AttributeSet attrs) {        super(context, attrs);    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        firstChildView = getChildAt(0);        secondChildView = getChildAt(1);    }    /**     * 根据外部传入的y值来设置显示哪个子View     * 如果向上滑动了好几页,突然想回到头布局时,只需向下滑动DELTA偏移即可显示头布局(语言功底差,描述不到位,相信大家都懂)     *     * @param delta     */    public void whichOneShow(int delta) {        DY += delta;        //向上滑动        //当y偏移量总和大于DELTA,且第一个子View显示时,设置第二个子View显示        if (DY > DELTA && firstChildView.getVisibility() == VISIBLE) {            DY = 0;            setDisplayedChild(1);        } else if (DY > 0 && secondChildView.getVisibility() == VISIBLE) {            //继续向上滑动,且第二个子View一直处于显示状态,则将偏移量总和置零            DY = 0;        }        //向下滑动        //当y偏移量总和大于DELTA(即小于[-DELTA]),且第二个子View显示时,设置第一个子View显示        if (DY < -DELTA && secondChildView.getVisibility() == VISIBLE) {            DY = 0;            setDisplayedChild(0);        } else if (DY < 0 && firstChildView.getVisibility() == VISIBLE) {            //继续向下滑动,且第一个子View一直处于显示状态,则将偏移量总和置零            DY = 0;        }    }}

MainActivity

public class MainActivity extends AppCompatActivity{    private RecyclerView mRecyclerView;    private MyViewSwitcher mViewSwitch;    @Override    public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {        super.onCreate(savedInstanceState, persistentState);        setContentView(R.layout.activity_search_movie);        initViews();    }    protected void initViews() {        mRecyclerView = (RecyclerView) findViewById(R.id.rv_movie);        mViewSwitch = (MyViewSwitcher) findViewById(R.id.viewswitch);        //RecyclerView设置数据部分代码省略        //...        //根据RecyclerView在竖直方向滑动的偏移量来控制头布局显示/隐藏        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {            @Override            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {                super.onScrolled(recyclerView, dx, dy);                mViewSwitch.whichOneShow(dy);            }        });    }}

如有错误或不足之处,欢迎指正。。

0 0
原创粉丝点击