第五章 用戶界面基礎(chǔ)(TextView的使用)

參考資料:
《Android應(yīng)用程序開發(fā)》ISBN 9787302283164
參考軟件:
Android Studio、Eclipse+ADT、Android SDK、JDK
用戶界面基礎(chǔ)
用戶界面(User Interface,UI)是系統(tǒng)和用戶之間進(jìn)行信息交換的媒介,實(shí)現(xiàn)信息的內(nèi)部形式與人類可以接受形式之間的轉(zhuǎn)換
在計(jì)算機(jī)出現(xiàn)早期,批處理界面(1945-1968)和命令行界面(1969-1983)得到廣泛的使用
目前,流行圖像用戶界面(Graphical User Interface,GUI),采用圖形方式與用戶進(jìn)行交互的界面
未來的用戶界面將更多的運(yùn)用虛擬現(xiàn)實(shí)技術(shù),使用戶能夠擺脫鍵盤與鼠標(biāo)的交互方式,而通過動(dòng)作、語言,甚至是腦電波來控制計(jì)算機(jī)
?一、Android用戶界面框架
Android用戶界面框架采用MVC(Model-View-Controller)模型
控制器(Controller)處理用戶輸入
視圖(View)顯示用戶界面和圖像
模型(Model)保存數(shù)據(jù)和代碼
?

*?圖取自網(wǎng)絡(luò),MVC模型
Android用戶界面框架采用視圖樹(View Tree)模型
由View和ViewGroup構(gòu)成

*圖取自網(wǎng)絡(luò),View Tree模型
?二、TextView
常見屬性
?android:autoLink設(shè)置是否當(dāng)文本為URL鏈接/email/電話號(hào)碼/map時(shí),文本顯示為可點(diǎn)擊的鏈接。可選值(none/web/email/phone/map/all)
android:autoText如果設(shè)置,將自動(dòng)執(zhí)行輸入值的拼寫糾正。此處無效果,在顯示輸入法并輸入的時(shí)候起作用。
android:bufferType指定getText()方式取得的文本類別。選項(xiàng)editable?類似于StringBuilder可追加字符,也就是說getText后可調(diào)用append方法設(shè)置文本內(nèi)容。spannable?則可在給定的字符區(qū)域使用樣式,參見這里1、這里2。
android:capitalize設(shè)置英文字母大寫類型。此處無效果,需要彈出輸入法才能看得到,參見EditView此屬性說明。
android:cursorVisible設(shè)定光標(biāo)為顯示/隱藏,默認(rèn)顯示。
android:digits設(shè)置允許輸入哪些字符。如“1234567890.+-*/%?()”
android:drawableBottom在text的下方輸出一個(gè)drawable,如圖片。如果指定一個(gè)顏色的話會(huì)把text的背景設(shè)為該顏色,并且同時(shí)和background使用時(shí)覆蓋后者。
android:drawableLeft在text的左邊輸出一個(gè)drawable,如圖片。
android:drawablePadding設(shè)置text與drawable(圖片)的間隔,與drawableLeft、drawableRight、drawableTop、drawableBottom一起使用,可設(shè)置為負(fù)數(shù),單獨(dú)使用沒有效果。
android:drawableRight在text的右邊輸出一個(gè)drawable,如圖片。
android:drawableTop在text的正上方輸出一個(gè)drawable,如圖片。
android:editable設(shè)置是否可編輯。這里無效果,參見EditView。
android:editorExtras設(shè)置文本的額外的輸入數(shù)據(jù)。在EditView再討論。
android:ellipsize設(shè)置當(dāng)文字過長(zhǎng)時(shí),該控件該如何顯示。有如下值設(shè)置:”start”—?省略號(hào)顯示在開頭;”end”——省略號(hào)顯示在結(jié)尾;”middle”—-省略號(hào)顯示在中間;”marquee”?——以跑馬燈的方式顯示(動(dòng)畫橫向移動(dòng))
android:freezesText設(shè)置保存文本的內(nèi)容以及光標(biāo)的位置。參見:這里。
android:gravity設(shè)置文本位置,如設(shè)置成“center”,文本將居中顯示。
android:hintText為空時(shí)顯示的文字提示信息,可通過textColorHint設(shè)置提示信息的顏色。此屬性在EditView中使用,但是這里也可以用。
android:imeOptions附加功能,設(shè)置右下角IME動(dòng)作與編輯框相關(guān)的動(dòng)作,如actionDone右下角將顯示一個(gè)“完成”,而不設(shè)置默認(rèn)是一個(gè)回車符號(hào)。這個(gè)在EditView中再詳細(xì)說明,此處無用。
android:imeActionId設(shè)置IME動(dòng)作ID。在EditView再做說明,可以先看這篇帖子:這里。
android:imeActionLabel設(shè)置IME動(dòng)作標(biāo)簽。在EditView再做說明。
android:includeFontPadding設(shè)置文本是否包含頂部和底部額外空白,默認(rèn)為true。
android:inputMethod為文本指定輸入法,需要完全限定名(完整的包名)。例如:com.google.android.inputmethod.pinyin,但是這里報(bào)錯(cuò)找不到。
android:inputType設(shè)置文本的類型,用于幫助輸入法顯示合適的鍵盤類型。在EditView中再詳細(xì)說明,這里無效果。
android:linksClickable設(shè)置鏈接是否點(diǎn)擊連接,即使設(shè)置了autoLink。
android:marqueeRepeatLimit在ellipsize指定marquee的情況下,設(shè)置重復(fù)滾動(dòng)的次數(shù),當(dāng)設(shè)置為marquee_forever時(shí)表示無限次。
android:ems設(shè)置TextView的寬度為N個(gè)字符的寬度。這里測(cè)試為一個(gè)漢字字符寬度,如圖:
android:maxEms設(shè)置TextView的寬度為最長(zhǎng)為N個(gè)字符的寬度。與ems同時(shí)使用時(shí)覆蓋ems選項(xiàng)。
android:minEms設(shè)置TextView的寬度為最短為N個(gè)字符的寬度。與ems同時(shí)使用時(shí)覆蓋ems選項(xiàng)。
android:maxLength限制顯示的文本長(zhǎng)度,超出部分不顯示。
android:lines設(shè)置文本的行數(shù),設(shè)置兩行就顯示兩行,即使第二行沒有數(shù)據(jù)。
android:maxLines設(shè)置文本的最大顯示行數(shù),與width或者layout_width結(jié)合使用,超出部分自動(dòng)換行,超出行數(shù)將不顯示。
android:minLines設(shè)置文本的最小行數(shù),與lines類似。
android:lineSpacingExtra設(shè)置行間距。
android:lineSpacingMultiplier設(shè)置行間距的倍數(shù)。如”1.2”
android:numeric如果被設(shè)置,該TextView有一個(gè)數(shù)字輸入法。此處無用,設(shè)置后唯一效果是TextView有點(diǎn)擊效果,此屬性在EdtiView將詳細(xì)說明。
android:password以小點(diǎn)”.”顯示文本
android:phoneNumber設(shè)置為電話號(hào)碼的輸入方式。
android:privateImeOptions設(shè)置輸入法選項(xiàng),此處無用,在EditText將進(jìn)一步討論。
android:scrollHorizontally設(shè)置文本超出TextView的寬度的情況下,是否出現(xiàn)橫拉條。
android:selectAllOnFocus如果文本是可選擇的,讓他獲取焦點(diǎn)而不是將光標(biāo)移動(dòng)為文本的開始位置或者末尾位置。TextView中設(shè)置后無效果。
android:shadowColor指定文本陰影的顏色,需要與shadowRadius一起使用。效果:
android:shadowDx設(shè)置陰影橫向坐標(biāo)開始位置。
android:shadowDy設(shè)置陰影縱向坐標(biāo)開始位置。
android:shadowRadius設(shè)置陰影的半徑。設(shè)置為0.1就變成字體的顏色了,一般設(shè)置為3.0的效果比較好。
android:singleLine設(shè)置單行顯示。如果和layout_width一起使用,當(dāng)文本不能全部顯示時(shí),后面用“…”來表示。如android:text="test_?singleLine?"?android:singleLine="true"?android:layout_width="20dp"將只顯示“t…”。如果不設(shè)置singleLine或者設(shè)置為false,文本將自動(dòng)換行
android:text設(shè)置顯示文本.
android:shadowDx設(shè)置陰影橫向坐標(biāo)開始位置。
android:shadowDy設(shè)置陰影縱向坐標(biāo)開始位置。
android:shadowRadius設(shè)置陰影的半徑。設(shè)置為0.1就變成字體的顏色了,一般設(shè)置為3.0的效果比較好。
android:singleLine設(shè)置單行顯示。如果和layout_width一起使用,當(dāng)文本不能全部顯示時(shí),后面用“…”來表示。如android:text="test_?singleLine?"?android:singleLine="true"?android:layout_width="20dp"將只顯示“t…”。如果不設(shè)置singleLine或者設(shè)置為false,文本將自動(dòng)換行
android:text設(shè)置顯示文本.
android:textSize設(shè)置文字大小,推薦度量單位”sp”,如”15sp”
android:textStyle設(shè)置字形[bold(粗體)?0,?italic(斜體)?1,?bolditalic(又粗又斜)?2]?可以設(shè)置一個(gè)或多個(gè),用“|”隔開
android:typeface設(shè)置文本字體,必須是以下常量值之一:normal?0,?sans?1,?serif?2,?monospace(等寬字體)?3]
android:height設(shè)置文本區(qū)域的高度,支持度量單位:px(像素)/dp/sp/in/mm(毫米)
android:maxHeight設(shè)置文本區(qū)域的最大高度
android:minHeight設(shè)置文本區(qū)域的最小高度
android:width設(shè)置文本區(qū)域的寬度,支持度量單位:px(像素)/dp/sp/in/mm(毫米),與layout_width的區(qū)別看這里。
android:maxWidth設(shè)置文本區(qū)域的最大寬度
android:minWidth設(shè)置文本區(qū)域的最小寬度
android:textAppearance設(shè)置文字外觀。如“?android:attr/textAppearanceLargeInverse”這里引用的是系統(tǒng)自帶的一個(gè)外觀,?表示系統(tǒng)是否有這種外觀,否則使用默認(rèn)的外觀。
可設(shè)置的值如下:
textAppearanceButton/textAppearanceInverse/textAppearanceLarge/textAppearanceLargeInverse/textAppearanceMedium/textAppearanceMediumInverse/textAppearanceSmall/textAppearanceSmallInverse
android:textAppearance設(shè)置文字外觀。如“?android:attr/textAppearanceLargeInverse”這里引用的是系統(tǒng)自帶的一個(gè)外觀,?表示系統(tǒng)是否有這種外觀,否則使用默認(rèn)的外觀。
可設(shè)置的值如下:
textAppearanceButton、textAppearanceInverse、textAppearanceLarge、textAppearanceLargeInverse、textAppearanceMedium、textAppearanceMediumInverse
常用代碼
1、讓一個(gè)TextView中的關(guān)鍵字高亮顯示
public?void?highlight(String target){??
??????? String temp=getText().toString();??
??????? SpannableStringBuilder spannable =?new?SpannableStringBuilder(temp);??
??????? CharacterStyle span=null;??
??????????
??????? Pattern p = Pattern.compile(target);??
??????? Matcher m = p.matcher(temp);??
????????while?(m.find()) {??
??????????? span =?new?ForegroundColorSpan(Color.RED);//需要重復(fù)!????????? //span = new ImageSpan(drawable,ImageSpan.XX);//設(shè)置現(xiàn)在圖片??????????? spannable.setSpan(span, m.start(), m.end(),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);??
??????? }??
??????? setText(spannable);??
??? }
?2、顯示富文本
通過第一個(gè)例子來講解一下TextView使用HTML標(biāo)簽設(shè)定樣式和通過autoLink屬性來設(shè)置超鏈接效果,在XML布局文件中定義兩個(gè)TextView,分別展示HTML標(biāo)簽和autoLink屬性的使用。
XML布局文件textviewdemo.xml代碼:
?1<?xml version="1.0"encoding="utf-8"?>
?2<LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"
?3????android:layout_width="match_parent"
?4????android:layout_height="match_parent"
?5????android:orientation="vertical">???
?6?????<TextView
?7?????????android:id="@+id/textView1"
?8????????android:layout_width="fill_parent"
?9????????android:layout_height="wrap_content"
10????????android:padding="20sp"
11????????/>
12?????<TextView
13????????android:id="@+id/textView2"
14????????android:layout_width="fill_parent"
15????????android:layout_height="wrap_content"
16????????android:padding="20sp"
17????????android:autoLink="all"
18????????android:textSize="20sp"
19????????/>
20</LinearLayout>
Activity文件textViewDemoActivity.java代碼:
?1package?cn.bgxt.textviewdemo;
?2
?3import?android.app.Activity;
?4import?android.os.Bundle;
?5import?android.text.Html;
?6import?android.text.method.LinkMovementMethod;
?7import?android.widget.TextView;
?8
?9publicclass?textViewDemoActivity?extends?Activity {
10
11?????private?TextView textView1,textView2;
12?????public?textViewDemoActivity() {
13????????// TODOAuto-generated constructor stub
14????}???
15????@Override
16?????protectedvoid?onCreate(Bundle savedInstanceState) {
17????????// TODOAuto-generated method stub
18????????super.onCreate(savedInstanceState);
19????????setContentView(R.layout.textviewdemo);
20????????//通過Id獲得兩個(gè)TextView控件
21????????textView1=(TextView)findViewById(R.id.textView1);
22????????textView2=(TextView)findViewById(R.id.textView2);
23????????
24????????//設(shè)置需要顯示的字符串
25????????String html="<font color ='red'>Helloandroid</font><br/>";
26????????html+="<font color='#0000ff'><big><i>Helloandroid</i></big></font><p>";
27????????html+="<big><a href='http://www.baidu.com'>百度</a></big>";
28????????//使用Html.fromHtml,把含HTML標(biāo)簽的字符串轉(zhuǎn)換成可顯示的文本樣式
29????????CharSequence charSequence=Html.fromHtml(html);
30????????//通過setText給TextView賦值
31????????textView1.setText(charSequence);
32????????//設(shè)定一個(gè)點(diǎn)擊的響應(yīng)
33????????textView1.setMovementMethod(LinkMovementMethod.getInstance());
34????????
35????????String text="我的URL:http://www.cnblogs.com/plokmju/\n";
36????????text+="我的email:plokmju@sina.com\n";
37????????text+="我的電話:+86 010-12345678";
38????????//因?yàn)閠extView2中有autoLink=”all“的屬性設(shè)定,所以會(huì)自動(dòng)識(shí)別對(duì)應(yīng)的連接,點(diǎn)擊出發(fā)對(duì)應(yīng)的Android程序
39????????textView2.setText(text);
40???? }
41
42?}
顯示效果:

3、TextView顯示圖片
在TextView中顯示圖片的例子,依然是使用HTML標(biāo)簽的方式定義樣式,但是使用的是Html.fromHtml()的另外一個(gè)重載的靜態(tài)方法,可以設(shè)定<img>標(biāo)簽中的圖像資源。
static Spanned fromHtml(Stringsource,Html.ImageGetter imageGetter,Html.TagHandler tagHandler)
對(duì)于這個(gè)方法,在imageGetter參數(shù)中設(shè)定<img>標(biāo)簽中的圖像資源文件,tagHandler主要是為了處理Html類無法識(shí)別的html標(biāo)簽的情況,一般不會(huì)用上,傳值為null即可。
布局XML文件textvideforimg.xml代碼:?
?1<?xml version="1.0"encoding="utf-8"?>
?2<LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"
?3????android:layout_width="match_parent"
?4????android:layout_height="match_parent"
?5????android:orientation="vertical">
?6?????<TextView
?7?????????android:id="@+id/textImg"
?8????????android:layout_width="fill_parent"
?9????????android:layout_height="match_parent"
10????????android:layout_margin="10dp"/>
11</LinearLayout>
Activity文件textviewForImgActivity.java代碼:
?1package?cn.bgxt.textviewdemo;
?2
?3import?java.lang.reflect.Field;
?4
?5import?android.R.color;
?6import?android.app.Activity;
?7import?android.graphics.drawable.Drawable;
?8import?android.os.Bundle;
?9import?android.text.Html;
10import?android.text.Html.ImageGetter;
11import?android.text.method.LinkMovementMethod;
12import?android.widget.TextView;
13
14publicclass?textviewForImgActivity?extends?Activity? {
15
16?????private?TextView textViewImg;
17?????public?textviewForImgActivity() {
18????????// TODOAuto-generated constructor stub
19???? }
20????
21???? @Override
22?????protectedvoid?onCreate(Bundle savedInstanceState) {
23????????// TODOAuto-generated method stub
24????????super.onCreate(savedInstanceState);
25????????setContentView(R.layout.textvideforimg);
26????????
27????????textViewImg=(TextView)findViewById(R.id.textImg);
28????????textViewImg.setTextColor(color.white);
29????????textViewImg.setBackgroundColor(color.black);
30????????textViewImg.setTextSize(20);
31????????//設(shè)定HTML標(biāo)簽樣式,圖片3為一個(gè)超鏈接標(biāo)簽a
32????????String html="圖像1<imgsrc='image1'/>圖像2<img src='image2'/>\n";
33????????html+="圖像3<ahref='http://www,baidu.com'><img src='image3'/></a>";
34????????//fromHtml中ImageGetter選擇html中<img>的圖片資源
35????????CharSequence cs=Html.fromHtml(html,?newImageGetter() {
36????????????
37????????????publicDrawable getDrawable(String source) {
38?????????????????//source為html字符串中定義的<img>中的src的內(nèi)容
39?????????????????//返回值Drawable就是對(duì)應(yīng)的<img>顯示的圖片資源
40???????????????? Drawable draw=null;
41?????????????????if(source.equals("image1"))
42???????????????? {
43????????????????????draw=getResources().getDrawable(R.drawable.image1);
44???????????????????? draw.setBounds(0, 0,draw.getIntrinsicWidth(), draw.getIntrinsicHeight());
45???????????????? }
46?????????????????elseif(source.equals("image2"))
47????? ???????????{
48?????????????????????//設(shè)定image2尺寸等比縮小
49????????????????????draw=getResources().getDrawable(R.drawable.image2);
50???????????????????? draw.setBounds(0, 0,draw.getIntrinsicWidth()/2, draw.getIntrinsicHeight()/2);
51???????????????? }
52?? ??????????????else
53???????????????? {
54?????????????????????//使用反射會(huì)更簡(jiǎn)便,無需知道src與資源Id的對(duì)應(yīng)關(guān)系
55????????????????????draw=getResources().getDrawable(getResourceId(source));
56???????????????????? draw.setBounds(0, 0,draw.getIntrinsicWidth(), draw.getIntrinsicHeight());
57???????????????? }
58?????????????????return?draw;
59????????????}
60????????},?null);
61????????textViewImg.setText(cs);
62????????textViewImg.setMovementMethod(LinkMovementMethod.getInstance());
63???? }
64????
65?????publicint?getResourceId(String source)
66???? {
67????????try?{
68????????????//使用反射機(jī)制,通過屬性名稱,得到其內(nèi)的值
69????????????Field field=R.drawable.class.getField(source);
70????????????return?Integer.parseInt(field.get(null).toString());
71????????}?catch?(Exception e) {
72????????????// TODO: handleexception
73????????}
74????????return?0;
75???? }
76????
77?}
效果截圖,其中第三個(gè)圖片點(diǎn)擊會(huì)觸發(fā)瀏覽器訪問百度網(wǎng)址:

?
4、在TextView增加Click事件
在TextView添加點(diǎn)擊事件,導(dǎo)航到其他的Activity中。使用SpannableString.setSpan()設(shè)定那一段文本需要相應(yīng)點(diǎn)擊事件。與之類似的還有SpannableBuilder對(duì)象,他們的關(guān)系和String與StringBuilder一樣。
void setSpan(Object what,int start,intend,int flags)
在what參數(shù)中傳遞一個(gè)抽象類ClickableSpan,需要實(shí)現(xiàn)其onClick()方法,此為指定文本的點(diǎn)擊相應(yīng)時(shí)間。start和end分別指定需要響應(yīng)onClick()方法的文本開始與結(jié)束。flags設(shè)定一個(gè)標(biāo)識(shí),確定使用什么方式選擇文本塊,一般使用Spanned接口下的SPAN_EXCLUSIVE_EXCLUSIVE對(duì)其進(jìn)行賦值,表示遵循設(shè)定的開始于結(jié)束位置的文本塊。
布局文件activityclick.xml的代碼:
?1<?xml version="1.0"encoding="utf-8"?>
?2<LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"
?3????android:layout_width="match_parent"
?4????android:layout_height="match_parent"
?5????android:orientation="vertical">
?6?????<TextView
?7?????????android:id="@+id/clickTextView1"
?8????????android:textSize="30dp"
?9????????android:layout_marginTop="30dp"
10????????android:layout_width="match_parent"
11????????android:layout_height="wrap_content"/>
12?????<TextView
13?????????android:textSize="30dp"
14?????????android:layout_marginTop="30dp"
15????????android:id="@+id/clickTextView2"
16????????android:layout_width="match_parent"
17????????android:layout_height="wrap_content"/>
18</LinearLayout>
Activity文件TextViewOnClickActivity.java的代碼:
?1package?cn.bgxt.textviewdemo;
?2
?3import?android.app.Activity;
?4import?android.content.Intent;
?5import?android.os.Bundle;
?6import?android.text.SpannableString;
?7import?android.text.Spanned;
?8import?android.text.method.LinkMovementMethod;
?9import?android.text.style.ClickableSpan;
10import?android.view.View;
11import?android.widget.TextView;
12
13publicclass?TextViewOnClickActivity?extends?Activity {
14
15?????private?TextView clickTextView1,clickTextView2;
16????
17?????public?TextViewOnClickActivity() {
18???? }
19
20????@Override
21?????protectedvoid?onCreate(Bundle savedInstanceState) {
22????????super.onCreate(savedInstanceState);
23????????setContentView(R.layout.activityclick);
24? ???????
25????????clickTextView1=(TextView)this.findViewById(R.id.clickTextView1);
26????????clickTextView2=(TextView)this.findViewById(R.id.clickTextView2);
27????????String text1="顯示Activity1";
28????????String text2="顯示Activity2";
29????????//使用SpannableString存放字符串
30????????SpannableString spannableString=newSpannableString(text1);
31????????SpannableString spannableString2=newSpannableString(text2);
32????????//通過setSpan設(shè)定文本塊響應(yīng)的點(diǎn)擊事件
33????????//此處只設(shè)定文本的索引為2開始的文本塊:Activity1
34????????spannableString.setSpan(new?ClickableSpan() {???????????
35????????????@Override
36????????????publicvoid?onClick(View widget) {
37?????????????????//導(dǎo)航到一個(gè)新的 Activity1中
38???????????????? Intent intent=newIntent(TextViewOnClickActivity.this,Activity1.class);
39???????????????? startActivity(intent);
40????????????}
41????????}, 2, text1.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
42????????
43????????spannableString2.setSpan(new?ClickableSpan() {
44????????????
45????????????@Override
46????????????publicvoid?onClick(View widget) {
47?????????????????// TODO Auto-generated method stub
48???????????????? Intent intent=newIntent(TextViewOnClickActivity.this,Activity2.class);
49???????????????? startActivity(intent);
50????????????}
51????????}, 2, text1.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
52????????
53????????//對(duì)TextView文本進(jìn)行賦值
54????????clickTextView1.setText(spannableString);
55????????//設(shè)置點(diǎn)擊響應(yīng)
56????????clickTextView1.setMovementMethod(LinkMovementMethod.getInstance());
57????? ???clickTextView2.setText(spannableString2);
58????????clickTextView2.setMovementMethod(LinkMovementMethod.getInstance());
59????????
60????????
61????????
62???? }
63?}
效果圖,從圖中可以看出只有點(diǎn)擊setSpan中設(shè)定的代碼塊才可以觸發(fā)點(diǎn)擊事件:

??5、一些小技巧
http://blog.csdn.net/hero_zhouwu/article/details/9705647