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請猛戳




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章