仿qq空间标题变色和仿知乎列表滑动隐藏和显示效果

来源:互联网 发布:战斧主机 知乎 编辑:程序博客网 时间:2024/05/21 00:28

下面是一个简单的仿qq空间标题变色的效果:
这里写图片描述

实现思路:根布局是一个RelativeLayout,在RelativeLayout里面放一个ScrollView和LinearLayout(标题布局),将标题布局设置为透明,监听ScrollView的滑动,根据滑动的距离计算出alpha值并设置给标题布局;

1、将标题布局设置为透明

//设置为透明titleBar.getBackground().setAlpha(0);

在将标题布局设置为透明的时候需要注意不要在xml布局里面进行设置,在xml布局里面进行设置的话会连同textview一起变为透明;

2、获取图片和标题栏的高度

//获取图片的高度iv.post(new Runnable() {       @Override       public void run() {           imageHeight=iv.getMeasuredHeight();       }});//获取标题栏高度titleBar.post(new Runnable() {    @Override    public void run() {        measuredHeight  = titleBar.getMeasuredHeight();    }});

在获取一个控件高度或者宽度的时候,直接通过titleBar.getMeasuredHeight();是获取不到的,因为这个时候该控件还没有测量绘制完成,获取到的宽度或者高度为0,可以通过上面的方式获取;

3、监听ScrollView滑动,计算alpha并设置透明度
在调用setOnScrollChangeListener的时候发现,该方法在api23才可以使用,对于api低于23的就不能调用这个方法,不过可以自定义一个ScrollView,重写onScrollChanged方法,在onScrollChanged方法里面进行监听并回调结果;

public class MyScrollView extends ScrollView{    private ScrollChangedListener mListener;    public MyScrollView(Context context) {        super(context);    }    public MyScrollView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    /**     * 监听ScrollView的滑动     * @param l     * @param t     * @param oldl     * @param oldt     */    @Override    protected void onScrollChanged(int l, int t, int oldl, int oldt) {        super.onScrollChanged(l, t, oldl, oldt);        if(mListener!=null){            //将ScrollView滑动监听进行回调            mListener.onScrollChangedListener(l, t, oldl, oldt);        }    }    public interface ScrollChangedListener{        void onScrollChangedListener(int l, int t, int oldl, int oldt);    }    /**     * 设置回调监听     * @param listener     */    public void setOnScrollChangedListener(ScrollChangedListener listener){        this.mListener=listener;    }}

这样子就解决了低版本的滑动监听问题,在回调里面根据滑动的距离计算出alpha值并进行设置,效果就实现了;

//监听scrollView滑动scrollView.setOnScrollChangedListener(new MyScrollView.ScrollChangedListener() {    @Override    public void onScrollChangedListener(int l, int t, int oldl, int oldt) {        // 获取图片的高度,根据当前滚动的位置,计算alpha 值        if (imageHeight == 0) return;        // mImageViewHeight - TitleBar的高度        float alpha = (float) t / (imageHeight-measuredHeight);        if (alpha <= 0) {            alpha = 0;        }        if (alpha > 1) {            alpha = 1;        }        titleBar.getBackground().setAlpha((int) (alpha * 255));        }});

仿知乎列表滑动隐藏和显示效果
实现仿知乎列表滑动隐藏和显示效果有两种方法,一种为:监听滑动+属性动画;另外一种为:behavior;

方法一:监听滑动+属性动画
主要是监听RecyclerView的滑动,

//滑动监听recyclerview.addOnScrollListener(new FabScrollListener(this));

在FabScrollListener里面重写onScrolled方法,根据移动的距离进行判断和回调;

@Overridepublic void onScrolled(RecyclerView recyclerView, int dx, int dy) {    super.onScrolled(recyclerView, dx, dy);    /**     * dy:Y轴方向的增量     * 有正和负     * 当正在执行动画的时候,就不要再执行了     *    */    if (distance > THRESHOLD && visible) {        //隐藏动画        visible = false;        hideListener.onHide();        distance = 0;    } else if (distance < -20 && !visible) {        //显示动画        visible = true;        hideListener.onShow();        distance = 0;    }    if (visible && dy > 0 || (!visible && dy < 0)) {        istance += dy;    }}

在回调方法onHide和onShow中设置属性动画;

@Overridepublic void onHide() {    //隐藏动画    toolbar.animate().translationY(-toolbar.getHeight()).setInterpolator(new AccelerateInterpolator(3));    RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) fab.getLayoutParams();    fab.animate().translationY(fab.getHeight()+layoutParams.bottomMargin).setInterpolator(new AccelerateInterpolator(3));}@Overridepublic void onShow() {    //显示动画    toolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(3));    fab.animate().translationY(0).setInterpolator(new DecelerateInterpolator(3));}

效果如下:
这里写图片描述

方法二:behavior
采用behavior的方式xml的布局要比第一种方式要复杂些;

<?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.support.design.widget.AppBarLayout        android:layout_width="match_parent"        android:layout_height="wrap_content">        <android.support.v7.widget.Toolbar            android:layout_width="match_parent"            android:layout_height="wrap_content"            app:title="知乎首页"            app:titleTextColor="#ffffff"            app:layout_scrollFlags="scroll|enterAlways"            android:id="@+id/tool_bar"/>    </android.support.design.widget.AppBarLayout>    <android.support.v7.widget.RecyclerView        android:id="@+id/recycler_view"        android:layout_width="match_parent"        android:layout_height="match_parent"        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>      <android.support.design.widget.FloatingActionButton          android:layout_width="wrap_content"          android:layout_height="wrap_content"           android:layout_gravity="bottom|end"          android:layout_marginBottom="70dp"          android:layout_marginEnd="16dp"          android:layout_marginRight="16dp"          android:src="@mipmap/add_icon"          app:layout_scrollFlags="scroll|enterAlways|snap"          app:layout_behavior="com.qqtitlebar.TanslationBehavior"/>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="?actionBarSize"        android:layout_alignParentBottom="true"        android:background="@android:color/white"        app:layout_behavior="@string/bottom_sheet_behavior">        <ImageView            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            android:src="@mipmap/message_icon" />        <ImageView            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            android:src="@mipmap/message_icon"            />        <ImageView            android:layout_width="0dp"            android:layout_height="match_parent"            android:src="@mipmap/message_icon"            android:layout_weight="1"/>        <ImageView            android:layout_width="0dp"            android:layout_height="match_parent"            android:src="@mipmap/message_icon"            android:layout_weight="1" />    </LinearLayout></android.support.design.widget.CoordinatorLayout>

这里涉及到一些Materia Design的控件:CoordinatorLayout、FloatingActionButton、AppBarLayout、Toolbar、RecyclerView,
CoordinatorLayout这里的协调behavior;
这里给RecyclerView和LinearLayout设置了app:layout_behavior,不过这两个都是系统的behavior,

RecyclerView:

app:layout_behavior="@string/appbar_scrolling_view_behavior"

LinearLayout:

app:layout_behavior="@string/bottom_sheet_behavior"

FloatingActionButton设置的是一个自定义的behavior

app:layout_behavior="com.qqtitlebar.TanslationBehavior"
public class TanslationBehavior extends FloatingActionButton.Behavior{    public TanslationBehavior(Context context, AttributeSet attrs){        super(context, attrs);    }    //关注垂直滚动,二轻向上的时候出来,向下是隐藏    @Override    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {        return nestedScrollAxes== ViewCompat.SCROLL_AXIS_VERTICAL;    }    private boolean isOut=false;    @Override    public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);        //而且向上的时候是出来的,向下是隐藏        if(dyConsumed>0){            if(!isOut){                //往上滑动,是隐藏,加一个标志为 已经往下走了                int translationY = ((CoordinatorLayout.LayoutParams) child.getLayoutParams()).bottomMargin + child.getMeasuredHeight();                child.animate().translationY(translationY).setDuration(500).start();                isOut=true;            }        }else{            child.animate().translationY(0).setDuration(500).start();            isOut=false;        }    }}

在自定义behavior的时候需要注意的就是一定要记得写构造方法,在布局文件中引用后,系统去找引用文件中的构造方法,如果没有就会报错;
采用behavior方式不用给RecyclerView设置addOnScrollListener方法进行监听;不过采用behavior方式涉及到很多Materia Design风格的新控件,需要做一些版本兼容,这里运行的环境是android6.0,未做版本兼容;
android6.0效果:
这里写图片描述

源码地址:
http://download.csdn.net/download/wangwo1991/9935522

阅读全文
0 0
原创粉丝点击