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

下面是一个简单的仿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方法,根据移动的距离进行判断和回调;

@Override
public 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中设置属性动画;

@Override
public 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));

}

@Override
public 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

https://pan.baidu.com/s/1pNbZ1c3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现仿知乎滑动动画可以使用Android平台自带的ViewPager组件,通过设置页面切换时的滑动动画效果实现。具体步骤如下: 1. 在布局文件中添加ViewPager组件。 2. 创建Fragment或者View作为ViewPager的子页面,并将其添加到ViewPager中。 3. 通过ViewPager.setAdapter方法设置ViewPager的适配器,适配器需要继承自FragmentPagerAdapter或者FragmentStatePagerAdapter类。 4. 通过ViewPager.setPageTransformer方法设置页面切换时的滑动动画,可以使用Android平台提供的一些默认动画效果,也可以自定义动画效果。 5. 最后在代码中通过ViewPager.setCurrentItem方法切换页面即可。 以下是一个简单的实现代码示例: ``` // 布局文件中添加ViewPager组件 <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent"/> // 创建Fragment或者View作为ViewPager的子页面 // 创建ViewPager适配器 public class MyPagerAdapter extends FragmentPagerAdapter { private List<Fragment> fragmentList; public MyPagerAdapter(FragmentManager fm, List<Fragment> fragmentList) { super(fm); this.fragmentList = fragmentList; } @Override public Fragment getItem(int position) { return fragmentList.get(position); } @Override public int getCount() { return fragmentList.size(); } } // 在代码中设置ViewPager适配器和滑动动画效果 ViewPager viewPager = findViewById(R.id.viewpager); List<Fragment> fragmentList = new ArrayList<>(); fragmentList.add(new MyFragment1()); fragmentList.add(new MyFragment2()); fragmentList.add(new MyFragment3()); MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager(), fragmentList); viewPager.setAdapter(adapter); viewPager.setPageTransformer(true, new ZoomOutPageTransformer()); // 设置滑动动画 // 自定义动画效果 public class ZoomOutPageTransformer implements ViewPager.PageTransformer { private static final float MIN_SCALE = 0.85f; private static final float MIN_ALPHA = 0.5f; public void transformPage(View view, float position) { int pageWidth = view.getWidth(); int pageHeight = view.getHeight(); if (position < -1) { // [-Infinity,-1) // This page is way off-screen to the left. view.setAlpha(0f); } else if (position <= 1) { // [-1,1] // Modify the default slide transition to shrink the page as well float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position)); float vertMargin = pageHeight * (1 - scaleFactor) / 2; float horzMargin = pageWidth * (1 - scaleFactor) / 2; if (position < 0) { view.setTranslationX(horzMargin - vertMargin / 2); } else { view.setTranslationX(-horzMargin + vertMargin / 2); } // Scale the page down (between MIN_SCALE and 1) view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); // Fade the page relative to its size. view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA)); } else { // (1,+Infinity] // This page is way off-screen to the right. view.setAlpha(0f); } } } ``` 以上就是实现仿知乎滑动动画的基本步骤和示例代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值