Android Scroller实战(二)窗帘效果实现

来源:互联网 发布:吴敦义 知乎 编辑:程序博客网 时间:2024/05/15 09:33

基于上一次讲解的登陆弹出框,如果你已经完全理解上一篇文章,那么今天对你来说就是小菜一碟了,此案例是在我的上一篇文章的基础上进行开发的,如果你感觉看着有点难理解,请先阅读Android Scroller入门(二),此案例并非原创,只是在别人写好的基础上进行改编而来的,下面给出一张图看一下直观的效果。


下面我就来讲解一下这个案例中主要的代码逻辑部分,你可以下载我最后提供的源码,导入到你的ADT或者Android  Studio中跟着思路来看。
1.自定义View extends RelativeLayout,然后重写构造方法,初始化布局。

 public CurtainView(Context context) {        this(context, null);    }    public CurtainView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public CurtainView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        init(context);    }    private void init(Context context) {        this.mContext = context;        //Interpolator 设置为有反弹效果的  (Bounce:反弹)        Interpolator interpolator = new BounceInterpolator();        mScroller = new Scroller(context, interpolator);        mScreenHeigh = Utils.getWindowHeigh(context);        mScreenWidth = Utils.getWindowWidth(context);        // 背景设置成透明        this.setBackgroundColor(Color.argb(0, 0, 0, 0));        final View view = LayoutInflater.from(mContext).inflate(R.layout.curtain, null);        img_curtain_ad = (ImageView) view.findViewById(R.id.img_curtain_ad);        img_curtain_rope = (ImageView) view.findViewById(R.id.img_curtain_rope);        addView(view);        img_curtain_ad.post(new Runnable() {            @Override            public void run() {                curtainHeigh = img_curtain_ad.getHeight();                //在当前视图内容偏移至(x , y)坐标处.                CurtainView.this.scrollTo(0, curtainHeigh);                //注意scrollBy和scrollTo的区别                Log.i(TAG, "curtainHeigh" + curtainHeigh + "");            }        });        img_curtain_rope.setOnTouchListener(this);    }
在构建Scroller实例的时候,需要传递一个Android自带的一个动画插入器BounceInterpolator来实现抖动的效果,然后用布局填充器将一个xml布局文件填充成一个view(可以调用View.inflate方法),将此view添加到RelativeLayout中,最后获取到此view的高度,调用scrollTo将此view滚动到不可见状态。

2.处理第一步中的onTouchListener对应的触摸事件,重写onTouchEvent方法

@Overridepublic boolean onTouch(View v, MotionEvent event) {    if (!isMove) {        int offViewY = 0;        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                downY = (int) event.getRawY();                //屏幕顶部和该布局顶部的距离                offViewY = downY - (int) event.getY();                return true;            case MotionEvent.ACTION_MOVE:                moveY = (int) event.getRawY();                scrollY = moveY - downY;                if (scrollY < 0) {                    if (isOpen) { // 向上滑动                        if (Math.abs(scrollY) <= img_curtain_ad.getBottom() - offViewY) {                            scrollTo(0, -scrollY);                        }                    }                } else {                    if (!isOpen) { // 向下滑动                        if (scrollY <= curtainHeigh) {                            scrollTo(0, curtainHeigh - scrollY);                        }                    }                }                break;            case MotionEvent.ACTION_UP:                upY = (int) event.getRawY();                if (Math.abs(upY - downY) < 10) {                    onRopeClick();                    break;                }                if (downY > upY) {                    // 向上滑动                    if (isOpen) {                        if (Math.abs(scrollY) > curtainHeigh / 2) {                            // 向上滑动超过半个屏幕高的时候 开启向上消失动画                            startMoveAnim(this.getScrollY(), (curtainHeigh - this.getScrollY()), upDuration);                            isOpen = false;                        } else {                            startMoveAnim(this.getScrollY(), -this.getScrollY(), upDuration);                            isOpen = true;                        }                    }                } else {                    // 向下滑动                    if (scrollY > curtainHeigh / 2) {                        // 向上滑动超过半个屏幕高的时候 开启向上消失动画                        startMoveAnim(this.getScrollY(), -this.getScrollY(), upDuration);                        isOpen = true;                    } else {                        startMoveAnim(this.getScrollY(), (curtainHeigh - this.getScrollY()), upDuration);                        isOpen = false;                    }                }                break;            default:                break;        }    }    return false;}
    public void onRopeClick() {        if (isOpen) {            CurtainView.this.startMoveAnim(0, curtainHeigh, upDuration);        } else {            CurtainView.this.startMoveAnim(curtainHeigh, -curtainHeigh, downDuration);        }        isOpen = !isOpen;    }
3,.调用startMoveAnim方法实现动画效果 ,内部使用startScroll方法开始滚动,同时调用invalidate方法重绘view,重绘view时,内部调用computeScroll方法来完成整个滚动过程
public void startMoveAnim(int startY, int dy, int duration) {    isMove = true;    mScroller.startScroll(0, startY, 0, dy, duration);    invalidate();//通知UI线程的更新}/** * View重绘时,会一直调用此方法 */@Overridepublic void computeScroll() {    //判断是否还在滚动,还在滚动为true    if (mScroller.computeScrollOffset()) {        scrollTo(mScroller.getCurrX(), mScroller.getCurrY());        //更新界面        postInvalidate();        isMove = true;    } else {        isMove = false;    }    super.computeScroll();}

以上是我要讲解的Demo的主要逻辑,如果不太懂,请下载源码分析。

下载Demo请猛戳

0 0
原创粉丝点击