傳送門 ☞ 輪子的專欄 ☞ 轉載請註明 ☞ http://blog.csdn.net/leverage_1229
今天我們學習如何自訂TextView組件,讓它既能顯示文本,又能顯示映像,達到“圖文並茂”的效果。這種圖文混搭的方式常常被用來展現新聞、文章、多媒體訊息等內容。下面給出該情景的案例:
1案例技術要點
1.1建立attrs.xml檔案用於設定自訂群組件的屬性、類型和樣式。
1.2利用android.content.res.TypedArray類將自訂群組件裝載到程式,以供程式調用。
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.customTextView);
1.3布局檔案引入自訂群組件需要如下設定
自訂群組件命名空間:
xmlns:custom="http://schemas.android.com/apk/res/com.custom.textview"
自訂群組件標籤:
<com.custom.textview.CustomTextView .../>
1.4構造一個HashMap資料結構,用於儲存自訂群組件的內容類型和值。
key:自訂群組件的內容類型(image、text)
value:自訂群組件的內容值(imageUrl,CharSequence)
1.5利用android.widget.LinearLayout.LayoutParams類用於設定組件的布局參數。這裡需要根據顯示內容的類型動態地設定組件的布局參數。
2案例代碼陳列
2.1工程包目錄
2.2AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.custom.textview" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" /> <uses-permission android:name="android.permission.INTERNET"/> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name"> <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
2.3strings.xml
<resources> <string name="app_name">自訂TextView實現圖文並茂</string></resources>
2.4自訂TextView組件的屬性類型樣式檔案:attrs.xml
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="customTextView"> <attr name="image_width" format="dimension" /> <attr name="image_height" format="dimension" /> <attr name="text_color" format="color" /> <attr name="text_size" format="dimension" /> </declare-styleable></resources>
2.5main.xml
<?xml version="1.0" encoding="utf-8" ?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res/com.custom.textview" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="@android:color/white" > <com.custom.textview.CustomTextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="wrap_content" custom:image_width="200dp" custom:image_height="50dp" /></LinearLayout>
2.6自訂群組件類:CustomTextView.java
package com.custom.textview;import java.net.URL;import java.util.ArrayList;import java.util.HashMap;import android.content.Context;import android.content.res.TypedArray;import android.graphics.drawable.Drawable;import android.os.Handler;import android.os.Message;import android.os.SystemClock;import android.text.Html;import android.util.AttributeSet;import android.view.Gravity;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView;public class CustomTextView extends LinearLayout { private Context context; private TypedArray typedArray; private LayoutParams params; public CustomTextView(Context context) { super(context); } public CustomTextView(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; this.setOrientation(LinearLayout.VERTICAL); // 從attrs.xml中擷取自訂屬性 typedArray = context.obtainStyledAttributes(attrs, R.styleable.customTextView); } public void setText(ArrayList<HashMap<String, String>> data) { for (HashMap<String, String> hashMap : data) { String type = hashMap.get("type"); String value = hashMap.get("value"); // 如果內容類型是圖片 if (type.equals("image")) { // 設定圖片顯示寬高、集中 int imageWidth = typedArray.getDimensionPixelOffset(R.styleable.customTextView_image_width, 100); int imageHeight = typedArray.getDimensionPixelOffset(R.styleable.customTextView_image_height, 100); ImageView imageView = new ImageView(context); params = new LayoutParams(imageWidth, imageHeight); params.gravity = Gravity.CENTER_HORIZONTAL; imageView.setLayoutParams(params); // 顯示預設圖片 imageView.setImageResource(R.drawable.ic_launcher); // 將ImageView添加到CustomTextView中 addView(imageView); // 開啟背景工作執行緒非同步載入圖片 new DownloadWork(value, imageView).start(); } else if (type.equals("text")) { int textColor = typedArray.getColor(R.styleable.customTextView_text_color, 0xFF0000FF); float textSize = typedArray.getDimension(R.styleable.customTextView_text_size, 16); TextView textView = new TextView(context); textView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); textView.setText(Html.fromHtml(value)); textView.setTextColor(textColor); textView.setTextSize(textSize); addView(textView); } } } private class DownloadWork extends Thread { private String imageUrl; private ImageView imageView; public DownloadWork(String imageUrl, ImageView imageView) { this.imageUrl = imageUrl; this.imageView = imageView; } @Override public void run() { URL url = null; Drawable drawable = null; int newImageWidth = 0; int newImageHeight = 0; try { url = new URL(imageUrl); drawable = Drawable.createFromStream(url.openStream(), "image"); // 對圖片進行縮放 newImageWidth = drawable.getIntrinsicWidth() / 3; newImageHeight = drawable.getIntrinsicHeight() / 3; } catch (Exception e) { e.printStackTrace(); } SystemClock.sleep(2000); HashMap<String, Object> map = new HashMap<String, Object>(); map.put("imageView", imageView); map.put("drawable", drawable); Message msg = handler.obtainMessage(); msg.obj = map; msg.arg1 = newImageWidth; msg.arg2 = newImageHeight; handler.sendMessage(msg); } } private Handler handler = new Handler() { public void handleMessage(Message msg) { @SuppressWarnings("unchecked") HashMap<String, Object> map = (HashMap<String, Object>) msg.obj; ImageView imageView = (ImageView) map.get("imageView"); LayoutParams params = new LayoutParams(msg.arg1, msg.arg2); params.gravity = Gravity.CENTER_HORIZONTAL; imageView.setLayoutParams(params); Drawable drawable = (Drawable) map.get("drawable"); imageView.setImageDrawable(drawable); } };}
2.7MainActivity.java
package com.custom.textview;import java.util.ArrayList;import java.util.HashMap;import android.app.Activity;import android.os.Bundle;public class MainActivity extends Activity { private final String text = " <p> 今年浙江衛視憑《中國好聲音》一舉做大" + ",其巨大的影響力直接波及到了各家衛視“跨年晚會”的戰略部署。日前" + ",“跨年晚會”概念的鼻祖湖南衛視率先表示“退出跨年燒錢大戰”。" + "但據湖南衛視內部人士透露,即使如此,今年的湖南跨年晚會也將會掂出“跨年季”這個概念" + ",“也就是從12月27日到12月31日,連續五天,我們將相繼用《百變大咖秀》、《快樂大本營》" + "、《女人如歌》、《天天向上》的特別節目來連續打造這個”季“的概念,直到12月31日的那場晚會。”</p>"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 採集顯示內容資料 ArrayList<HashMap<String, String>> data = new ArrayList<HashMap<String,String>>(); HashMap<String, String> part1 = new HashMap<String, String>(); part1.put("type", "image"); part1.put("value", "http://www.linuxidc.com/upload/2012_12/121218101020341.png"); HashMap<String, String> part2 = new HashMap<String, String>(); part2.put("type", "text"); part2.put("value", text); HashMap<String, String> part3 = new HashMap<String, String>(); part3.put("type", "image"); part3.put("value", "http://www.linuxidc.com/upload/2012_12/121218101020341.png"); data.add(part1); data.add(part2); data.add(part3); CustomTextView customTextView = (CustomTextView) findViewById(R.id.textView); customTextView.setText(data); }}3案例效果展示