今天我们学习如何自定义TextView组件,让它既能显示文本,又能显示图像,达到“图文并茂”的效果。这种情景在新闻、文章、彩信内容中很常见。下面给出该场景的案例:

一、案例技术要点

1.创建attrs.xml文件用于设置自定义组件的属性、类型和样式。

2.利用android.content.res.TypedArray类将自定义组件装载到程序,以供程序调用。


1. TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.customTextView);

3.布局文件引入自定义组件需要如下设置

自定义组件命名空间:

1. xmlns:custom="http://schemas.android.com/apk/res/com.custom.textview"

自定义组件标签:


1. <com.custom.textview.CustomTextView .../>

4.构造一个HashMap数据结构,用于保存自定义组件的内容类型和值。

key:自定义组件的内容类型(image、text)

value:自定义组件的内容值(imageUrl,CharSequence)

5.利用android.widget.LinearLayout.LayoutParams类用于设置组件的布局参数。这里需要根据显示内容的类型动态地设置组件的布局参数。

二、案例代码陈列

AndroidManifest.xml



1. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
2. package="com.custom.textview"  
3. android:versionCode="1"  
4. android:versionName="1.0" >  
5.   
6. <uses-sdk  
7. android:minSdkVersion="8"  
8. android:targetSdkVersion="15" />  
9.       
10. <uses-permission android:name="android.permission.INTERNET"/>  
11.       
12. <application  
13. android:icon="@drawable/ic_launcher"  
14. android:label="@string/app_name">  
15. <activity  
16. android:name=".MainActivity"  
17. android:label="@string/app_name" >  
18. <intent-filter>  
19. <action android:name="android.intent.action.MAIN" />  
20.   
21. <category android:name="android.intent.category.LAUNCHER" />  
22. </intent-filter>  
23. </activity>  
24. </application>  
25.       
26. </manifest>

strings.xml


1. <resources>  
2. <string name="app_name">自定义TextView实现图文并茂</string>  
3. </resources>


自定义TextView组件的属性类型样式文件:attrs.xml

1. <?xml version="1.0" encoding="utf-8"?>  
2. <resources>  
3. <declare-styleable name="customTextView">  
4. <attr name="image_width" format="dimension" />  
5. <attr name="image_height" format="dimension" />  
6. <attr name="text_color" format="color" />  
7. <attr name="text_size" format="dimension" />  
8. </declare-styleable>  
9. </resources>


main.xml


1. <?xml version="1.0" encoding="utf-8" ?>  
2. "http://schemas.android.com/apk/res/android"  
3. "http://schemas.android.com/apk/res/com.custom.textview"  
4. "match_parent"  
5. "match_parent"  
6. "vertical"  
7. "@android:color/white" >  
8.   
9.     <com.custom.textview.CustomTextView  
10. "@+id/textView"  
11. "match_parent"  
12. "wrap_content"  
13. "200dp"  
14. "50dp" />  
15.   
16. </LinearLayout>

自定义组件类:CustomTextView.java


1. package com.custom.textview;  
2.   
3. import java.net.URL;  
4. import java.util.ArrayList;  
5. import java.util.HashMap;  
6.   
7. import android.content.Context;  
8. import android.content.res.TypedArray;  
9. import android.graphics.drawable.Drawable;  
10. import android.os.Handler;  
11. import android.os.Message;  
12. import android.os.SystemClock;  
13. import android.text.Html;  
14. import android.util.AttributeSet;  
15. import android.view.Gravity;  
16. import android.widget.ImageView;  
17. import android.widget.LinearLayout;  
18. import android.widget.TextView;  
19.   
20. public class CustomTextView extends LinearLayout {  
21. private Context context;  
22. private TypedArray typedArray;  
23. private LayoutParams params;  
24.   
25. public CustomTextView(Context context) {  
26. super(context);  
27.     }  
28.   
29. public CustomTextView(Context context, AttributeSet attrs) {  
30. super(context, attrs);  
31. this.context = context;  
32. this.setOrientation(LinearLayout.VERTICAL);  
33. // 从attrs.xml中获取自定义属性  
34.         typedArray = context.obtainStyledAttributes(attrs, R.styleable.customTextView);  
35.     }  
36.   
37. public void setText(ArrayList<HashMap<String, String>> data) {  
38. for (HashMap<String, String> hashMap : data) {  
39. "type");  
40. "value");  
41. // 如果内容类型是图片  
42. if (type.equals("image")) {  
43. // 设置图片显示宽高、集中  
44. int imageWidth = typedArray.getDimensionPixelOffset(R.styleable.customTextView_image_width, 100);  
45. int imageHeight = typedArray.getDimensionPixelOffset(R.styleable.customTextView_image_height, 100);  
46. new ImageView(context);  
47. new LayoutParams(imageWidth, imageHeight);  
48.                 params.gravity = Gravity.CENTER_HORIZONTAL;  
49.                 imageView.setLayoutParams(params);  
50. // 显示默认图片  
51.                 imageView.setImageResource(R.drawable.ic_launcher);  
52. // 将ImageView添加到CustomTextView中  
53.                 addView(imageView);  
54. // 开启工作线程异步加载图片  
55. new DownloadWork(value, imageView).start();  
56. else if (type.equals("text")) {  
57. int textColor = typedArray.getColor(R.styleable.customTextView_text_color, 0xFF0000FF);  
58. float textSize = typedArray.getDimension(R.styleable.customTextView_text_size, 16);  
59. new TextView(context);  
60. new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));  
61.                 textView.setText(Html.fromHtml(value));  
62.                 textView.setTextColor(textColor);  
63.                 textView.setTextSize(textSize);  
64.                 addView(textView);  
65.             }  
66.         }  
67.     }  
68.   
69. private class DownloadWork extends Thread {  
70. private String imageUrl;  
71. private ImageView imageView;  
72.   
73. public DownloadWork(String imageUrl, ImageView imageView) {  
74. this.imageUrl = imageUrl;  
75. this.imageView = imageView;  
76.         }  
77.   
78. @Override  
79. public void run() {  
80. null;  
81. null;  
82. int newImageWidth = 0;  
83. int newImageHeight = 0;  
84. try {  
85. new URL(imageUrl);  
86. "image");  
87. // 对图片进行缩放  
88. 3;  
89. 3;  
90. catch (Exception e) {  
91.                 e.printStackTrace();  
92.             }  
93. 2000);  
94.   
95. new HashMap<String, Object>();  
96. "imageView", imageView);  
97. "drawable", drawable);  
98.             Message msg = handler.obtainMessage();  
99.             msg.obj = map;  
100.             msg.arg1 = newImageWidth;  
101.             msg.arg2 = newImageHeight;  
102.             handler.sendMessage(msg);  
103.         }  
104.     }  
105.   
106. private Handler handler = new Handler() {  
107. public void handleMessage(Message msg) {  
108. @SuppressWarnings("unchecked")  
109.             HashMap<String, Object> map = (HashMap<String, Object>) msg.obj;  
110. "imageView");  
111. new LayoutParams(msg.arg1, msg.arg2);  
112.             params.gravity = Gravity.CENTER_HORIZONTAL;  
113.             imageView.setLayoutParams(params);  
114. "drawable");  
115.             imageView.setImageDrawable(drawable);  
116.         }  
117.     };  
118. }

MainActivity.java

1. package com.custom.textview;  
2.   
3. import java.util.ArrayList;  
4. import java.util.HashMap;  
5.   
6. import android.app.Activity;  
7. import android.os.Bundle;  
8.   
9. public class MainActivity extends Activity {  
10.       
11. private final String text = " <p>  今年浙江卫视凭《中国好声音》一举做大" +  
12. ",其巨大的影响力直接波及到了各家卫视“跨年晚会”的战略部署。日前" +  
13. ",“跨年晚会”概念的鼻祖湖南卫视率先表示“退出跨年烧钱大战”。" +  
14. "但据湖南卫视内部人士透露,即使如此,今年的湖南跨年晚会也将会掂出“跨年季”这个概念" +  
15. ",“也就是从12月27日到12月31日,连续五天,我们将相继用《百变大咖秀》、《快乐大本营》" +  
16. "、《女人如歌》、《天天向上》的特别节目来连续打造这个”季“的概念,直到12月31日的那场晚会。”</p>";  
17.   
18. @Override  
19. public void onCreate(Bundle savedInstanceState) {  
20. super.onCreate(savedInstanceState);  
21.         setContentView(R.layout.main);  
22. // 采集显示内容数据  
23. new ArrayList<HashMap<String,String>>();  
24. new HashMap<String, String>();  
25. "type", "image");  
26. "value", "http://www.linuxidc.com/upload/2012_12/121218101020341.png");  
27. new HashMap<String, String>();  
28. "type", "text");  
29. "value", text);  
30. new HashMap<String, String>();  
31. "type", "image");  
32. "value", "http://www.linuxidc.com/upload/2012_12/121218101020341.png");  
33.         data.add(part1);  
34.         data.add(part2);  
35.         data.add(part3);  
36.           
37.         CustomTextView customTextView = (CustomTextView) findViewById(R.id.textView);  
38.         customTextView.setText(data);  
39.     }  
40. }


三、案例效果展示


android LinearLayout 代码添加view android 自定义linearlayout_xml

 

android LinearLayout 代码添加view android 自定义linearlayout_android_02