• 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 ......

  • 相关阅读:
    iOS 静态、全局变量、常量
    原子性atomic/nonatomic
    iOS数组遍历
    iOS开发过程中易犯的小错误
    mac开启Airdrop的硬件要求
    Activity Monitor 闪退 & 无法进入睡眠
    在Linux中连接android设备
    网格布局(GridLayout) 行数与列数
    $符号报not defing 报错
    eclipse鼠标变成十字符号
  • 原文地址:https://www.cnblogs.com/wjtaigwh/p/6549863.html
Copyright © 2020-2023  润新知