android LayoutInflater、setContentView、findviewbyid 區分解析
一、LayoutInflater.inflate(layoutId, root, boolen)中三個引數的意義及作用
(這點可以參考鴻洋前輩部落格地址:http://blog.csdn.net/lmj623565791/article/details/38171465)
主要知識點其實很少,如下:
若temp為layoutId所代表的佈局,inflate的三種方法區分如下:
View view=LayoutInflater.Inflate(layoutId, null )只建立temp ,temp.LayoutParams=null,返回temp
View view=LayoutInflater.Inflate(layoutId, root, false )建立temp,temp.LayoutParams=root.LayoutParams;返回temp
View view=LayoutInflater.Inflate(layoutId, root, true ) 建立temp,然後執行root.addView(temp, params);最後返回root
關於點三條可能難以理解,此處筆者自己寫了一個例子:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Main Text View"/>
</LinearLayout>
button_layout.xml<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
MainActivity.java
package com.example.double2.layoutinflatertest;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity {
private LinearLayout mainLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainLayout = (LinearLayout) findViewById(R.id.main_layout);
LayoutInflater layoutInflater = LayoutInflater.from(this);
View buttonLayout = layoutInflater.inflate(R.layout.button_layout, null);
mainLayout.addView(buttonLayout);
// View buttonLayout = layoutInflater.inflate(R.layout.button_layout, mainLayout,true);
}
}
View buttonLayout = layoutInflater.inflate(R.layout.button_layout, null);
mainLayout.addView(buttonLayout);
當執行如下一句時,佈局如下:
View buttonLayout = layoutInflater.inflate(R.layout.button_layout, mainLayout,true);
二、又上圖可知,兩種方式都是可以給activity_main中加入button佈局了,但是讓人奇怪的是,為什麼兩者是同一個button,顯示的卻會有差別呢?第二個問題就自然出來了。
解決辦法:我們給button_layout中的button加上一個RelativeLayout,如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"/>
</RelativeLayout>
然後我們可以發現,兩種方式都只會有一種效果了,如下:可以發現,這往往就是我們最想要的效果,就是這個button本來多大,就給它。這樣我們修改這個button的時候才比較方便。
那麼是什麼導致在第一個問題中,button無法顯示原來的大小的呢?
View buttonLayout = layoutInflater.inflate(R.layout.button_layout, null);
mainLayout.addView(buttonLayout);
當我們執行如上程式碼時,root為null,我們獲得的buttonLayout的LayoutParams為null。當我們在viewgroup中使用addView(View child)方法,新增一個沒有LayoutParams屬性的子view。在viewgroup方法內部,它會呼叫generateDefaultLayoutParams()生成一個LayoutParams賦值個給子view。
LayoutParams有什麼用呢?
簡單來說,當一個view的LayoutParams存在時,該佈局的寬高設定才會有效。而一個view需要存在LayoutParams,就必須存在父佈局。
關於LayoutParams,可以參考這篇部落格:http://blog.csdn.net/double2hao/article/details/51438798
View buttonLayout = layoutInflater.inflate(R.layout.button_layout, mainLayout,true);
而當我們執行這行程式碼的時候,我們最終返回的是root,而root即為activity_main中的LinearLayout。也就和button本身並沒有什麼關係了。三、那麼activity_main中的LinearLayout也為空,為什麼我們經常使用setContentView(R.id.XXX)的時候卻不會造成LayoutParams的缺失而導致佈局無法準確顯示的問題呢?
如此,我們就需要去了解setContentView()和layoutInflater.inflate()的區別了。
setContentView()設定佈局的時候,Android會自動在佈局檔案的最外層再巢狀一個FrameLayout,所以設定的佈局是存在LayoutParams的,也因此可以正常顯示。
關於問題二和三,如果還有興趣的讀者,可以參考一下郭霖前輩的部落格:
http://blog.csdn.net/guolin_blog/article/details/12921889
四,findviewbyid()和LayoutInflater.Inflate()有什麼區別呢?
findViewById():從setContentView()已經設定的layout中獲取到某個控制元件。
Inflate():把某個layout從xml檔案中例項化成一個物件。
相關文章
- Android LayoutInflater 原始碼解析Android原始碼
- 從findViewById失效的問題到深入setContentViewView
- Android setContentView原始碼解析AndroidView原始碼
- Android LayoutInflater Factory 原始碼解析Android原始碼
- Android 原始碼解析 之 setContentViewAndroid原始碼View
- Android View 原始碼解析(一) - setContentViewAndroidView原始碼
- View.findViewById()和Activity.findViewById()區別View
- Android顯示框架:Android佈局解析者LayoutInflaterAndroid框架
- Android原始碼解析Activity#setContentView()方法Android原始碼View
- Android:隨筆——取代findViewByIdAndroidView
- 【Android原始碼】LayoutInflater 分析Android原始碼
- Android 從SetContentView()談起AndroidView
- Android原始碼分析(LayoutInflater.from(this).inflate(resId,null);原始碼解析)Android原始碼Null
- Android技能樹 — LayoutInflater Factory小結Android
- 探索Android檢視載入器LayoutInflaterAndroid
- Android view 部分 setContentView 的前因後果AndroidView
- Android中深入理解 LayoutInflater.inflate()Android
- Android事件分發機制解析Android事件
- Android LayoutInflater.inflate各個引數作Android
- android中LayoutInflater.from(context).inflate的分析AndroidContext
- 選擇ButterKnife,告別findViewByIdView
- Android 事件分發機制原始碼解析Android事件原始碼
- View 繪製體系知識梳理(2) setContentView 原始碼解析View原始碼
- Activity 中的方法 findViewById(int) 和 AppCompatActivity 中的方法 findViewById(int) 都匹配...ViewAPP
- Flex佈區域性分屬性困惑解析Flex
- 深入理解LayoutInflater
- Android系統原始碼分析--View繪製流程之-setContentViewAndroid原始碼View
- Android系統原始碼分析–View繪製流程之-setContentViewAndroid原始碼View
- Android 中LayoutInflater(佈局載入器)系列博文說明Android
- View 繪製體系知識梳理(1) LayoutInflater#inflate 原始碼解析View原始碼
- Android 事件分發機制原始碼解析-view層Android事件原始碼View
- Android事件分發機制之原始碼完美解析(上)Android事件原始碼
- Android 事件分發完全解析之為什麼是她Android事件
- Android 事件分發完全解析之事件從何而來Android事件
- Android 中LayoutInflater(佈局載入器)原始碼篇之rInflate方法Android原始碼
- Android中區分系統程式和安裝程式Android
- Android面試送分題:Android面試真題解析火爆全網,建議收藏Android面試
- Activity中setContentView做了什麼View