android的阻尼效果-ListView添加阻尼效果的HeadView

本文介绍了一种在Android应用中实现阻尼效果的方法,通过自定义PullZoomListView组件,利用ValueAnimator实现下拉刷新时视图的阻尼缩放动画。文章提供了完整的代码示例,包括关键的触摸事件处理逻辑及动画实现细节。
摘要由CSDN通过智能技术生成

转载:android的阻尼效果

这里写图片描述

package com.xiey94.zuni;

import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AbsListView;
import android.widget.LinearLayout;
import android.widget.ListView;

/**
 * @author xiey
 * @date created at 2017/12/6 20:34
 * @package com.xiey94.zuni
 * @motto Why should our days leave us never to return?
 */

public class PullZoomListView extends ListView {

    /**
     * 要实现阻尼效果的HeadView
     */
    private LinearLayout mHeadView;

    /**
     * 默认状态下要实现阻尼效果的HeadView
     */
    private int mHeadViewHeight;
    private AbsListView.LayoutParams params;

    /**
     * 自定义下拉增加的最大高度
     */
    private int mMaxHeight = 200;

    /**
     * 按下的y轴的值,默认为 :-1
     */
    private int mDownY = -1;

    /**
     * 记录最终下拉的高度,默认为:-1
     */
    private int mDiffY = -1;

    /**
     * 构造函数
     */
    public PullZoomListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initHeadView();
    }

    /**
     * 给ListView的HeadView添加要实现阻尼效果的View
     */
    private void initHeadView() {
        mHeadView = (LinearLayout) View.inflate(getContext(), R.layout.head_view, null);
        //手动测量宽高,最终是UNSPECIFIED :模式下父容器不会对子元素加以任何约束,直接是图片的大小
        mHeadView.measure(0, 0);
        mHeadViewHeight = mHeadView.getMeasuredHeight();
        Log.e("TAG", "measureHeight:" + mHeadViewHeight);
        this.addHeaderView(mHeadView);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (isDisplayHeaderView()) {
                    params = (AbsListView.LayoutParams) mHeadView.getLayoutParams();
                    mDownY = (int) ev.getY();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (isDisplayHeaderView()) {
                    if (mDownY == -1) {
                        mDownY = (int) ev.getY();
                    }
                    int moveY = (int) ev.getY();
                    //移动的间距
                    int diffY = moveY - mDownY;
                    if (diffY >= mMaxHeight) {
                        diffY = mMaxHeight;
                    }

                    if (diffY > 0) {
                        mDiffY = diffY;
                        params.height = mHeadViewHeight + mDiffY;
                        mHeadView.setLayoutParams(params);
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                if (mDiffY > 0 && isDisplayHeaderView()) {
                    reset();
                }
                break;
            default:
                break;
        }
        return super.onTouchEvent(ev);
    }

    /**
     * 释放手指后实现阻尼效果
     */
    private void reset() {
//        mDiffY = -1;
        //动画器
        ValueAnimator animator;
        //动画更新的监听
        animator = ValueAnimator.ofInt(mHeadViewHeight + mDiffY, mHeadViewHeight);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //获取动画当前变化的值
                Integer height = (Integer) animation.getAnimatedValue();
                //根据最新高度,更新布局高度
                params.height = height;
                mHeadView.setLayoutParams(params);
            }
        });
        //动画时间
        animator.setDuration(50);
        //开启动画
        animator.start();
    }

    public View getView() {
        return mHeadView;
    }

    /**
     * 判断HeadView是否完全显示了
     * true完全显示,false没有显示
     */
    private boolean isDisplayHeaderView() {
        //0存储x,1存储y
        int[] location = new int[2];
        //获取HeadView屏幕中y轴的值
        mHeadView.getLocationOnScreen(location);
        int mSecondHeaderViewYOnScreen = location[1];
        return mSecondHeaderViewYOnScreen > 0 ? true : false;
    }
}

head_view.xml

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

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="fitXY"
            android:src="@drawable/huge_min" />
    </RelativeLayout>
</LinearLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        PullZoomListView listView = (PullZoomListView) findViewById(R.id.listView);
        List<String> data = new ArrayList<>();

        for (int i = 0; i < 30; i++) {
            data.add("嘻嘻哈哈哈AKD");
        }

        listView.setAdapter(new ArrayAdapter(this, android.R.layout.simple_expandable_list_item_1, data));
    }
}

activity_main.xml

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

    <com.xiey94.zuni.PullZoomListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

这里要注意一下:

mHeadView.measure(0, 0);

可参考:调用view.measure(0,0)时发生了什么


最后附赠上胡歌的帅照:

胡歌


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值