React Native Android之原生UI組件動態(tài)addView不顯示問題解決
版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載寿烟。
轉(zhuǎn)載請表明出處:http://www.reibang.com/p/a6c5042c5ce8
[TOC]
在如今的App中箱蟆,已經(jīng)有成千上萬的原生UI部件了——其中的一些是平臺的一部分瑰排,另一些可能來自于一些第三方庫挖炬,而且可能你自己還收藏了很多。React Native已經(jīng)封裝了大部分最常見的組件鼠渺,譬如ScrollView
和TextInput
,但不可能封裝全部組件眷细。而且拦盹,說不定你曾經(jīng)為自己以前的App還封裝過一些組件,React Native肯定沒法包含它們溪椎。幸運的是掌敬,在React Naitve應用程序中封裝和植入已有的組件非常簡單。但在實施的過程中往往會發(fā)生一些小狀況池磁,如今天分享的這個問題奔害,當原生UI組件
動態(tài)addView時在界面中不顯示。
(下面React Native 簡稱為RN)
還原場景
在下面代碼中地熄,我們定義了一個原生的控件华临,這個組件同樣也可用于RN。
public class RCTVideoLayout extends RelativeLayout {
public RCTVideoLayout(Context context) {
this(context, null);
}
public RCTVideoLayout(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public RCTVideoLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
/**
* 初始化View
*
* @param context
*/
private void initView(Context context) {
View rootView = View.inflate(context, R.layout.video_layout, null);
addView(rootView);
}
/**
* 動態(tài)添加View
* @param str
*/
public void autoAddView(String str){
Button button = new Button(getContext());
button.setText(str);
addView(button);
}
在這段上面的autoAddView
函數(shù)中就是一個動態(tài)添加View
的操作端考,如果這段代碼在原生中執(zhí)行是沒問題的雅潭,但在RN中動態(tài)調(diào)用,會導致無論addView多少次都沒問題却特,但在RN中每次調(diào)用均在UI中看不出有什么明顯變化扶供,通過斷點也是沒發(fā)現(xiàn)問題所在,那么究竟是什么原因?qū)е碌哪亓衙鳎旅嫖医o大家分析一下椿浓。
利用工具分析問題所在
發(fā)生如此詭異的情況,該怎么分析呢闽晦?Android Studio
中有個工具Layout inspector
扳碍,這個工具可以快速對手機上面的界面做分析。
-
Android Studio
打開任意工程后仙蛉,按照如下圖所示:
WechatIMG11
- 等待幾秒后笋敞,會自動打開分析界面:
這個界面是一個Demo工程,里面同樣也是用RN調(diào)用原生封裝的組件荠瘪,但同樣的情況是調(diào)用了原生addView后夯巷,并沒有在UI上看到
-
現(xiàn)在把所有的層級打開后赛惩,發(fā)現(xiàn)原生的確已經(jīng)addView進去了,只不過他的height和 width 都是0趁餐,所以這樣就能解釋為什么我們動態(tài)添加View后看不到UI變化喷兼。
WechatIMG8
解決方案
-
從上圖中可以分析得到,無論我們
addView
多少次澎怒,所產(chǎn)生的View都是0高0寬
褒搔,這個明顯就是沒有讓ViewGroup
去測量子控件。現(xiàn)在原因已經(jīng)明了喷面,那么如何解決這種問題呢星瘾?那當然是讓ViewGroup每次都自己測量子控件的高寬咯皮假,我們回到剛才的自定義ViewGroup中的代碼中怜械,添加如下代碼://以下代碼修復通過動態(tài) addView 后看不到的問題 @Override public void requestLayout() { super.requestLayout(); post(measureAndLayout); } private final Runnable measureAndLayout = new Runnable() { @Override public void run() { measure( MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.EXACTLY)); layout(getLeft(), getTop(), getRight(), getBottom()); } };
以上代碼中所作的事情就是每次
addView
后图毕,在ViewGroup
源碼中可看到addView
后茫死,實際調(diào)用requestLayout()
函數(shù),如下圖所示:
-
添加代碼后阿宅,我們再次運行程序碾局,再次通過
Layout inspector
工具來看看效果:WechatIMG9 可以發(fā)現(xiàn)這回終于有顯示了碗脊,再看到hight和width都有對應的值了边翁。
總結(jié)
以上是我在封裝原生控件給RN調(diào)用時遇到的一個問題翎承,歡迎大家支持。