欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

SlidingDrawer源碼分析 - 新聞資訊 - 云南小程序開(kāi)發(fā)|云南軟件開(kāi)發(fā)|云南網(wǎng)站建設(shè)-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設(shè)/小程序開(kāi)發(fā)/軟件開(kāi)發(fā)

知識(shí)

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價(jià)值,我們?cè)谧非笃湟曈X(jué)表現(xiàn)的同時(shí),更側(cè)重于功能的便捷,營(yíng)銷的便利,運(yùn)營(yíng)的高效,讓網(wǎng)站成為營(yíng)銷工具,讓軟件能切實(shí)提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序?yàn)楹笃谏?jí)提供便捷的支持!

您當(dāng)前位置>首頁(yè) » 新聞資訊 » 技術(shù)分享 >

SlidingDrawer源碼分析

發(fā)表時(shí)間:2020-10-19

發(fā)布人:葵宇科技

瀏覽次數(shù):20

一屬性變量分析


構(gòu)造函數(shù)完成獲取attr屬性內(nèi)容的攫取,攫取用戶設(shè)備的UI屬性,用于構(gòu)造新的UI構(gòu)造。
屬性內(nèi)容為,留意這里的SlidingShow作者本身定義的,拷自源碼包:

<resources>
    <declare-styleable name="SlidingShow">
        <attr name="handle" format="reference" />
        <attr name="content" format="reference" />
        <attr name="orientation"  format="integer" />
        <attr name="bottomOffset" format="dimension" />
        <attr name="topOffset" format="dimension" />
        <attr name="allowSingleTap" format="boolean" />
        <attr name="animateOnClick" format="boolean" />
    </declare-styleable>
</resources>
android:allowSingleTap:指導(dǎo)是否可以經(jīng)由過(guò)程handle打開(kāi)或封閉

android:animateOnClick:指導(dǎo)是否當(dāng)應(yīng)用者按下手柄打開(kāi)/封閉時(shí)是否該有一個(gè)動(dòng)畫。

android:content:隱蔽的內(nèi)容
android:handle:handle(手柄)

二源碼情景分析


在分析源碼前,先要選擇一個(gè)分析次序,次序按照ViewGroup繪制周期來(lái)進(jìn)展。
[img]http://img.blog.csdn.net/20141228174928045

根據(jù)viewGroup的繪制次序開(kāi)端分析源碼。

2.1 測(cè)量函數(shù)


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {(1)
        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);

        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
        final View handle = mHandle;
        measureChild(handle, widthMeasureSpec, heightMeasureSpec);//(2緝獲取child View的大年夜小
        //定義mContent大年夜小
        if (mVertical) {
            int height = heightSpecSize - handle.getMeasuredHeight() - mTopOffset;(3)
            mContent.measure(MeasureSpec.makeMeasureSpec(widthSpecSize, MeasureSpec.EXACTLY),
                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
        } else {
            int width = widthSpecSize - handle.getMeasuredWidth() - mTopOffset;
            mContent.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
                    MeasureSpec.makeMeasureSpec(heightSpecSize, MeasureSpec.EXACTLY));
        }
        setMeasuredDimension(widthSpecSize, heightSpecSize);
    }
(1) widthMeasureSpec和heightMeasureSpec為寬度規(guī)格和高度規(guī)格,可以獲取對(duì)應(yīng)的mode(AT_MOST盡大年夜/  EXACTLY精確/  UNSPECIFIED不限制),可以獲取對(duì)應(yīng)尺寸。
(2) 獲取viewGroup中子視圖的尺寸,這里是獲取handle的View大年夜小。
(3) 根據(jù)對(duì)應(yīng)的偏移量和handle view的大年夜小,設(shè)置Content大年夜小。

2.2 視圖函數(shù)


    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {(1)
        if (mTracking) {
            return;
        }
        final int width = r - l;    //viewGroup的寬度
        final int height = b - t;   //viewGroup的高度
        final View handle = mHandle;

        int childWidth = handle.getMeasuredWidth();     //handle尺寸
        int childHeight = handle.getMeasuredHeight();
        int childLeft;
        int childTop;
        final View content = mContent;
        if (mVertical) {
            childLeft = (width - childWidth) / 2;
            /**
             * 設(shè)定hanlde地位,這里handle與mBottomOffset和本身大年夜小有關(guān)
             * 設(shè)定content地位,這里content與mTopOffset和handle大年夜小有關(guān)
             */
            childTop = mExpanded ? mTopOffset : height - childHeight + mBottomOffset;(2)
            //設(shè)定content的地位
            content.layout(0, mTopOffset + childHeight, content.getMeasuredWidth(),
                    mTopOffset + childHeight + content.getMeasuredHeight());
        } else {
            childLeft = mExpanded ? mTopOffset : width - childWidth + mBottomOffset;
            childTop = (height - childHeight) / 2;

            content.layout(mTopOffset + childWidth, 0,
                    mTopOffset + childWidth + content.getMeasuredWidth(),
                    content.getMeasuredHeight());
        }
        //肯定handle地位
        handle.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);(3)
        mHandleHeight = handle.getHeight();
        mHandleWidth = handle.getWidth();
    }

(1) 參數(shù)changed表示view有新的尺寸或地位;參數(shù)l表示相對(duì)于父view的Left地位;參數(shù)t表示相對(duì)于父view的Top地位;參數(shù)r表示相對(duì)于父view的Right地位;參數(shù)b表示相對(duì)于父view的Bottom地位。
(2) 問(wèn)號(hào)表達(dá)式,根據(jù)前提展開(kāi)或是緊縮決定handle的Top地位。
(3) 肯定handle地位,包含了展開(kāi)和緊縮的剖斷,這里Content地位還不太對(duì),還顯示在expanded(展開(kāi)狀況)。

2.3 繪制圖像函數(shù)

    @Override
    protected void dispatchDraw(Canvas canvas) {    //繪制兩個(gè)子view
        final long drawingTime = getDrawingTime();  //獲取當(dāng)前GPU繪制view時(shí)光,不是日期時(shí)光(1)
        final View handle = mHandle;
        final boolean isVertical = mVertical;

        drawChild(canvas, handle, drawingTime);(1)
        if (mTracking || mAnimating) {      //斷定當(dāng)緇ご態(tài)是否為追蹤或者產(chǎn)活潑畫狀況
            final Bitmap cache = mContent.getDrawingCache();
            if (cache != null) {
                if (isVertical) {
                    canvas.drawBitmap(cache, 0, handle.getBottom(), null);
                } else {
                    canvas.drawBitmap(cache, handle.getRight(), 0, null);
                }
            } else {
                canvas.save();
                canvas.translate(isVertical ? 0 : handle.getLeft() - mTopOffset,
                        isVertical ? handle.getTop() - mTopOffset : 0);(2)
                drawChild(canvas, mContent, drawingTime);
                canvas.restore();   //更改save辦法前所有的繪制修改
            }
        } else if (mExpanded) {
            drawChild(canvas, mContent, drawingTime);(3)
        }
    }

(1)根據(jù)當(dāng)前設(shè)備的canvas繪制handle
(2)更改響應(yīng)的canvas設(shè)備,用戶繪制content
(3)根據(jù)當(dāng)前設(shè)備的canvas繪制content

2.4 完成繪制函數(shù)

    @Override
    protected void onFinishInflate() {
        mHandle = findViewById(mHandleId);
        if (mHandle == null) {
            throw new IllegalArgumentException("The handle attribute is must refer to an"
                    + " existing child.");
        }
        mHandle.setOnClickListener(new DrawerToggler());//設(shè)置單擊監(jiān)聽(tīng)類(1)
        mContent = findViewById(mContentId);
        if (mContent == null) {
            throw new IllegalArgumentException("The content attribute is must refer to an"
                    + " existing child.");
        }
        mContent.setVisibility(View.GONE);
    }

(1)設(shè)置監(jiān)聽(tīng)類,內(nèi)部設(shè)置響應(yīng)的點(diǎn)擊事宜動(dòng)畫。

2.4.1 監(jiān)聽(tīng)類的解析


    private class DrawerToggler implements OnClickListener {
        public void onClick(View v) {
            if (mLocked) {(1)
                return;
            }
            // mAllowSingleTap isn't relevant here; you're *always*
            // allowed to open/close the drawer by clicking with the
            // trackball.
            //android:allowSingleTap:指導(dǎo)是否可以經(jīng)由過(guò)程handle打開(kāi)或封閉
            //android:animateOnClick:指導(dǎo)是否當(dāng)應(yīng)用者按下手柄打開(kāi)/封閉時(shí)是否該有一個(gè)動(dòng)畫。
            if (mAnimateOnClick) {(2)
                animateToggle();(3)
            } else {
                toggle();(4)
            }
        }
    }
(1)斷定是否將view鎖住,不許可點(diǎn)擊。
(2)斷定是否應(yīng)用單擊動(dòng)畫,可以不應(yīng)用,可以應(yīng)用。
(3)animateToggle()辦法,單擊后的動(dòng)畫效不雅
    public void animateToggle() {
        if (!mExpanded) {
            animateOpen();
        } else {
            animateClose();
        }
    }
展開(kāi)和緊縮兩種動(dòng)畫效不雅:
    public void animateOpen() {
        prepareContent();   //預(yù)備content(-1)
        final OnDrawerScrollListener scrollListener = mOnDrawerScrollListener;
        if (scrollListener != null) {
            scrollListener.onScrollStarted();//調(diào)用onScrollStarted函數(shù)
        }
        animateOpen(mVertical ? mHandle.getTop() : mHandle.getLeft());//展開(kāi)動(dòng)畫(-2)
        sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);//設(shè)定當(dāng)前的accessibilityEvent
        
        if (scrollListener != null) {
            scrollListener.onScrollEnded(); //調(diào)用onScrollEnded函數(shù)
        }
    }
(-1)預(yù)備content
    private void prepareContent() {
        if (mAnimating) {
            return;
        }

        // Something changed in the content, we need to honor the layout request
        // before creating the cached bitmap
        final View content = mContent;
        if (content.isLayoutRequested()) {
            if (mVertical) {
                final int childHeight = mHandleHeight;
                int height = getBottom() - getTop() - childHeight - mTopOffset;
                content.measure(MeasureSpec.makeMeasureSpec(getRight() - getLeft(), MeasureSpec.EXACTLY),
                        MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
                content.layout(0, mTopOffset + childHeight, content.getMeasuredWidth(),
                        mTopOffset + childHeight + content.getMeasuredHeight());
            } else {
                final int childWidth = mHandle.getWidth();
                int width = getRight() - getLeft() - childWidth - mTopOffset;
                content.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
                        MeasureSpec.makeMeasureSpec(getBottom() - getTop(), MeasureSpec.EXACTLY));
                content.layout(childWidth + mTopOffset, 0,
                        mTopOffset + childWidth + content.getMeasuredWidth(),
                        content.getMeasuredHeight());
            }
        }
        // Try only once... we should really loop but it's not a big deal
        // if the draw was cancelled, it will only be temporary anyway
        content.getViewTreeObserver().dispatchOnPreDraw();
        if (!content.isHardwareAccelerated()) content.buildDrawingCache();

        content.setVisibility(View.GONE);
//        mContent.setVisibility(View.VISIBLE);
    }
從新繪制content,設(shè)計(jì)響應(yīng)的measure() layout()等辦法。 跟onLayout(boolean changed, int l, int t, int r, int b)辦法中繪制content雷同。
(-2)動(dòng)畫展開(kāi)aimateOpen(boolean)辦法
    private void animateOpen(int position) {
        prepareTracking(position);//預(yù)備路徑
        performFling(position, -mMaximumAcceleration, true);//履行跳動(dòng)
    }

    private void prepareTracking(int position) {
        mTracking = true;//設(shè)置標(biāo)記位
        mVelocityTracker = VelocityTracker.obtain();(--1)
        boolean opening = !mExpanded;
        if (opening) {
            mAnimatedAcceleration = mMaximumAcceleration;   //加快度設(shè)定
            mAnimatedVelocity = mMaximumMajorVelocity;      //最趕緊度設(shè)定
            mAnimationPosition = mBottomOffset +
                    (mVertical ? getHeight() - mHandleHeight : getWidth() - mHandleWidth);
            moveHandle((int) mAnimationPosition);   //移動(dòng)動(dòng)畫(--2)
            mAnimating = true;
            mHandler.removeMessages(MSG_ANIMATE);(--3)
            long now = SystemClock.uptimeMillis();
            mAnimationLastTime = now;   //記錄時(shí)光
            mCurrentAnimationTime = now + ANIMATION_FRAME_DURATION;
            mAnimating = true;
        } else {
            if (mAnimating) {
                mAnimating = false;
                mHandler.removeMessages(MSG_ANIMATE);
            }
            moveHandle(position);(--4)
        }
    }
(--1) 速度追蹤器獲取
(--2) 處理移動(dòng)操作,moveHandle
    private void moveHandle(int position) {
        final View handle = mHandle;

        if (mVertical) {
            if (position == EXPANDED_FULL_OPEN) {//完全展開(kāi)
                handle.offsetTopAndBottom(mTopOffset - handle.getTop());//設(shè)定程度偏移量
                invalidate();
            } else if (position == COLLAPSED_FULL_CLOSED) {//完全封閉
                handle.offsetTopAndBottom(mBottomOffset + getBottom() - getTop() -
                        mHandleHeight - handle.getTop());
                invalidate();
            } else {
                final int top = handle.getTop();//中心狀況
                int deltaY = position - top;
                if (position < mTopOffset) {
                    deltaY = mTopOffset - top;
                } else if (deltaY > mBottomOffset + getBottom() - getTop() - mHandleHeight - top) {
                    deltaY = mBottomOffset + getBottom() - getTop() - mHandleHeight - top;
                }
                handle.offsetTopAndBottom(deltaY);

                final Rect frame = mFrame;
                final Rect region = mInvalidate;

                handle.getHitRect(frame);
                region.set(frame);

                region.union(frame.left, frame.top - deltaY, frame.right, frame.bottom - deltaY);
                region.union(0, frame.bottom - deltaY, getWidth(),
                        frame.bottom - deltaY + mContent.getHeight());

                invalidate(region);
            }
        } else {
            ......
        }
    }
(--3) 移除動(dòng)畫消息
(--4) 移動(dòng)到響應(yīng)地位
2.4.1總結(jié)animateClose();和animateOpen();根本上一樣這里就不在描述了。toggle();更是簡(jiǎn)單了很多,沒(méi)有對(duì)應(yīng)的動(dòng)畫,這里也不再分析。

2.5 滑動(dòng)事宜處理

        前面的介紹中,起首描述若何繪制一個(gè)View,并給出了繪制次序;后來(lái)設(shè)計(jì)了響應(yīng)的點(diǎn)擊事宜處理,并供給了有動(dòng)畫和無(wú)動(dòng)畫兩種情況下的處理函數(shù);那么最后則是處理滑動(dòng)或者多點(diǎn)觸控的事宜。
這里會(huì)用到兩個(gè)辦法,都是viewGroup的辦法,分別是onInterceptTouchEvent()和onTouchEvent()辦法,履行次序遵守下面五點(diǎn):
1. down事宜起首會(huì)傳遞到onInterceptTouchEvent()辦法
2. 如不雅該ViewGroup的onInterceptTouchEvent()在接收到down事宜處理完成之后return false,那么后續(xù)的move, up等事宜將持續(xù)會(huì)先傳遞給該ViewGroup,之后才和down事宜一樣傳遞給最終的目標(biāo)view的onTouchEvent()處理。
3. 如不雅該ViewGroup的onInterceptTouchEvent()在接收到down事宜處理完成之后return true,那么后續(xù)的move, up等事宜將不再傳遞給onInterceptTouchEvent(),而是和down事宜一樣傳遞給該ViewGroup的onTouchEvent()處理,留意,目標(biāo)view將接收不到任何事宜。
4. 如不雅最終須要處理事宜的view的onTouchEvent()返回了false,那么該事宜將被傳遞至其上一層次的view的onTouchEvent()處理。
5. 如不雅最終須要處理事宜的view 的onTouchEvent()返回了true,那么后續(xù)事宜將可以持續(xù)傳遞給該view的onTouchEvent()處理。
    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        if (mLocked) {
            return false;
        }
        final int action = event.getAction();
        float x = event.getX();
        float y = event.getY();

        final Rect frame = mFrame;
        final View handle = mHandle;

        handle.getHitRect(frame);//找到控件占據(jù)的矩形區(qū)域的矩形坐標(biāo)
        if (!mTracking && !frame.contains((int) x, (int) y)) {
            return false;
        }

        if (action == MotionEvent.ACTION_DOWN) {
            mTracking = true;//籌劃路徑中

            handle.setPressed(true);
            // Must be called before prepareTracking()
            prepareContent();

            // Must be called after prepareContent()
            if (mOnDrawerScrollListener != null) {
                mOnDrawerScrollListener.onScrollStarted();
            }

            if (mVertical) {
                final int top = mHandle.getTop();
                mTouchDelta = (int) y - top;
                prepareTracking(top);//設(shè)定當(dāng)前地位
            } else {
                final int left = mHandle.getLeft();
                mTouchDelta = (int) x - left;
                prepareTracking(left);
            }
            mVelocityTracker.addMovement(event);
        }

        return true;//返回true,Event交由onTouchEvent處理
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mLocked) {
            return true;
        }

        if (mTracking) {
            mVelocityTracker.addMovement(event);
            final int action = event.getAction();
            switch (action) {
                case MotionEvent.ACTION_MOVE://移動(dòng)操作
                    moveHandle((int) (mVertical ? event.getY() : event.getX()) - mTouchDelta);
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL: {
                    final VelocityTracker velocityTracker = mVelocityTracker;
                    velocityTracker.computeCurrentVelocity(mVelocityUnits);

                    float yVelocity = velocityTracker.getYVelocity();
                    float xVelocity = velocityTracker.getXVelocity();//計(jì)算路徑的點(diǎn)
                    boolean negative;

                    final boolean vertical = mVertical;
                    if (vertical) {
                        negative = yVelocity < 0;
                        if (xVelocity < 0) {
                            xVelocity = -xVelocity;
                        }
                        if (xVelocity > mMaximumMinorVelocity) {
                            xVelocity = mMaximumMinorVelocity;
                        }
                    } else {
                        negative = xVelocity < 0;
                        if (yVelocity < 0) {
                            yVelocity = -yVelocity;
                        }
                        if (yVelocity > mMaximumMinorVelocity) {
                            yVelocity = mMaximumMinorVelocity;
                        }
                    }

                    float velocity = (float) Math.hypot(xVelocity, yVelocity);// sqrt(x2+ y2).
                    if (negative) {
                        velocity = -velocity;
                    }

                    final int top = mHandle.getTop();
                    final int left = mHandle.getLeft();

                    if (Math.abs(velocity) < mMaximumTapVelocity) {
                        if (vertical ? (mExpanded && top < mTapThreshold + mTopOffset) ||
                                (!mExpanded && top > mBottomOffset + getBottom() - getTop() -
                                        mHandleHeight - mTapThreshold) :
                                (mExpanded && left < mTapThreshold + mTopOffset) ||
                                        (!mExpanded && left > mBottomOffset + getRight() - getLeft() -
                                                mHandleWidth - mTapThreshold)) {

                            if (mAllowSingleTap) {//是否經(jīng)由過(guò)程點(diǎn)擊打開(kāi)
                                playSoundEffect(SoundEffectConstants.CLICK);

                                if (mExpanded) {
                                    animateClose(vertical ? top : left);
                                } else {
                                    animateOpen(vertical ? top : left);
                                }
                            } else {
                                performFling(vertical ? top : left, velocity, false);//履行松開(kāi)手的后面活動(dòng)(1)
                            }

                        } else {
                            performFling(vertical ? top : left, velocity, false);
                        }
                    } else {
                        performFling(vertical ? top : left, velocity, false);
                    }
                }
                break;
            }
        }

        return mTracking || mAnimating || super.onTouchEvent(event);
    }
(1)松開(kāi)手后的處理函數(shù)
private void performFling(int position, float velocity, boolean always) {
        mAnimationPosition = position;
        mAnimatedVelocity = velocity;   //手勢(shì)控制速度

        if (mExpanded) {
            if (always || (velocity > mMaximumMajorVelocity ||
                    (position > mTopOffset + (mVertical ? mHandleHeight : mHandleWidth) &&
                            velocity > -mMaximumMajorVelocity))) {
                // We are expanded, but they didn't move sufficiently to cause
                // us to retract.  Animate back to the expanded position.
                mAnimatedAcceleration = mMaximumAcceleration;
                if (velocity < 0) {
                    mAnimatedVelocity = 0;
                }
            } else {
                // We are expanded and are now going to animate away.
                mAnimatedAcceleration = -mMaximumAcceleration;
                if (velocity > 0) {
                    mAnimatedVelocity = 0;
                }
            }
        } else {
            if (!always && (velocity > mMaximumMajorVelocity ||
                    (position > (mVertical ? getHeight() : getWidth()) / 2 &&
                            velocity > -mMaximumMajorVelocity))) {
                // We are collapsed, and they moved enough to allow us to expand.
                mAnimatedAcceleration = mMaximumAcceleration;
                if (velocity < 0) {
                    mAnimatedVelocity = 0;
                }
            } else {
                // We are collapsed, but they didn't move sufficiently to cause
                // us to retract.  Animate back to the collapsed position.
                mAnimatedAcceleration = -mMaximumAcceleration;
                if (velocity > 0) {
                    mAnimatedVelocity = 0;
                }
            }
        }

        long now = SystemClock.uptimeMillis();
        mAnimationLastTime = now;
        mCurrentAnimationTime = now + ANIMATION_FRAME_DURATION;
        mAnimating = true;
        mHandler.removeMessages(MSG_ANIMATE);
        mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE), mCurrentAnimationTime);
        stopTracking();//停止動(dòng)畫
    }

計(jì)算接下來(lái)活動(dòng)所須要的參量,發(fā)送handler履行后面的動(dòng)畫。
   private void doAnimation() {
        if (mAnimating) {
            incrementAnimation();
            if (mAnimationPosition >= mBottomOffset + (mVertical ? getHeight() : getWidth()) - 1) {
                mAnimating = false;
                closeDrawer();
            } else if (mAnimationPosition < mTopOffset) {
                mAnimating = false;
                openDrawer();
            } else {
                moveHandle((int) mAnimationPosition);
                mCurrentAnimationTime += ANIMATION_FRAME_DURATION;
                mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE),
                        mCurrentAnimationTime);//輪回消息
            }
        }
    }

    private void incrementAnimation() {
        long now = SystemClock.uptimeMillis();
        float t = (now - mAnimationLastTime) / 1000.0f;                   // ms -> s
        final float position = mAnimationPosition;
        final float v = mAnimatedVelocity;                                // px/s
        final float a = mAnimatedAcceleration;                            // px/s/s
        mAnimationPosition = position + (v * t) + (0.5f * a * t * t);     // px
        mAnimatedVelocity = v + (a * t);                                  // px/s
        mAnimationLastTime = now;                                         // ms
    }

    private class SlidingHandler extends Handler {
        public void handleMessage(Message m) {
            switch (m.what) {
                case MSG_ANIMATE:
                    doAnimation();
                    break;
            }
        }
    }

相關(guān)案例查看更多