仿微信朋友圈(QQ空间)下拉刷新(头部放大动画效果)

仿微信朋友圈下拉刷新(头部放大动画效果)

现在比较流行的Material Design控件已经可以实现更加炫酷的效果,以下我根据微信朋友圈(QQ空间也如此)原始的写法,基本可以达到预期效果。


先看下效果图
效果展示


布局文件由一张美女图和一个圆形icon组成,代码如下:

<?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="120dp">
    <ImageView
        android:id="@+id/layout_header_image"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:scaleType="centerCrop"
        android:src="@drawable/image"/>

    <ImageView
        android:id="@+id/icon"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:src="@drawable/icon"
        android:layout_alignParentLeft="true"
        android:layout_alignParentBottom="true"
        android:layout_marginLeft="20dp"
        android:layout_marginBottom="20dp"
        />
</RelativeLayout>

看完Demo可以想到下面必定是一个list列表,上面的美女图片我以headerView的形式加在列表之上,而向下滑动的过程则是调用了overScrollBy方法中两个重要参数 dx,dy。于是,我重写了一个listview去实现该方法:

public class PushListView extends ListView {

    private int mImageViewHeight = 0;
    private boolean refresh = false;
    private ImageView mImageView,image_icon;

    public PushListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mImageViewHeight = context.getResources().getDimensionPixelSize(R.dimen.header_height);
    }

    public void setZoomImageView(ImageView iv,ImageView icon) {
        mImageView = iv;
        image_icon = icon;
    }

    public void isRefresh( boolean a){
        if(a == true){
            image_icon.clearAnimation();
            image_icon.setVisibility(View.GONE);
        }
    }

    @Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
        /*
        dx,dy增量
        deltaY:
        -:下拉过度
        +:上拉过度
         */
        if (deltaY < 0) {
            mImageView.getLayoutParams().height = mImageView.getHeight() - deltaY;
            image_icon.setRotation(image_icon.getRotation() - deltaY);
            mImageView.requestLayout();
        } else {
            //缩小
            if (mImageView.getHeight()>mImageViewHeight) {
                mImageView.getLayoutParams().height = mImageView.getHeight() - deltaY;
                mImageView.requestLayout();
            }
        }
        return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        //让头部在上滑时缩小,监听
        View header = (View) mImageView.getParent();
        //header.getTop()<0头部滑出的距离
        if (header.getTop() < 0 && mImageView.getHeight() > mImageViewHeight) {
            mImageView.getLayoutParams().height = mImageView.getHeight() + header.getTop();
            header.layout(header.getLeft(), 0, header.getRight(), header.getHeight());
            mImageView.requestLayout();
        }
        super.onScrollChanged(l, t, oldl, oldt);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        if(action == MotionEvent.ACTION_UP){//松开手弹回初始位置
            ResetAnimation animation = new ResetAnimation(mImageView,mImageViewHeight);
            animation.setDuration(300);
            mImageView.startAnimation(animation);
            image_icon.startAnimation(rotationAnimation());
        }
        return super.onTouchEvent(ev);
    }

    public class ResetAnimation extends Animation{
        private ImageView mTv;
        private int targetHeight;
        private int originalHeight;
        private int extraHeight;
        public ResetAnimation(ImageView iv, int targetHeight) {
            this.mTv = iv;
            this.targetHeight = targetHeight;//最终恢复的高度
            this.originalHeight = mTv.getHeight();//现在的高度
            this.extraHeight = originalHeight - targetHeight;//高度差
        }
        //下拉过度,弹回去动画
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            //interpolatedTime(0.0 to 1.0)   执行的百分比
            mImageView.getLayoutParams().height = (int) (originalHeight - extraHeight * interpolatedTime);
            mImageView.requestLayout();
            super.applyTransformation(interpolatedTime, t);
        }
    }
    //刷新icon动画集(旋转刷新)
    public Animation rotationAnimation(){
        Animation  mRotateAnimation = new RotateAnimation(0.0f, 720.0f, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
        mRotateAnimation.setFillAfter(true);
        mRotateAnimation.setInterpolator(new LinearInterpolator());
        mRotateAnimation.setDuration(1000);
        mRotateAnimation.setRepeatCount(Animation.INFINITE);
        mRotateAnimation.setRepeatMode(Animation.RESTART);
        return  mRotateAnimation;
    }
}

最后将重写的listview应用到Mainactivity中,布局为一个listview,这里就不贴出了。我在handler中模拟了一次下拉刷新的过程,具体操作还要看业务逻辑去具体实现:

public class MainActivity extends Activity {

    private PushListView listView;
    ImageView iv,icon;
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if(msg.what==1){
                listView.isRefresh(true);//模拟下拉刷新
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        View header = View.inflate(this,R.layout.item_header,null);
        iv = (ImageView) header.findViewById(R.id.layout_header_image);
        icon = (ImageView) header.findViewById(R.id.icon);
        listView = (PushListView) findViewById(R.id.listview);
        ArrayAdapter<String> adapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,
                new String[] {
                        "周一上班",
                        "周二继续上班",
                        "周三打豆豆",
                        "周四打篮球",
                        "周五放假"
                });
        listView.addHeaderView(header);
        listView.setZoomImageView(iv,icon);
        listView.setAdapter(adapter);

        mHandler.sendEmptyMessageDelayed(1,6000);
    }
}

以上为整个效果的全部过程,代码比较简洁,主要需要理解的是listview的onscrollby方法,对于头部高度做实时控制,开发过程中也是遇到了不少问题,但是不要急躁,一步一个脚印,总能实现。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值