亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

自定義View系列的總結

2019-11-09 16:17:47
字體:
來源:轉載
供稿:網友

在自定義View系列中以上9篇都是”谷歌的小弟”的原創博文,在這個系列教程中對大部分知識點都做了詳細的闡述。在我通讀了以上文章后受益匪淺啊,原理明白了就算不強記以后很容易能想得到但是一些用法之類的查找確實麻煩,所以再來一篇總結,結合自己的理解和應用加深理解且以后回憶起來也提供一條思路。順序就按照小弟的來。

常用的工具類

Configuration.class:設備信息類,用來描述設備的配置信息,比如用戶的配置信息,設備的相關信息(輸入模式、屏幕方向)。//獲取對象Configuration configuration = getResources().getConfiguration();//用戶LocaleLocale locale = configuration.locale;//信號的國家碼int mcc = configuration.mcc;//信號的網絡碼int mnc = configuration.mnc;//橫豎屏int screen = configuration.orientation;ViewConfiguration.class:它提供了自定義View可能用到的一些標準常量,比如尺寸大小、靈敏度。舉個例子,獲取距離至少為多大系統才會認為是滑動而不是點擊。它提供了一系列的方法供我們查詢這些標準常量,既然是常量便是不可修改的。//獲取對象ViewConfiguration viewConfiguration = ViewConfiguration.get(mContext);//對象方法-系統識別滑動的最小距離int touchSlop = viewConfiguration.getScaledTouchSlop();//對象方法-是否有物理按鍵boolean flag = viewConfiguration.haspermanentMenuKey();//靜態方法-雙擊間隔時間,在時間內判定為雙擊,超出為兩次單擊int doubleTimeout = ViewConfiguration.getDoubleTapTimeout();//靜態方法-按住變成長按動作需要的時間int longPRessTimeout = ViewConfiguration.getLongPressTimeout();GestureDetector.class:這個類是用來簡化Touch處理,可以實現一些常用的操作,比如拖動,滑動等。通過設置GestureDetector.OnGestureListener來監聽手勢,我們通過實現接口代碼處理相應手勢動作下的邏輯。/** * step1:實現GestureDetector.OnGestureListener */ //觸摸屏幕時均會調用該方法 boolean onDown(MotionEvent e);//手指在屏幕上拖動時會調用該方法 boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);//手指長按屏幕時均會調用該方法public void onLongPress(MotionEvent e);//手指在屏幕上滾動時會調用該方法public boolean onScroll(MotionEvent e1,MotionEvent e2, float distanceX,float distanceY);//手指在屏幕上按下,且未移動和松開時調用該方法public void onShowPress(MotionEvent e);//輕擊屏幕時調用該方法public boolean onSingleTapUp(MotionEvent e);/** * step2:生成GestureDetector對象 */ GestureDetector gestureDetector = new GestureDetector(context,newGestureListenerImpl());/** * step3:將View的onTouch時間交由GestureDetector處理 */ @Override public boolean onTouchEvent(MotionEvent event) { return mGestureDetector.onTouchEvent(event); } VelocityTracker.class:速度追蹤器。用于跟蹤觸摸屏事件的速率。private void startVelocityTracker(MotionEvent event) { /** * step1-開始追蹤,追蹤誰? */ VelocityTracker velocityTracker = VelocityTracker.obtain(); velocityTracker.addMovement(event); /** * step2-追蹤處理,獲取具體的數值 */ //設置VelocityTracker單位.1000表示1秒時間內運動的像素 velocityTracker.computeCurrentVelocity(1000); //獲取在1秒內X方向所滑動像素值 int xVelocity = (int) velocityTracker.getXVelocity(); //獲取追蹤到的速度 int velocity_x = Math.abs(xVelocity); /** * step3-釋放 */ if (velocityTracker != null) { velocityTracker.recycle(); velocityTracker = null; }}

Scroller.class:下節總結。

ViewDragHelper.class:處理拖拽動作的類。

mViewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {});

創建實例,三個參數基本就是這三個。對應的內部方法。

/** * 唯一的抽象接口 * 1. 返回true表示可以捕獲這個View的動作 * 2. 我們可以通過它的參數來判斷哪些 */public abstract boolean tryCaptureView(View child, int pointerId);/** * 處理水平方向的越界 * 1. 返回值是我們最終拖拽的距離 * 2. 參數left是手勢拖拽的距離 * 3. 判定X是否越界, * 最小位移min: paddingLeft * 最大位移max:parent.width-paddingRight-childView.width * a. left<min return min; * b. left>max return max; * c. else return left; */public int clampViewPositionHorizontal(View child, int left, int dx);/** * 處理垂直方向的越界(參照水平方向) */ public int clampViewPositionVertical(View child, int top, int dy);/** * 捕獲子View動作 */ public void onViewCaptured(View capturedChild, int activePointerId);/** * 釋放子View動作 */ public void onViewReleased(View releasedChild, float xvel, float yvel);

提供一個圖給大家腦補…

這里寫圖片描述

/*** ViewGroup的事件分發交給ViewDragHelper處理*/@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) { return mDragHelper.shouldInterceptTouchEvent(ev);}/*** ViewGroup的事件消費交給ViewDragHelper處理*/@Overridepublic boolean onTouchEvent(MotionEvent event) { mDragHelper.processTouchEvent(event); return true;}

onMeasure()測量過程

MeasureSpec.class

封裝了parentView對childView布局的要求;32位,高2位是mode,低30位是size;EXACTLY,精確模式,已知大小AT_MOST,未檢測出大小,但最大不超過其sizeUNSPECIFIED,不做考慮

View的測量過程,我們通過源碼可以知道,View的大小不僅僅它本身的布局有關,還和parentView的MeasureSpec相關,view的size由parentView的MeasureSpec.mode和其本身的布局共同決定,對源碼的分析可以得出以下結論。

① 當View的寬高為具體值value時,不管其parentView的MeasureSpec.mode。 size = value; mode = EXACTLY;② 當View的寬高布局為match_parent,parentView.mode為EXACTLY。 size = parentLeftSize; mode = EXACTLY;③ 當View的寬高布局為match_parent,parentView.mode為AT_MOST。 size = parentLeftSize; mode = AT_MOST;

④ 當View的寬高布局為wrap_content,不管其parentView的MeasureSpec.mode。 size = parentLeftSize; mode = AT_MOST; 這里寫圖片描述

parentLeftSiz表示parentView剩下的空間;

onMeasure()分析 在了解了MeasureSpec后,我們具體分析View如何獲取大小的。

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension( getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); }protected int getSuggestedMinimumWidth()。看是否有background,沒有的話size=minWidth(或minHeight),有的話取兩者中較大的值為size;public static int getDefaultSize(int size, int measureSpec)。可知size=MeasureSpec.getSize(measureSpec);就是說onMeasure()過程中View的size是由ViewGroup()繪制 protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed);的時候設置的size決定的,也就是這個圖。

這里寫圖片描述

我們看到情況④,當childView的布局為wrap_content時,childView的size一直都是parentLeftSize,即父控件剩余空間,也可以說是match_parent,就是填滿空間了…,所以我們在自定義View時如果不對這種情況進行處理的話就會造成我們的自定義View布局為wrap_content時,實際效果是match_parent;為什么TextView等等控件在上述情況表現正常呢,這是因為在源碼中已經對上述情況作了處理。那么我們應該如何處理?@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = 100; int height = 200; int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); if( widthMode==MeasureSpec.AT_MOST && heightMode==MeasureSpec.AT_MOST ) setMeasuredDimension(width, height); else if (widthMode==MeasureSpec.AT_MOST) setMeasuredDimension(width, heightSize); else if ( heightMode==MeasureSpec.AT_MOST ) setMeasuredDimension(widthSize, height);}我們在重寫onMeasure()方法時,利用判斷childView.mode來甄別布局是否為wrap_content。當mode為AT_MOST時我們就認為是wrap_content。但是我們查看圖表可知,情況③也是AT_MOST模式,但是它的屬性是match_parent,Why?其實我們通過反證法,可以得出結論此種情況是不存在(不合理)的,所以正常情況不會出現,所以可以忽略。

onLayout()擺放過程

View經過onMeasure()階段之后,會進入到onLayout()確定View的位置過程。先要確定View應該放在哪里我們需要理清思路。 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {};方法該方法在源碼中為空,且源碼給出的注釋說明,我們調用該方法去確定子View的位置,也就是說子View的位置是由其父View中的onLayout()方法確定的,通過查看父View的onLayout()源碼,我們知道該方法為抽象方法,即繼承ViewGroup的View(如LinearLayout等)需要按照自己的規則去實現onLayout()方法。所以自定義ViewGroup時,我們在onLayout()方法中我們根據parentView的參數等去計算所有chiilView的位置,并且在得到具體位置的值時調用childView的layout()確定位置(即第一步)。

有兩個方法有必要討論一下,getMeasuredWidth()和getWidth()方法。它們有何區別。

getMeasuredWidth()方法查看源碼,return mMeasuredWidth變量,查找源碼可以看出此變量在 private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight)方法中給賦值的,在網上查發現,’setMeasuredDimension()’方法調用了setMeasuredDimensionRaw(),而onMeasure()調用了setMeasuredDimension()。getWidth()方法查看源碼發現,返回值是”mRight - mLeft”,且它在onLayout()過程后才有的值。那么,getMeasuredWidth()方法的值是在onMeasure()測量過程后獲取的大小。并且它的值和我們在setMeasuredDimension()設置的值相關。那么,getWidth()方法的值是在onLayout()擺放過程之后獲取的大小,并且它的值是坐標相減的結果。

總結完onDraw()之后,會有例子體現。

onDraw()繪畫過程

繪制的過程從以下幾個方面來簡述。

源碼draw(canvas)繪制過程 - 從源碼注釋可看出View的繪制大體上分為6步。 - 1. 繪制背景drawBackground(canvas); - 2. 保存當前畫布的堆棧狀態并在該畫布上創建Layer用于繪制View在滑動時的邊框漸變效果(可忽略); - 3. 繪制View的內容,protected void onDraw(Canvas canvas) {};我們需要實現的方法: - 4. 畫子View,dispatchDraw(canvas); - 5. 繪制當前視圖在滑動時的邊框漸變效果(可忽略); - 6. 繪制View的滾動條;

Canvas、Bitmap、Paint的關系 - 源碼中看出我們繪制View時重寫onDraw()方法,而方法中只有參數Canvas,查看官方文檔可以得到繪制4要素 - 1. 用什么工具畫? Paint類 。 - 2. 把畫畫在哪里?Bitmap上,Bitmap承載和呈現了畫的各種圖形。 - 3. 畫的內容?根據自己的需求畫圓,畫直線,畫路徑。 - 4. 怎么畫? canvas各種操作。

Canvas類的常用操作 - canvas.translate(x, y); 移動坐標系 - canvas.rotate(angle); 旋轉坐標系 - canvas.clipXxx(); 裁剪某個形狀,就是把坐標系放入到裁剪區域 - canvas.save()生成一個透明的圖層Layer; - canvas.restore()Layer操作的東西覆蓋到原來的圖形上;

PorterDuffXfermode圖形合成的規則 -

Bitmap和Matrix矩陣處理圖像 -

Shader渲染圖像 -

PathEffect畫路徑時樣式效果 -


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
中文字幕日韩欧美在线视频| 久久久久久久久久久亚洲| 久久激情五月丁香伊人| 亚洲xxx大片| 中文字幕国产精品久久| 精品日本美女福利在线观看| 亚洲午夜未满十八勿入免费观看全集| www.色综合| 视频直播国产精品| 国产aⅴ夜夜欢一区二区三区| 国产精品日韩在线| www.美女亚洲精品| 国产成人精品视| 亚洲人成网站777色婷婷| 丝袜情趣国产精品| 国产精品色悠悠| 综合欧美国产视频二区| 欧美激情免费在线| 亚洲国产中文字幕久久网| 国产精品流白浆视频| 2019中文字幕全在线观看| 亚洲成人网久久久| 亚洲精品福利在线观看| 午夜剧场成人观在线视频免费观看| 亚洲自拍小视频| 色青青草原桃花久久综合| 久久中国妇女中文字幕| 精品免费在线观看| 亚洲va久久久噜噜噜| 欧美成人黄色小视频| 精品在线欧美视频| 日韩在线观看免费av| 亚洲最新av网址| 成人美女av在线直播| 精品美女久久久久久免费| 亚洲免费伊人电影在线观看av| 久久精品国产久精国产思思| 中文字幕亚洲激情| 亚洲欧洲国产伦综合| 一区二区三区四区在线观看视频| 91免费版网站入口| 国产精品久久久久久久久久东京| 热99精品里视频精品| 社区色欧美激情 | 国产九九精品视频| 国产91精品网站| 亚洲电影免费观看| 777777777亚洲妇女| 91夜夜揉人人捏人人添红杏| 亚洲xxxxx性| 91久热免费在线视频| 在线看欧美日韩| 亚洲第一av在线| 亚洲美女在线看| 亚洲国产小视频| 欧美激情网友自拍| 亚洲欧洲av一区二区| 亚洲人免费视频| 最新日韩中文字幕| 欧美色另类天堂2015| 国产成人啪精品视频免费网| 日本精品一区二区三区在线| 欧美日本黄视频| 91国语精品自产拍在线观看性色| 一个人www欧美| 欧美精品www在线观看| 日韩最新中文字幕电影免费看| 在线观看精品国产视频| 国产在线精品一区免费香蕉| 欧美日韩激情美女| 亚洲成人精品久久| 日本久久久久久久久久久| 日韩av最新在线观看| 欧美孕妇毛茸茸xxxx| 日韩精品福利网站| 97免费中文视频在线观看| 国产精品美乳在线观看| 欧美疯狂xxxx大交乱88av| 欧美专区在线视频| 亚洲第一av在线| 俺也去精品视频在线观看| 亚洲午夜久久久影院| 久久久久久亚洲精品中文字幕| 精品久久久久久亚洲国产300| 亚洲aⅴ日韩av电影在线观看| 亚洲一区av在线播放| 九色精品美女在线| 97人人模人人爽人人喊中文字| 国产精品欧美日韩一区二区| 欧美精品在线视频观看| 欧美激情亚洲另类| 亚洲国产高潮在线观看| 成人精品福利视频| 98精品国产自产在线观看| 亚洲欧美日韩国产中文专区| 久久国产精品久久久| 国产主播喷水一区二区| 亚洲第一天堂av| 欧美一区三区三区高中清蜜桃| 综合网中文字幕| 国产成人97精品免费看片| 在线一区二区日韩| 国产精品综合不卡av| 亚洲视频axxx| 国产又爽又黄的激情精品视频| 日本成人在线视频网址| 国产精品27p| 欧美老女人xx| 日韩va亚洲va欧洲va国产| 亚洲综合自拍一区| 在线观看日韩av| 欧美另类极品videosbestfree| 亚洲精品视频久久| 一本色道久久综合狠狠躁篇怎么玩| 91久热免费在线视频| 欧美电影第一页| 中文字幕久精品免费视频| 久久久国产视频91| 日韩美女视频在线观看| 国产精品视频大全| 欧美大片网站在线观看| 色999日韩欧美国产| 97在线视频免费| 亚洲欧洲在线观看| 人人澡人人澡人人看欧美| 亚洲已满18点击进入在线看片| 中文字幕9999| 亚洲xxxx做受欧美| 欧美电影在线播放| 4444欧美成人kkkk| 成人性生交大片免费观看嘿嘿视频| 色综合色综合久久综合频道88| 亚洲激情电影中文字幕| 日韩女优人人人人射在线视频| 日韩精品免费一线在线观看| 精品久久久久久久久久久久久| 国产精品盗摄久久久| 欧美另类99xxxxx| 日韩小视频在线| 日韩中文字幕网站| 亚洲天堂免费视频| 91影院在线免费观看视频| 精品国内亚洲在观看18黄| 欧美激情亚洲国产| 亚洲性夜色噜噜噜7777| 92裸体在线视频网站| 日韩av黄色在线观看| 亚洲精品www久久久久久广东| 亚洲毛片在线看| 精品视频在线观看日韩| 欧美理论在线观看| 色综合天天狠天天透天天伊人| 日韩美女视频免费在线观看| 亚洲美女福利视频网站| 亚洲free性xxxx护士hd| 精品毛片三在线观看| 欧美亚洲成人精品| 亚洲第一视频在线观看| 91丝袜美腿美女视频网站| 欧美日韩国产激情| 久久久久久久久久国产精品| 欧美成人精品h版在线观看| 日韩av一区在线| 亚洲jizzjizz日本少妇|