Android 面試總結之佈局常見問題
1、Android 中常用的佈局都有哪些?
FrameLayout
RelativeLayout
LinearLayout
AbsoluteLayout
TableLayout
GrideLayout(Android 4.0 推出)
2、談談 UI 中, Padding 和 Margin 有什麼區別?
android:padding 和 android:layout_margin 的區別,其實概念很簡單,padding 是站在父 view 的角度描述問 題,它規定它裡面的內容必須與這個父 view 邊界的距離。margin 則是站在自己的角度描述問題,規定自己和其他(上下左右)的 view 之間的距離,如果同一級只有一個 view,那麼它的效果基本上就和 padding 一樣了。
3、使用權重如何讓一個控制元件的寬度為父控制元件的 1/3?
可以在水平方向的 LinearLayout 中設定 weightSum 為 3,然後讓其子控制元件的 weight 為 1,那麼該子控制元件就是父控制元件的 1/3。
4、Android 中佈局的優化措施都有哪些?
這個問題也屬於Android 效能優化的一部分。
1、儘可能減少佈局的巢狀層級
可以使用 sdk 提供的 hierarchyviewer 工具分析檢視樹,幫助我們發現沒有用到的佈局。
2、不用設定不必要的背景,避免過度繪製,比如父控制元件設定了背景色,子控制元件完全將父控制元件給覆蓋的情況下,那麼父控制元件就沒有必要設定背景。
3、使用<include>標籤複用相同的佈局程式碼
4、使用<merge>標籤減少檢視層次結構
該標籤主要有兩種用法:
1) 因為所有的 Activity 檢視的根節點都是 FrameLayout,因此如果我們的自定義的佈局也是 FragmenLayout 的時候那麼可以使用 merge 替換。
2) 當應用 Include 或者 ViewStub 標籤從外部匯入 xml 結構時,可以將被匯入的 xml 用 merge 作為根節 點表示,這樣當被嵌入父級結構中後可以很好的將它所包含的子集融合到父級結構中,而不會出現冗餘的節點。
<merge>只能作為 xml 佈局的根元素。
5、通過<ViewStub>實現 View 的延遲載入
5、android:layout_gravity 和 android:gravity 的區別?
第一個是讓該佈局在其父控制元件中的佈局方式,第二個是該佈局佈置其字物件的佈局方式。
6、scrollView 巢狀 listview 方式除了測量還有什麼方法?
a. 手動設定 ListView 高度
經過測試發現,在 xml 中直接指定 ListView 的高度,是可以解決這個問題的,但是 ListView 中的資料是可變的,實際高度還需要實際測量。 於是手動程式碼設定 ListView 高度的方法就誕生了。
b. 使用單個 ListView 取代 ScrollView 中所有內容
如果滿足頭佈局和腳佈局的 UI 設計,直接使用 listview 替代 scrollview
c. 使用 LinearLayout 取代 ListView
既然 ListView 不能適應 ScrollView,那就換一個可以適應 ScrollView 的控制元件,幹嘛非要吊死在 ListView 這一棵樹上呢? 而 LinearLayout 是最好的選擇。但如果我仍想繼續使用已經定義好的 Adater 呢?我們只需要自定 義一個類繼承自 LinearLayout,為其加上對 BaseAdapter 的適配。
d. 自定義可適應 ScrollView 的 ListView
可以自定義一個類繼承自 ListView,通過重寫其 onMeasure 方法,達到對 ScrollView 適配的效果。
7、dp 和 px 之間的關係?
dp:是 dip 的簡寫,指密度無關的畫素。 指一個抽象意義上的畫素,程式用它來定義介面元素。一個與密度無關的,在邏輯尺寸上,與一個位於畫素密度為 160dpi 的螢幕上的畫素是一致的。 要把密度無關畫素轉換為螢幕畫素,可以用這樣一個簡單的公式: pixels=dips*(density/160)。舉個例子,在 DPI 為 240 的螢幕上,1 個 DIP 等 於 1.5 個物理畫素。
佈局時最好使用 dp 來定義我們程式的介面,因為這樣可以保證我們的 UI 在各種解析度的螢幕上都可以正常顯示。
/*根據手機的解析度從PX(畫素)的單位轉成dip*/
public static int pxToDip(Context context, float pxValue){
final float scale = context.getResources().getDisplayMetrics().density;
return(int)(pxValue/scale+0.5f);
}
/*根據手機的解析度從dip的單位轉化為px(畫素)*/
public static int dipTopx(Context context, float dpValue){
final float scale = context.getResources().getDisplayMetrics().density;
return(int)(dpValue*scale+0.5f);
}
於是乎,應該也能理解android專案中的圖片資原始檔,一般我們需要在以下幾個資料夾中提供不同大小的圖片。
xhdpi: 2.0
hdpi: 1.5
mdpi: 1.0 (baseline)
ldpi: 0.75
如果一張放在mdpi 的圖片載入到記憶體中大小是 10m ,那麼遇到hdpi的裝置圖片載入到記憶體中大小是15m。
8、什麼是螢幕尺寸、螢幕解析度、螢幕畫素密度?
螢幕尺寸是指螢幕對角線的長度。單位是英寸,1英寸=2.54釐米。
螢幕解析度是指在橫縱向上的畫素點數,單位是px,1px=1畫素點,一般是縱向畫素橫向畫素,如1280×720。
螢幕畫素密度是指每英寸上的畫素點數,單位是dpi,即“dot per inch”的縮寫,畫素密度和螢幕尺寸和螢幕解析度有關。
9、Android 樣式和主題?
樣式(Styles):
Android 允許在外部樣式檔案中定義 Android 應用程式的 Look 和 Feel ,你可以將定義好的樣式應用在不同的檢視(Views)上。你可以在 XML 檔案中定義樣式,並將這些樣式運用到不同的元件上。使用XML這種方式定義樣式,你只需要配置一些通用的屬性,以後如果需要修改樣式,可以集中修改。
屬性(Attributes):
你也可以將單個屬性應用到 Android 樣式上,通常會在自定義View 的時候,自定義屬性。
主題(Themes):
主題相比單個檢視而言,是應用到整個 Activity 或者 application 的樣式
10、如何將Acitivity中的Window的背景圖設定為空?
getWindow().setBackgroundDrawable(null);//android的預設背景是不是為空。
11、佈局適配
在明白上面基礎問題的一些基本概念後,這裡總結了一些佈局適配的經驗。
在Android 中 有4種普遍尺寸:小(small),普通(normal),大(large),超大(xlarge) 。
常見的普遍解析度: 低精度(ldpi), 中精度(mdpi), 高精度(hdpi), 超高精度(xhdpi) 1080P(xxhdpi)。
A. 基本設定
在中Menifest中新增子元素 android:anyDensity=”true”時,應用程式安裝在不同密度的終端上時,程式會分別載入xxhdpi、xhdpi、hdpi、mdpi、ldpi資料夾中的資源。 相反,如果設為false,即使在資料夾下擁有相同資源,應用不會自動地去相應資料夾下尋找資源。
B. 適配方案
1、使用wrap_content、math_parent、weight wrap_content:
根據控制元件的內容設定控制元件的尺寸 math_parent:根據父控制元件的尺寸大小設定控制元件的尺寸 ;weight:權重,線上性佈局中可以使用weight屬性設定控制元件所佔的比例。
2、使用相對佈局,禁用絕對佈局。
3、建立不同的layout:每一種layout需要儲存在相應的資源目錄中,目錄以-為字尾命名。例如,對大尺寸螢幕(large screens),一個唯一的layout檔案應該儲存在res/layout-large/中。
4、使用9-patch PNG圖片:當我們需要使圖片在拉伸後還能保持一定的顯示效果,比如,不能使圖片中的重要畫素拉伸,不能使內容區域受到拉伸的影響,我們就可以使用.9.png圖來實現。
12、Android Drawable
Drawable屬於輕量級的、使用也很簡單,Android把可繪製的物件抽象為Drawable,不同的圖形影象資源就代表著不同的drawable型別, 在實際的開發過程中使用@drawable來使用drawable資源。關於Drawable更多的請看下圖
13、View
A. View是什麼?
簡單來說,View是Android系統在螢幕上的視覺呈現,也就是說你在手機螢幕上看到的東西都是View。
B. View是如何繪製出來的?
View的繪製流程是從ViewRoot的performTraversals()方法開始,依次經過measure(),layout()和draw()三個過程才最終將一個View繪製出來。
C. View是怎麼呈現在介面上的?
Android中的檢視都是通過Window來呈現的,不管Activity、Dialog還是Toast它們都有一個Window,然後通過WindowManager來管理View。Window和頂級View——DecorView的通訊是依賴ViewRoot完成的。
D. 關於Android View控制元件的理解
Android中控制元件大致被分為兩類ViewGroup,View。ViewGroup作為容器管理View。Android檢視,是類似於Dom樹的架構。父檢視負責測量定位繪製等操作。我們經常在用的findViewById 方法代價昂貴的原因,就是因為他負責至上而下遍歷整棵控制元件樹,來尋找View例項,在重複操作中儘量少用。現在在用的很多控制元件都是直接或者間接繼承自View的,為了方便理解可看下圖
14、View和ViewGroup什麼區別?
Android的UI介面都是由View和ViewGroup及其派生類組合而成的。其中,View是所有UI元件的基類,而ViewGroup是容納這些元件的容器,其本身也是從View派生出來的。AndroidUI介面的一般結構:
15、Android View重新整理機制?
在Android的佈局體系中,父View負責重新整理、佈局顯示子View;而當子View需要重新整理時,則是通知父View來完成。
16、RelativeLayout和LinearLayout效能比較?
1.RelativeLayout會讓子View呼叫2次onMeasure,LinearLayout 在有weight時,也會呼叫子View2次onMeasure
2.RelativeLayout的子View如果高度和RelativeLayout不同,則會引發效率問題,當子View很複雜時,這個問題會更加嚴重。如果可以,儘量使用padding代替margin。
3.在不影響層級深度的情況下,使用LinearLayout和FrameLayout而不是RelativeLayout。
17、Android UI介面架構理解
每個Activity,Dialog,Toast都包含一個PhoneWindow物件,PhoneWindow設定DecorView為應用視窗的根檢視。在裡面就是熟悉的TitleView和ContentView,沒錯,平時使用的setContentView()就是設定的ContentView。