動態創建TextView的兩種方式:
下面介紹兩種創建方式:
在drawable里面創建共同依賴的background.xml文件,里面設置shape來設置文本框的一些特殊效果:
eg:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" ><!-- 實心 --> <solid android:color="@android:color/white" /> <!-- 邊框 --> <stroke android:width="0.5dp" android:color="@android:color/black" /> <!-- 圓角 --> <corners android:radius="3dp" /> <!-- 邊距 --> <padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" /> <!-- 漸變 --> <gradient android:angle="270" android:endColor="#FFFF782" android:startColor="#13C7AF" />
</shape>
- 代碼方式:
TextView textView = new TextView(context);
textView.setId(id);
textView.setText("android");
textView.setTextColor(0xff999faa);
textView.setTextSize(12);
textView.setBackgroundResource(R.drawable.background);
- xml配置文件和代碼結合方式:
textview_layout.xml<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="match_parent"android:layout_height="match_parent"><TextView
android:id="@+id/textView"android:layout_width="match_parent"android:layout_height="wrap_content"android:textColor="#999faa"android:textSize="12sp"android:background="@drawable/background"android:text="android" />
</LinearLayout>
ViewGroup viewGroup = (ViewGroup) LayoutInflater.from(this).inflate(R.layout.textiew, null);
TextView textView = (TextView) findViewById(R.id.textView);
viewGroup.removeView(textView);//替換掉textId
textView.setId(id);
這樣通過前面的兩種方式即可創建一個TextView控件,通過xxxViewGroup.addView(textView)即可將改textView加入到xxxViewGroup中。
TextView控件布局位置的控制:
上面創建了textView控件,但該控件的布局位置并沒有確定,而這個布局位置又是十分重要的,否則該控件也沒有存在的意義。
//此處以RelativeLayout布局為例,同樣LinearLayout也支持該接口
//設置RelativeLayout布局的寬高
RelativeLayout.LayoutParams reLayoutParams =
new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
//以下rules說明設置控件在xxxView的右側,父控件的底部
reLayoutParams.addRule(RelativeLayout.RIGHT_OF, xxxViewId);
reLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
//setMargins設置控件相對其他控件的間隔
reLayoutParams.setMargins(left, top, right, bottom);
以上代碼只完成了RelativeLayout的布局rules的設置,如何和待控制的控件綁定呢?
xxxViewGroup.addView(textView,reLayoutParams);
為TextView添加邊框
在文章開始部分創建了一個background.xml文件,但并沒有說明該xml文件的作用,不過也容易猜到,這個background.xml為textView設置了一個邊框。
默認情況下TextView控件是沒有邊框的,如何創建邊框,有以下方式:
- 設置background為透明圖片的背景圖。
- 通過shape設置背景圖片。(推薦,background.xml即為這個shape配置文件,對該文件各項參數的設置,請參考google)
對前面代碼中幾處關鍵點的說明:
- View.setId(int id)如何避免id沖突:
按照規則,每個View都必須有一個唯一的標識符,這個標識符是一個正整數。而我們上面代碼中動態創建的View要如何保證id的唯一性?
在sdk17 以上使用myView.setId(View.generateViewId());在低于17 的版本中我們需要自己去實現一些方法,參考View.Java的內部實現:
private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);/**
* Generate a value suitable for use in {@link #setId(int)}.
* This value will not collide with ID values generated at build time by aapt for R.id.
*
* @return a generated ID value
*/
public static int generateViewId() {for (;;) {final int result = sNextGeneratedId.get();// aapt-generated IDs have the high byte nonzero; clamp to the range under that.int newValue = result + 1;if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.if (sNextGeneratedId.compareAndSet(result, newValue)) {return result;}}
}ID大于0x00FFFFFF的已經在xml中定義到了,容易發生沖突。在調用的地方可以這樣使用:if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {myView.setId(Utils.generateViewId());} else {myView.setId(View.generateViewId());}}
- 為什么要調用viewGroup.removeView(textView)?
一個View只能依賴于一個父ViewGroup,我們通過inflate這種方式創建的view已經屬于一個ViewGroup了,所以此處需要父ViewGroup先remove掉,否則會報這樣的錯誤:”The specified child already has a parent. You must call removeView”
關于異常“The specified child already has a parent. You must call removeView”的解決
擴展內容—動態添加布局
前面講到動態添加控件,而布局同樣可以動態添加:
方法和上面類似,主要注重如何控制添加的布局的位置,在控制布局的位置的時候使用LayoutParam類來實現。
RelativeLayout rl = new RelativeLayout(this);
//設置RelativeLayout布局的寬高
RelativeLayout.LayoutParams relLayoutParams=new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
xxxViewGroup.addView(rl, relLayoutParams);
控件屬性相關的一些動態設置的接口:
// 設置背景圖
textView.setBackgroundResource(R.drawable.block_text_backgroumg);
// 設置背景透明度
textView.getBackground().setAlpha(150);
// 設定text內容為Html格式
textView.setText(Html.fromHtml(rsultText));
// 設定為可以scroll的textView
textView.setMovementMethod(ScrollingMovementMethod.getInstance());
// 設定text內容與邊框的距離
textView.setPadding(6, 6, 6, 6);
參考資料:
Android 利用addView 動態給Activity添加View組件
android 中使用View.setId(int id),如何避免id沖突呢?