• Android -- 自定义ScrollView实现放大回弹效果


    1,刚刚在别人开源的项目中看到了一个挺不错的用户体验,效果图如下:

    2,那下面我们就来实现一下,首先看一下布局,由于一般只是我们包含头像的那部分方法,所以这里我们要把布局分成两部分,对应的布局文件效果图如下:

    3,自定义ScrollView

      第一步:创建一个类,继承自ScrollView,重写相应的构造函数

    public class ZoomInScrollView extends ScrollView {
     public ZoomInScrollView(Context context) {
            this(context, null);
        }
    
        public ZoomInScrollView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public ZoomInScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    }
    

      第二步:重写OnFinishInflate()方法,并记录第一个子view,即我们的head_fragment

    @Override
        protected void onFinishInflate() {
            super.onFinishInflate();
            //设置不可过度滚动,否则上移后下拉会出现部分空白的情况
            setOverScrollMode(OVER_SCROLL_NEVER);
            View child = getChildAt(0);
            if (child != null && child instanceof ViewGroup) {
                //获取默认第一个子View
                mHeaderView = ((ViewGroup) child).getChildAt(0);
            }
        }
    

      第三步:重写OnTouchEvent()方法,在Action_Move方法中拿到下滑的距离,通过设置head_view的属性参数来改变它的大小,在UP的时候还原head_view

    @Override
        public boolean onTouchEvent(MotionEvent ev) {
            if (mHeaderView == null)
                return super.onTouchEvent(ev);
            switch (ev.getAction()) {
                case MotionEvent.ACTION_MOVE:
                    if (!mIsPulling) {
                        //第一次下拉
                        if (getScrollY() == 0) {
                            //在顶部的时候,记录顶部位置
                            mLastY = (int) ev.getY();
                        } else {
                            break;
                        }
                    }
                    if (ev.getY() - mLastY < 0)
                        return super.onTouchEvent(ev);
                    int distance = (int) ((ev.getY() - mLastY) * mScaleRatio);
                    mIsPulling = true;
                    setZoom(distance);
                    return true;
                case MotionEvent.ACTION_UP:
                    mIsPulling = false;
                    replyView();
                    break;
            }
            return super.onTouchEvent(ev);
        }
    

        在回弹view的时候通过属性动画动态的改变head_view的值,并重写onSizeChange()方法,实时的记录head_view的宽高

    **
         * 放大view
         */
        private void setZoom(float s) {
            float scaleTimes = (float) ((mHeaderWidth + s) / (mHeaderWidth * 1.0));
    //        如超过最大放大倍数,直接返回
            if (scaleTimes > mScaleTimes) return;
    
            ViewGroup.LayoutParams layoutParams = mHeaderView.getLayoutParams();
            layoutParams.width = (int) (mHeaderWidth + s);
            layoutParams.height = (int) (mHeaderHeight * ((mHeaderWidth + s) / mHeaderWidth));
    //        设置控件水平居中
            ((MarginLayoutParams) layoutParams).setMargins(-(layoutParams.width - mHeaderWidth) / 2, 0, 0, 0);
            mHeaderView.setLayoutParams(layoutParams);
        }
    
        /**
         * 回弹
         */
        private void replyView() {
            final float distance = mHeaderView.getMeasuredWidth() - mHeaderWidth;
            // 设置动画
            ValueAnimator anim = ObjectAnimator.ofFloat(distance, 0.0F).setDuration((long) (distance * mReplyRatio));
            anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    setZoom((Float) animation.getAnimatedValue());
                }
            });
            anim.start();
        }
    
    @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mHeaderWidth = mHeaderView.getMeasuredWidth();
            mHeaderHeight = mHeaderView.getMeasuredHeight();
        }
    

      这样就实现了我们的效果了,看一下我们自己实现的效果:

       github下载地址(还没有传上去,网速差,骚等一下),有需要源码的同学可以去下载一下。See You Next Time ......

  • 相关阅读:
    lvs持久连接及防火墙标记实现多端口绑定服务
    LVS负载均衡器DR模型的实现
    CentOS 6.5结合busybox完成自制Linux系统及远程登录和nginx安装测试
    CentOS 6.5下的lamp环境rsyslog+MySQL+loganalyzer实现日志集中分析管理
    centos中selinux功能及常用服务配置
    网站遭遇CC及DDOS攻击紧急处理方案
    centos6.5下系统编译定制iptables防火墙扩展layer7应用层访问控制功能及应用限制QQ2016上网
    centos 6.5内核编译步骤及配置详解
    centos系统初始化流程及实现系统裁剪
    iptables实现网络防火墙及地址转换
  • 原文地址:https://www.cnblogs.com/wjtaigwh/p/6549863.html
Copyright © 2020-2023  润新知