欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

android自定義布局中的平滑移動

在android應用程序的開發(fā)過程中,相信我們很多人都想把應用的交互做的比較絢麗,比如讓界面切換平滑的滾動,還有熱度灰常高的偽3D等界面效果,通常情況下,系統(tǒng)提供的應用在特效這方面只能為我們提供簡單的動畫接口,所以要想實現(xiàn)比較酷炫的效果還是要自己去開發(fā)布局控件(即所謂的自定義View、ViewGroup)。小弟也經(jīng)常做一些自定義的控件,最近工作比較清閑,所以便將自己對自定義布局控件的一些心得寫出來,權當是自己的學習筆記了,各位高手看到了可以忽略android自定義布局中的平滑移動

我們提供的服務有:成都網(wǎng)站建設、網(wǎng)站建設、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認證、上虞ssl等。為上千企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務,是有科學管理、有技術的上虞網(wǎng)站制作公司

。下面就我最近工作中遇到的一個自定義控件開發(fā)做一些簡單的介紹,其實那個地方原本可以用ScrollView解決很大一部分問題的,但有一些效果確實需要對控件進行重新定義,在繼承ScrollView開發(fā)中仍然會遇到一些ScrollView自身的限制,所以就仿照ScrollView自己做了一個控件。在其中遇到了一些問題自然就是像ScrollView中拖動的效果(比如快速拖動在手指離開屏幕時控件依舊會由于慣性繼續(xù)滑動一段距離后才會停止運動),所以就對這個東東做了一下仔細的研究,雖然以前也做過類似的開發(fā),這次由于時間比較充裕,所以將開發(fā)中遇到的一些問題都一一記錄了下來。下面開始正題:

自定義布局控件自然是要繼承某個View或ViewGroup

由于是根據(jù)項目的開發(fā)來寫的這篇博客,所以我就以自定義布局控件(ViewGroup)來做介紹了。

開發(fā)一個自定義的ViewGroup自然是要繼承ViewGroup類了,在繼承這個類之后必須要重寫的方法就是

onLayout(boolean changed, int l, int t, int r, int b)

另外至少要有一個構造方法,我個人習慣重寫那個有兩個參數(shù)的構造方法(XXX(Context context, AttributeSet attrs)),因為有了這個構造方法就可以在xml布局文件里使用這個類了。

如果想要對這個布局控件以及其子控件的尺寸進行精確的控制那就要重寫下面這個方法了

onMeasure(int widthMeasureSpec, int heightMeasureSpec)

這個方法從字面理解就是估算控件的尺寸大小了,關于這個方法的詳細說明引用一下另一位童鞋的文章http://www.eoeandroid.com/thread-102385-1-1.html,這里就不詳細介紹了


下面開始介紹關于如何讓自定義的控件進行平滑的移動,并能夠根據(jù)手勢的情況產(chǎn)生慣性滑動的效果

先介紹一下開發(fā)這種滑動效果需要用到的各種工具類:

android.view.VelocityTracker
android.view.Scroller
android.view.ViewConfiguration

VelocityTracker從字面意思理解那就是速度追蹤器了,在滑動效果的開發(fā)中通常都是要使用該類計算出當前手勢的初始速度(不知道我這么理解是否正確,對應的方法是velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity))并通過getXVelocity或getYVelocity方法得到對應的速度值initialVelocity,并將獲得的速度值傳遞給Scroller類的fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY) 方法進行控件滾動時各種位置坐標數(shù)值的計算,API中對fling 方法的解釋是基于一個fling手勢開始滑動動作,滑動的距離將由所獲得的初始速度initialVelocity來決定。關于ViewConfiguration 的使用主要使用了該類的下面三個方法:

configuration.getScaledTouchSlop() //獲得能夠進行手勢滑動的距離
configuration.getScaledMinimumFlingVelocity()//獲得允許執(zhí)行一個fling手勢動作的最小速度值
configuration.getScaledMaximumFlingVelocity()//獲得允許執(zhí)行一個fling手勢動作的最大速度值

需要重寫的方法至少要包含下面幾個方法:

onTouchEvent(MotionEvent event)//有手勢操作必然少不了這個方法了

computeScroll()//必要時由父控件調(diào)用請求或通知其一個子節(jié)點需要更新它的mScrollX和mScrollY的值。典型的例子就是在一個子節(jié)點正在使用Scroller進行滑動動畫時將會被執(zhí)行。所以,從該方法的注釋來看,繼承這個方法的話一般都會有Scroller對象出現(xiàn)。


在往下就是介紹比較具體的開發(fā)思路

首先我們要初始化一些變量,其中的多數(shù)代碼已經(jīng)在上面做出介紹了

Java代碼

  1. void init(Context context) {
                    mScroller = new Scroller(getContext());
                    setFocusable(true);
                    setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
                    setWillNotDraw(false);
                    final ViewConfiguration configuration = ViewConfiguration.get(context);
                    mTouchSlop = configuration.getScaledTouchSlop();
                    mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
                    mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
            }

復制代碼

然后我們申明一個用來處理滑動操作的方法fling(int velocityY),代碼如下:

Java代碼
  1. public void fling(int velocityY) {
            if (getChildCount() > 0) {
                    mScroller.fling(getScrollX(), getScrollY(), 0, velocityY, 0, 0, 0,
                                    maxScrollEdge);
                    final boolean movingDown = velocityY > 0;
                    awakenScrollBars(mScroller.getDuration());
                    invalidate();
            }
    }

復制代碼

在這個方法里只是使用Scroller的fling方法開始執(zhí)行fling手勢動作了,關于其中的各種參數(shù)就不一一解釋了。

awakenScrollBars(int startDelay)方法根據(jù)我對注釋的理解就是在這里給出動畫開始的延時,當參數(shù)startDelay為0時動畫將立刻開始,其實就是一個延遲的作用


下面是對VelocityTracker的初始化以及資源釋放的方法

Java代碼
  1. private void obtainVelocityTracker(MotionEvent event) {
            if (mVelocityTracker == null) {
                    mVelocityTracker = VelocityTracker.obtain();
            }
            mVelocityTracker.addMovement(event);
    }
    private void releaseVelocityTracker() {
            if (mVelocityTracker != null) {
                    mVelocityTracker.recycle();
                    mVelocityTracker = null;
            }
    }

復制代碼

onTouchEvent(MotionEvent event)方法的重寫

Java代碼
  1. public boolean onTouchEvent(MotionEvent event) {

  2.                 if (event.getAction() == MotionEvent.ACTION_DOWN

  3.                                 && event.getEdgeFlags() != 0) {

  4.                         return false;

  5.                 }

  6.                 obtainVelocityTracker(event);

  7.                 final int action = event.getAction();

  8.                 final float x = event.getX();

  9.                 final float y = event.getY();

  10.                 switch (action) {

  11.                 case MotionEvent.ACTION_DOWN:

  12.                         LogUtil.log(TAG, "ACTION_DOWN#currentScrollY:" + getScrollY()

  13.                                         + ", mLastMotionY:" + mLastMotionY,

  14.                                         LogUtil.LOG_E);

  15.                         if (!mScroller.isFinished()) {

  16.                                 mScroller.abortAnimation();

  17.                         }

  18.                         mLastMotionY = y;

  19.                         break;

  20.                 case MotionEvent.ACTION_MOVE:

  21.                         final int deltaY = (int) (mLastMotionY - y);

  22.                         mLastMotionY = y;

  23.                         if (deltaY < 0) {

  24.                                 if (getScrollY() > 0) {

  25.                                         scrollBy(0, deltaY);

  26.                                 } 

  27.                         } else if (deltaY > 0) {

  28.                                 mIsInEdge = getScrollY() <= childTotalHeight - height;

  29.                                 if (mIsInEdge) {

  30.                                         scrollBy(0, deltaY);

  31.                                 }

  32.                         }

  33.                         break;

  34.                 case MotionEvent.ACTION_UP:

  35.                         final VelocityTracker velocityTracker = mVelocityTracker;

  36.                         velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);

  37.                         int initialVelocity = (int) velocityTracker.getYVelocity();

  38.                         if ((Math.abs(initialVelocity) > mMinimumVelocity)

  39.                                         && getChildCount() > 0) {

  40.                                 fling(-initialVelocity);

  41.                         }

  42.                         releaseVelocityTracker();

  43.                         break;

  44.                 }

  45.                 return true;

  46.         }

復制代碼

在onTouchEvent方法中,當手勢執(zhí)行到ACTION_UP時獲得當時手勢的速度值然后判斷這個速度值是否大于可滑動的最小速度,如果符合條件那么就執(zhí)行fling(int velocityY)方法,通過fling方法中的日志發(fā)現(xiàn),在執(zhí)行了invalidate()方法之后,程序便會執(zhí)行computeScroll()方法,在computeScroll()方法中執(zhí)行scrollTo方法主要是因為mScrollX、mScrollY這兩個變量的修飾符為portected,無法在擴展類里面無法對這兩個變量直接進行操作,那么就需要使用scrollTo方法對這兩個變量進行操作,以刷新當前的UI控件,下面附上computeScroll()方法的代碼

Java代碼
  1. public void computeScroll() {

  2.         if (mScroller.computeScrollOffset()) {

  3.                 int scrollX = getScrollX();

  4.                 int scrollY = getScrollY();

  5.                 int oldX = scrollX;

  6.                 int oldY = scrollY;

  7.                 int x = mScroller.getCurrX();

  8.                 int y = mScroller.getCurrY();

  9.                 scrollX = x;

  10.                 scrollY = y;

  11.                 scrollY = scrollY + 10;

  12.                 scrollTo(scrollX, scrollY);

  13.                 postInvalidate();

  14.         }

  15. }

復制代碼

其中的mScroller.computeScrollOffset()是用來判斷動畫是否完成,如果沒有完成返回true繼續(xù)執(zhí)行界面刷新的操作,各種位置信息將被重新計算用以重新繪制最新狀態(tài)的界面。關于scrollTo方法,我們需要看一下該方法的代碼(來自View中):

Java代碼
  1. public void scrollTo(int x, int y) {

  2.         if (mScrollX != x || mScrollY != y) {

  3.             int oldX = mScrollX;

  4.             int oldY = mScrollY;

  5.             mScrollX = x;

  6.             mScrollY = y;

  7.             onScrollChanged(mScrollX, mScrollY, oldX, oldY);

  8.             if (!awakenScrollBars()) {

  9.                 invalidate();

  10.             }

  11.         }

  12.     }

復制代碼

我們可以看到,當傳遞進來的x、y的值與控件當前的mScrollX、mScrollY的值不相同時對界面進行重新計算,根據(jù)日志打印的情況來看似乎awakenScrollBars()返回的總是true, 這樣的話每執(zhí)行一次computeScroll()方法,就需要執(zhí)行一次postInvalidate()方法來刷新界面,而postInvalidate()方法會通過內(nèi)部線程重新調(diào)用invalidate()已達到界面刷新的效果,產(chǎn)生手勢離開屏幕之后的慣性滑動效果。


可能上面說的比較凌亂,在這里總結(jié)一下,大概的思路如下:

首先我們通過VelocityTracker、ViewConfiguration類得到一些慣性滑動所必須的變量,比如手勢離開屏幕時的初始速度,允許進行手勢操作的最小距離以及允許手勢操作的速度邊界值;

第二,創(chuàng)建Scroller的對象,使用它的fling方法供我們控制界面滑動使用;

第三,重寫onTouchEvent方法,當我們用手指在屏幕上來回滑動時此時執(zhí)行的是scrollBy方法來刷新界面,當手指離開屏幕,此時就要開始執(zhí)行ACTION_UP后面的操作了;

通過對手指離開屏幕時的速度進行判斷是否能夠進行慣性滑動操作,

如果能夠執(zhí)行那么就使用Scroller類的fling方法啟動滑動動畫,

這時需要調(diào)用一下invalidate()方法來間接的調(diào)用computeScroll方法,

在computeScroll方法中對Scroller的動畫是否執(zhí)行完成做了判斷,

如果動畫沒有完成(mScroller.computeScrollOffset() == true)那么就使用scrollTo方法對mScrollX、mScrollY的值進行重新計算刷新界面,

調(diào)用postInvalidate()方法重新繪制界面,

postInvalidate()方法會調(diào)用invalidate()方法,

invalidate()方法又會調(diào)用computeScroll方法,

就這樣周而復始的相互調(diào)用,直到mScroller.computeScrollOffset() 返回false才會停止界面的重繪動作


總結(jié),滑動效果來看,它依然是在不停的計算控件的位置刷新屏幕,不停的繪制新的圖片替換舊的圖片,當然每次刷新的速度很快,從而給人一種是在快速滑動的感覺,寫到這里我發(fā)現(xiàn),現(xiàn)在所謂的動畫總是逃脫不了電影的那種模式,每秒播放多少幀的圖片來達到連續(xù)播放的效果欺騙人的眼睛。

而且,關于android一些酷炫效果的開發(fā),還是要自己多動手,熟悉View、ViewGroup中每個繪制方法、位置計算方法的調(diào)用方式以及順序,那么至少是在2D動畫開發(fā)中,也就是一種方式,逃脫不了不停重新繪制的這個圈。

關于熟悉View、ViewGroup中每個繪制方法、位置計算方法的調(diào)用方式以及順序的問題,我建議最好自己寫一個簡單的自定義View或ViewGroup的擴展類,重載那些繪制、位置計算的方法打個日志出來一看自然就明白了,雖然這個方法很笨,但是很容易出效果的

當前題目:android自定義布局中的平滑移動
文章源于:http://chinadenli.net/article22/jsiicc.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供Google、營銷型網(wǎng)站建設、網(wǎng)頁設計公司、網(wǎng)站導航、標簽優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設
中文字幕有码视频熟女| 色丁香一区二区黑人巨大| 国产亚洲神马午夜福利| 国产精品第一香蕉视频| 91精品国产品国语在线不卡| 91欧美一区二区三区成人| 午夜精品一区二区av| 日韩成人午夜福利免费视频| 午夜福利黄片免费观看| 国内九一激情白浆发布| 老司机精品国产在线视频| 欧美人禽色视频免费看| 亚洲熟女熟妇乱色一区| 亚洲深夜精品福利一区| 五月婷婷综合缴情六月| 91超精品碰国产在线观看| 中文字幕精品一区二区年下载| 亚洲欧美日韩国产综合在线 | 欧美日韩精品久久第一页| 开心五月激情综合婷婷色| 亚洲国产成人精品福利| 一二区中文字幕在线观看| 欧美日韩三区在线观看| 欧美日韩免费黄片观看| 美国黑人一级黄色大片| 欧美有码黄片免费在线视频| 欧洲自拍偷拍一区二区| 色哟哟在线免费一区二区三区| 一区二区三区四区亚洲专区| 国产精品一区二区视频| 综合久综合久综合久久| 中文字幕精品一区二区三| 九九热在线视频观看最新| 91麻豆视频国产一区二区| 久久国产成人精品国产成人亚洲| 婷婷一区二区三区四区| 亚洲精品伦理熟女国产一区二区| 国产一级精品色特级色国产| 日韩一区二区免费在线观看| 在线观看视频国产你懂的| 日本人妻熟女一区二区三区|