當前位置:首頁 » 安卓系統 » androidview重繪

androidview重繪

發布時間: 2022-10-25 19:13:39

㈠ View繪制流程(一)

最近在學習 View 的繪制流程,看了幾篇不錯的博客( ViewRootImpl的獨白,我不是一個View(布局篇) 、 Android應用層View繪制流程與源碼分析 )自己對照源碼,梳理了一遍。

在Activity的onResume之後,當前Activity的Window對象中的View會被添加在WindowManager中。

整個View樹的繪圖流程是在 ViewRootImpl 類的 performTraversals() 方法(這個方法巨長)開始的,該方法做的執行過程主要是根據之前設置的狀態,判斷是否重新計算視圖大小 (measure) 、是否重新放置視圖的位置 (layout) 、以及是否重繪 (draw) ,其核心也就是通過判斷來選擇順序執行這三個方法。

ViewRootImpl 調用 performMeasure 執行Window對應的View的測量。

int widthMeasureSpec :他由兩部分組成, 高2位表示MODE ,定義在MeasureSpec類(View的內部類)中,有三種類型, MeasureSpec.EXACTLY 表示確定大小, MeasureSpec.AT_MOST 表示最大大小, MeasureSpec.UNSPECIFIED 不確定。 低30位表示size ,也就是父View的大小。對於系統Window類的DecorVIew對象Mode一般都為MeasureSpec.EXACTLY ,而size分別對應屏幕寬高。對於子View來說大小是由父View和子View共同決定的。

默認的尺寸大小即傳入的參數都是通過 getDefaultSize 返回的,我們就看一下該方法的實現。

到此一次最基礎的元素View的 measure 過程就完成了。

View實際是嵌套的,而且measure是遞歸傳遞的,所以每個View都需要 measure ,能夠嵌套的View都是ViewGroup的子類,所以在ViewGroup中定義了 measureChildren , measureChild , measureChildWithMargins 方法來對子視圖進行測量, measureChildren 內部實質只是循環調用 measureChild , measureChild 和 measureChildWithMargins 的區別就是是否把 margin padding 也作為子視圖的大小。 ViewGroup 本身不調用 measureChildWithMargins 和 measureChildren 方法,由繼承類通過for循環調用此方法進行子View的測量。下面看一下ViewGroup中稍微復雜的 measureChildWithMargins 方法。

getChildMeasureSpec 的邏輯是通過其父View提供的 MeasureSpec 參數得到 specMode 和 specSize ,然後根據計算出來的 specMode 以及子View的 childDimension (layout_width或layout_height)來計算自身的 measureSpec ,如果其本身包含子視圖,則計算出來的 measureSpec 將作為調用其子視圖 measure 函數的參數,同時也作為自身調用 setMeasuredDimension 的參數,如果其不包含子視圖則默認情況下最終會調用 onMeasure 的默認實現,並最終調用到 setMeasuredDimension 。

Activity 的 onResume 之後,當前 Activity Window 對象中的View(DecorView)會被添加在 WindowManager 中。也就是在 ActivityThread 的 handleResumeActivity 方法中調用 wm.addView(decor, l); 將DecorView添加到 WindowManager 中;

WindowManager 繼承 ViewManager ,它的實現類為 WindowManagerImpl ,該類中的方法的具體實現是由其代理類 WindowManagerGlobal 實現的;

在它的 addView 方法中會創建 ViewRootImpl 的實例,然後將Window對應的View(DecorView),ViewRootImpl,LayoutParams順序添加在WindowManager中,最後將Window所對應的View設置給創建的ViewRootImpl,通過 ViewRootImpl 來更新界面並完成Window的添加過程;

設置view調用的是 ViewRootImpl 的 setView 方法,在該方法中調用 requestLayout(); 方法來非同步執行view的繪制方法;之後將 Window 添加到屏幕,通過 WMS (跨進程通信)

在 requestLayout 方法中最終會調用 ViewRootImpl 的 performTraversals(); 方法,該方法做的執行過程主要是根據之前設置的狀態,判斷是否重新計算視圖大小 (measure) 、是否重新放置視圖的位置 (layout) 、以及是否重繪 (draw) ,其核心也就是通過判斷來選擇順序執行這三個方法: performMeasure 、 performLayout 、 performDraw ;

在 performMeasure 方法中調用的是 View 的 measure 方法,該方法是 final 修飾,不能被子類重寫,在該方法中實際調用的是 View 的 onMeasure 方法,子類可以重寫 onMeasure 方法來實現自己的測量規則。

View 默認的 onMeasure 方法很簡單只是調用了 setMeasuredDimension 方法,該方法的作用是給 View 的成員變數 mMeasuredWidth mMeasuredHeight 賦值,View的測量主要就是給這兩個變數賦值,這兩個變數一旦賦值,也就意味著測量過程的結束。

setMeasuredDimension 方法傳入的尺寸是通過 getDefaultSize(int size, int measureSpec); 方法返回的,在
getDefaultSize 方法中解析 measureSpec Mode Size ,如果Mode為 MeasureSpec.AT_MOST 或者 MeasureSpec.EXACTLY ,最終的size的值為解析後的size;如果 Mode MeasureSpec.UNSPECIFIED ,最終的size為建議的最小值= getSuggestedMinimumWidth ,該方法的具體實現為 return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth()); ,建議的最小寬度和高度都是由View的Background尺寸與通過設置View的 miniXXX 屬性共同決定的

measureSpec 是由 getRootMeasureSpec 方法決定的: measureSpec = View.MeasureSpec.makeMeasureSpec(windowSize, View.MeasureSpec.EXACTLY); 根布局的大小是 Window 的大小,Window大小是不能改變的,總是全屏的。

View實際是嵌套的,而且measure是遞歸傳遞的,所以每個View都需要measure,能夠嵌套的View都是ViewGroup的子類,所以在ViewGroup中定義了 measureChildren , measureChild , measureChildWithMargins 方法來對子視圖進行測量, measureChildren 內部實質只是循環調用 measureChild , measureChild 和 measureChildWithMargins 的區別就是是否把 margin padding 也作為子視圖的大小。

measureChildWithMargins 方法的作用就是對 父View 提供的 measureSpec 參數結合 子View LayoutParams 參數進行了調整,然後再來調用 child.measure() 方法,具體通過方法 getChildMeasureSpec 方法來進行參數調整。計算出來自身的 measureSpec 作為調用其子視圖 measure 方法的參數,同時也作為自身調用 setMeasuredDimension 的參數,如果其不包含子視圖則默認情況下最終會調用 onMeasure 的默認實現,並最終調用到 setMeasuredDimension 。

最終決定 View measure 大小是 View 的 setMeasuredDimension 方法,該方法就是設置mMeasuredWidth和mMeasuredHeight的大小,ViewGroup在 onMeasure 方法調用 setMeasuredDimension 之前調整了 measureSpec

㈡ android 為什麼禁用硬體加速 滑動屏幕會控制項會重繪

你好;可能是你用的加速軟體不夠完善, 建議你使用騰訊手機管家給手機加速,打開騰訊手機管家,進行體檢加速; 也可以健康優化給手機加速, 另外垃圾清理,垃圾掃描;也可以給手機加速; 而且它全新視覺界面,創新操作體驗.;一鍵優化,輕松管理你的手機 讓你享受一站式手機服務;簡訊、通訊錄、應用等都可以快速添加、刪除。

㈢ android 自定義View 怎麼重繪

修改顏色後調用invalidate()
在自定義View 中提供一個方法
public void setRectColor(int color){
colors[x][x] = color; //修改顏色

invalidate();
}

㈣ android自定義 view組件重繪問題

new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
public void run() {
onDraw(null);
invalidate();
}

});
}
}).start();
新線程實現了runnable介面但是 裡面的 第一個 run 方法只執行一次就退出了。應該加入循環不斷更新。而hander.post 里的那個runnable 外層每循環一次就post一次 所以不用加入循環語句。

boolean flag=true;
new Thread(new runnable{
public void run(){
try{
while(flag){
Thread.sleep(1);
handler.post(new Runnable() {
public void run() {
onDraw(null);
invalidate();
}
});
}catch (InterruptedException e) {
e.printStackTrace();
flag=flase;
}
}
}).start();

㈤ Android 如何判斷一個View重繪或載入完成

1、view重繪時回調(即監聽函數,當view重繪完成自動動用,需要向view的觀察者添加監聽器)。格式:

view.getViewTreeObserver().addOnDrawListener(new OnDrawListener() {

@Override

public void onDraw() {

// TODO Auto-generated method stub

}

});

2、view載入完成時回調(當view載入完成自動動用,需要向view的觀察者添加監聽器)。格式:

view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

@Override

public void onGlobalLayout() {

// TODO Auto-generated method stub

}

});

(5)androidview重繪擴展閱讀:

兩種方式刷新:

1、主線程可以直接調用Invalidate()方法刷新

2、子線程可以直接調用postInvalidate()方法刷新。

API的描述 : Invalidatethe whole view. If the view is visible, onDraw(Canvas) will be called at somepoint in the future. This must be called from a UI thread. To call from anon-UI thread, call postInvalidate().。

API的描述譯文:當Invalidate()被調用的時候,View的OnDraw()就會被調用,Invalidate()必須是在UI線程中被調用,如果在新線程中更新視圖的就調用postInvalidate()。

㈥ android 自定義View 怎麼重繪

修改顏色後調用invalidate()
在自定義View 中提供一個方法
public void setRectColor(int color){
colors[x][x] = color; //修改顏色

invalidate();
}

㈦ android怎麼動態調用View.ondraw實現動態繪制自定義View

在自定義的時候,復寫該方法,在代碼中繪制控制項時,會自動調用該方法,在修改了控制項,需要重新繪制時,則使用View的invalidate()即可實現重繪!!!

㈧ android canvas view重繪 我在一個activity中調用了canvas。在canvas中我點擊事件需要重新繪制當前view

除了SurfaceView,其它的都必須通過調用View.invalidate方法刷新View
所以不能直接執行moren(canvas),需要在onTouchEvent調用invalidate

㈨ 如何讓fragment的view重繪

可以在fragment中調用父Activity的recreate()方法重繪父Activity,這樣fragment也會被重繪。

代碼如下:

java">getActivity().recreate();
熱點內容
紫光存儲最近 發布:2025-02-01 04:58:49 瀏覽:380
sqlserver重命名 發布:2025-02-01 04:56:24 瀏覽:428
iisftp被動模式 發布:2025-02-01 04:41:50 瀏覽:350
車載安卓怎麼安裝軟體 發布:2025-02-01 04:30:50 瀏覽:469
安卓系統su程序是什麼 發布:2025-02-01 04:25:42 瀏覽:475
android代碼行數統計 發布:2025-02-01 04:20:47 瀏覽:216
快速喊話腳本 發布:2025-02-01 04:16:48 瀏覽:885
如何分辨普拉多的配置 發布:2025-02-01 04:11:45 瀏覽:681
linuxc文件刪除 發布:2025-02-01 04:11:33 瀏覽:218
c語言稀疏矩陣轉置矩陣 發布:2025-02-01 03:47:57 瀏覽:531