Android Scroller实战(一)登陆弹出框

今天讲解一下Scroller的实战应用,此案例是在我的上一篇文章的基础上进行开发的,如果你感觉看着有点难理解,请先阅读Android Scroller入门(二),此案例并非原创,只是在别人写好的基础上进行改编而来的,下面给出一张图看一下直观的效果。


下面我讲解一下主要的地方,你可以下载我提供的Demo,然后对比着学习。

1. 因为登陆布局利用RelativeLayout做的,那么我们要自定义一个布局LoginView extends RelativieLayout,当然我们需要重写构造函数,生成布局然后利用scrollTo方法将它滚动到底部(隐藏)

public LoginView(Context context) {
        this(context,null);
    }

    public LoginView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public LoginView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    private void init(Context context) {
        /**
         * 这个函数是在ViewGroup里定义的,主要用于控制child View获取焦点的能力,比如是否阻止child View获取焦点。
         * 他有三个常量可供设置
         *
         *  FOCUS_BEFORE_DESCENDANTS ViewGroup本身先对焦点进行处理,如果没有处理则分发给child View进行处理
         *	FOCUS_AFTER_DESCENDANTS 先分发给Child View进行处理,如果所有的Child View都没有处理,则自己再处理
         *	FOCUS_BLOCK_DESCENDANTS ViewGroup本身进行处理,不管是否处理成功,都不会分发给ChildView进行处理
         */
        setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
        setFocusable(true);
        mScroller = new Scroller(context);
        mScreenHeigh = Utils.getWindowHeigh(context);
        mScreenWidth = Utils.getWindowWidth(context);
        final View view = LayoutInflater.from(context).inflate(R.layout.view_login, null);
        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);// 如果不给他设这个,它的布局的MATCH_PARENT就不知道该是多少
        addView(view, params);
        // 背景设置成透明
        setBackgroundColor(Color.argb(0, 0, 0, 0));
        view.post(new Runnable() {

            @Override
            public void run() {
                viewHeight = view.getHeight();
            }
        });
        //滚动到底部不可见
        LoginView.this.scrollTo(0, -mScreenHeigh);
        ImageView btn_close = (ImageView) view.findViewById(R.id.btn_close);
        btn_close.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                dismiss();
            }
        });
    }
2. 处理手指的触摸事件,我们要重写onTouchEvent方法

@Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downY = (int) event.getY();
                Log.d(TAG, "downY = " + downY);
                //如果完全显示的时候,让布局得到触摸监听,如果不显示,触摸事件不拦截,向下传递
                if (isShow) {
                    return true;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                moveY = (int) event.getY();
                scrollY = moveY - downY;
                //向下滑动
                if (scrollY > 0) {
                    if (isShow) {
                        scrollTo(0, -Math.abs(scrollY));
                    }
                } else {
                    if (mScreenHeigh - this.getTop() <= viewHeight && !isShow) {
                        scrollTo(0, Math.abs(viewHeight - scrollY));
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                upY = (int) event.getY();
                if (isShow) {
                    if (this.getScrollY() <= -(viewHeight / 2)) {
                        startMoveAnim(this.getScrollY(), -(viewHeight - this.getScrollY()), mDuration);
                        isShow = false;
                        Log.d("isShow", "false");
                    } else {
                        startMoveAnim(this.getScrollY(), -this.getScrollY(), mDuration);
                        isShow = true;
                        Log.d("isShow", "true");
                    }
                }
                Log.d("this.getScrollY()", "" + this.getScrollY());
                changed();
                break;
            case MotionEvent.ACTION_OUTSIDE:
                Log.d(TAG, "ACTION_OUTSIDE");
                break;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }
3.执行startMoveAnim方法滚动到指定位置

    /**
     * 拖动动画
     * @param startY
     * @param dy  移动到某点的Y坐标距离
     * @param duration 时间
     */
    public void startMoveAnim(int startY, int dy, int duration) {
        isMoving = true;
        mScroller.startScroll(0, startY, 0, dy, duration);
        invalidate();//通知UI线程的更新
    }
4.一旦执行startMoveAnim方法就会执行到invalidate导致view重绘,调用到computerScroll方法,完成整个滚动效果

  @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            // 更新界面
            postInvalidate();
            isMoving = true;
        } else {
            isMoving = false;
        }
        super.computeScroll();
    }
5.最后要对我提供一个接口,来控制视图的显示和隐藏

   /** 监听接口*/
    public onStatusListener statusListener;

    /**
     * 监听接口,来在主界面监听界面变化状态
     */
    public interface onStatusListener {
        /**  开打状态  */
        public void onShow();

        /**  关闭状态  */
        public void onDismiss();
    }
下载Demo请猛戳




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值