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

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

自定義View系列的總結

2019-11-09 15:02:23
字體:
來源:轉載
供稿:網友

在自定義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()??词欠裼衎ackground,沒有的話size=minWidth(或minHeight),有的話取兩者中較大的值為size;public static int getDefaultSize(int size, int measureSpec)??芍猻ize=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
日韩欧美在线国产| 精品久久久久久中文字幕大豆网| 欧美日产国产成人免费图片| 在线观看精品国产视频| 久久这里只有精品99| 亚洲第一区第二区| 欧美第一黄色网| 狠狠色香婷婷久久亚洲精品| 精品福利免费观看| 福利视频导航一区| 久久久久久91香蕉国产| 国产欧美va欧美va香蕉在线| www.日韩视频| 欧美激情精品久久久久久黑人| 国产精品一区久久| 有码中文亚洲精品| 色偷偷偷综合中文字幕;dd| 精品亚洲国产视频| 91色视频在线观看| 亚洲免费成人av电影| 黑人巨大精品欧美一区二区| 日韩中文字幕欧美| 国产日韩欧美夫妻视频在线观看| 亚洲已满18点击进入在线看片| 秋霞午夜一区二区| 在线播放日韩欧美| 欧美性高跟鞋xxxxhd| 亚洲国产精品人人爽夜夜爽| 日本国产欧美一区二区三区| 欧美亚洲另类制服自拍| 91在线色戒在线| 最近2019中文字幕在线高清| 欧美激情亚洲一区| 亚洲最大中文字幕| 欧美精品免费看| 欧美视频在线免费看| 亚洲免费伊人电影在线观看av| 国产精品久久久久一区二区| 国产精品久久久久久久久久三级| 国产精品久久久久久久久久小说| 欧美日韩中文字幕| 久久久久国产视频| 亚洲人成人99网站| 亚洲视频电影图片偷拍一区| 国产亚洲欧美日韩一区二区| 午夜精品久久久久久久久久久久| 国产亚洲激情视频在线| 在线看片第一页欧美| 国产精品久久久久久久久久久不卡| 亚洲精品欧美极品| 91经典在线视频| 日韩成人中文字幕在线观看| 国产免费一区视频观看免费| 欧美老肥婆性猛交视频| 久久久综合免费视频| 川上优av一区二区线观看| 欧美国产高跟鞋裸体秀xxxhd| 自拍偷拍亚洲在线| 亚洲综合大片69999| 亚洲成人av在线播放| 午夜精品久久久久久久99热| 亚洲欧洲美洲在线综合| 久久久国产一区| 精品久久中文字幕久久av| 久久亚洲一区二区三区四区五区高| 亚洲男人第一网站| 成人亲热视频网站| 久久成人人人人精品欧| 97超级碰在线看视频免费在线看| 成人精品网站在线观看| 国产日韩在线看片| 日韩av高清不卡| 国产精品∨欧美精品v日韩精品| 九九热99久久久国产盗摄| 在线观看中文字幕亚洲| 亚洲视频第一页| 欧美日韩中文字幕综合视频| 日本精品免费观看| 欧美国产一区二区三区| 中文字幕精品久久久久| 久久最新资源网| 欧美猛交ⅹxxx乱大交视频| 狠狠色狠狠色综合日日小说| 91沈先生在线观看| 亚洲免费影视第一页| 在线视频一区二区| 中文国产亚洲喷潮| 精品自在线视频| 久久免费精品视频| 日韩美女激情视频| 日韩精品在线观| 日本国产欧美一区二区三区| 色偷偷噜噜噜亚洲男人的天堂| 日韩va亚洲va欧洲va国产| xxxx欧美18另类的高清| 美女国内精品自产拍在线播放| 成人精品久久一区二区三区| 国产欧美一区二区白浆黑人| 日产精品99久久久久久| 欧美电影在线播放| 国产人妖伪娘一区91| 久久资源免费视频| 一本一道久久a久久精品逆3p| 九九热这里只有精品6| 国内精品小视频在线观看| 蜜臀久久99精品久久久久久宅男| 成人久久精品视频| 国产69精品久久久久9999| 成人激情视频在线观看| 亚洲欧洲自拍偷拍| 欧美成人小视频| 亚洲精品免费网站| 亚洲肉体裸体xxxx137| 亚洲欧美日韩一区二区在线| 久久久久免费精品国产| 欧美性猛交xxxx富婆| 亚洲欧美日韩中文在线| 亚洲精品国产品国语在线| 欧美亚洲成人xxx| 日韩免费视频在线观看| 欧美成人精品不卡视频在线观看| 91国内免费在线视频| 国产亚洲一区精品| 国产精品扒开腿爽爽爽视频| 91视频88av| 911国产网站尤物在线观看| 欧美国产日韩xxxxx| 国产精品第七十二页| 成人xxxxx| 亚洲国产另类 国产精品国产免费| 日韩电影在线观看永久视频免费网站| 国产一区二区欧美日韩| 日韩在线观看精品| 亚洲电影中文字幕| 亚洲一区二区三区在线免费观看| 欧美精品18videos性欧美| 久久久久久高潮国产精品视| 亚洲国产欧美在线成人app| 欧美成人合集magnet| www.欧美精品一二三区| 日韩av电影在线免费播放| 亚洲欧洲成视频免费观看| 国产成人精品视频在线观看| 日韩亚洲欧美中文高清在线| 色综合色综合久久综合频道88| 久久香蕉精品香蕉| 午夜精品理论片| 亚洲偷熟乱区亚洲香蕉av| 欧美人与性动交a欧美精品| 国产精品色视频| 日韩在线视频一区| 亚洲成**性毛茸茸| 国产一区二区三区中文| 韩国美女主播一区| 91沈先生在线观看| 亚洲综合中文字幕68页| 亚洲女人天堂色在线7777| 日韩在线播放一区| 精品久久久免费| 亚洲精品日韩欧美| 91亚洲国产成人精品性色| 亚洲欧美日韩高清| 欧美日韩另类在线| 欧美日韩一区二区三区在线免费观看|