安卓头部视差(Parallax)实现

本文介绍了一种模仿QQ控件中滑动效果的实现方法。通过自定义ListView并结合ValueAnimator,根据手指滑动距离调整头部ImageView的高度,达到平滑过渡的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

看着QQ控件的这种效果挺炫的于是就照着教程模仿着写了一个,完成之后整理一下思路,觉着还是比较简单的,实现核心就是根据手指滑动距顶部距离来改变头部ImageView控件的高度。

下面贴出代码:

ListView的头布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
<ImageView
    android:id="@+id/imageview"
    android:layout_width="match_parent"
    android:layout_height="240dp"
    android:scaleType="centerCrop"
    android:src="@mipmap/image"
    />


</LinearLayout>

这里的注意点就是图片设置给Src,这样修改ImageView的高度才能看出效果。

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent" 
    android:layout_height="match_parent"
    tools:context="com.example.studyparallax.MainActivity">

    <com.example.studyparallax.com.customUi.ParallaxListView
        android:id="@+id/parallaxListView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
/>

</RelativeLayout>

重写的ListView增加了Parallax的功能:

package com.example.studyparallax.com.customUi;

import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewTreeObserver;
import android.view.animation.OvershootInterpolator;
import android.widget.ImageView;
import android.widget.ListView;

/**
 * Created by 春水碧于天 on 2017/1/6.
 */

public class ParallaxListView extends ListView {

    private int maxHeight; //图片的高度
    private int orignalHeight; //ImageView的最初的高度
    public ParallaxListView(Context context) {
        super(context);
    }

    public ParallaxListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ParallaxListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public ParallaxListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }




    private ImageView imageView;

    public void setParallaxImage(final ImageView Imageview){

        this.imageView = Imageview;

        imageView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

            @Override
            public void onGlobalLayout() {

                imageView.getViewTreeObserver().removeOnGlobalLayoutListener(this);

                orignalHeight = imageView.getHeight(); //获取imageview的最初高度
                int drawableHeight = imageView.getDrawable().getIntrinsicHeight();

                //如果ImageView的高度比图片的高度大的情况下就设置图片的最大高度为imageview的二倍
                maxHeight = orignalHeight >drawableHeight? orignalHeight *2:drawableHeight;

                //获取图片的高度,而不是ImageView的高度
                maxHeight = Imageview.getDrawable().getIntrinsicHeight();

            }
        });



    }

    /**
     * 在listView滑动到头的时候,可以获取到继续滑动的距离和方向
     * @param deltaY 继续滑动的x方向的距离
     * @param scrollY
     * @param scrollRangeX
     * @param scrollRangeY
     * @param maxOverScrollX x方向最大可以滚动的距离
     * @param maxOverScrollY y方向最大可以滚动的距离
     * @param isTouchEvent true:是手指滑动 false:惯性滑动
     * @return
     */
    //所有可以滚动的View都有这个方法
    @Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {


        if(deltaY<0 && isTouchEvent){

            Log.i("Tag","deltaY:"+deltaY);


            if(imageView!=null){

                int newHeight = imageView.getHeight()-deltaY/3;
                Log.i("tag","newHeight====>:"+newHeight);

                if(newHeight>maxHeight) newHeight =maxHeight;

                    imageView.getLayoutParams().height = newHeight;
                    imageView.requestLayout(); //使设置的高度生效


            }

        }

        return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        if(ev.getAction() == MotionEvent.ACTION_UP){

            //手指抬起时

            //手指抬起将图片从当前高度变换成初始时的高度
            final ValueAnimator animator = ValueAnimator.ofInt(imageView.getHeight(),orignalHeight);

            //添加一个值的动画监听
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {

                    //获取动画的值设置给ImageView
                    int animatedValue = (int)animator.getAnimatedValue();
                    imageView.getLayoutParams().height = animatedValue;
                    imageView.requestLayout();


                }
            });

            animator.setInterpolator(new OvershootInterpolator()); //设置一个弹性插值器
            animator.setDuration(350);
            animator.start();


        }

        return super.onTouchEvent(ev);
    }
}

MainActivity:

package com.example.studyparallax;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;

import com.example.studyparallax.com.customUi.ParallaxListView;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private ParallaxListView parallaxListView;
    private ImageView imageView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        parallaxListView = (ParallaxListView) findViewById(R.id.parallaxListView);
        ArrayList<String> Arrays = new ArrayList<String>();

        for(int i=0;i<=20;i++){


            Arrays.add(i+"");

        }


        View HeaderView = View.inflate(MainActivity.this,R.layout.listview_headre,null);

        imageView = (ImageView)HeaderView.findViewById(R.id.imageview);

        //取出顶部滑动的蓝色阴影
        parallaxListView.setOverScrollMode(ListView.OVER_SCROLL_NEVER);
        //将图片设置给ParallaxListView,需要操作头布局设置进去的ImageView的一些参数
        parallaxListView.setParallaxImage(imageView);
        //给ListView添加一个头布局
        parallaxListView.addHeaderView(HeaderView);

        parallaxListView.setAdapter(new ArrayAdapter<String>(this,R.layout.support_simple_spinner_dropdown_item,Arrays));
    }
}

实现效果:
这里写图片描述

这里的动画的实现使用的是ValueAnimator,初涉,对它的Api理解的还不够深入,后面要深入的研究一下,对安卓的动画还是挺感兴趣的!(^_^)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值