Android TextView 元件 框線網底顏色設定範例-01

1 間題

本程式範例是要來設計一個 Android 程式,當使用者輸入完一段文字後,就顯示所輸入的文字是什麼。而顯示的結果要有兩種選擇,一種是「紅框綠底藍字」,另一種是「藍框黃底紅字」。例如:

51-avd-shape01-default.jpg

圖1.1. 程式啟動時的初始畫面。

52-avd-shape01-btn-red.jpg

圖1.2. 點按「顯示輸入結果為紅框綠底藍字」按鈕後的結果。

53-avd-shape01-btn-blue.jpg  

圖1.3. 點按「顯示輸入結果為藍框黃底紅字」的結果畫面。

2 程式設計過程

01-proj-shape01.jpg

圖2.1. 新建一個 Android 應用程式專案名稱為:Shape01

 

02-proj-configure.jpg

圖2.2. 新專案的 Configure 配置設定。預設是要建立 Activity 視窗元件。

 

03-configure-icon.jpg

圖2.3. 建置 Android 程式顯示時的圖示(icon)來源。系統預設會自動建立相關「drawable」開頭的目錄,內存相關的圖示檔案。

 

04-sel-activity.jpg

圖2.4. 預設勾選將要建立一個空白的 Activity 視窗元件。

 

05-SampleShape-activity.jpg

圖2.5. 設定 Activity 視窗的名稱為「SampleShape」,而該 Activity 視窗的元件之配置檔名為「activity_sampe_shape.xml」, 其中 .xml 不用在畫面上輸入。

 

06-default-gui.jpg

圖2.6. 進入 Eclipse 初始編輯 Android 應用程式的畫面。

 

07-new-textview1.jpg

圖2.7. 新增第一個 TextView 元件的 GUI 畫面。

 

08-new-textview1-xml.jpg

圖2.8. 新增第一個 TextView 元件後的 activity_sample_shape.xml 的畫面。

其中,textView2 元件是當建立一個 Android 視窗時,系統主動新增的一個 TextView 元件,用以顯示「Hello World!」。textViw1 元件是現在使用者所新增的 TextView 元件。

 

09-new-textview1-changed-name-xml.jpg

圖2.9. 將原本的兩個 TextView 元件進行更名,以及設定顯示的文字,並且一併修改被別的元件參考時的元件名稱。

當每一增一個 Activity 視窗中的元件時,強烈建議一定要立即到 Activity 的 layout xml 配置檔中來對相關的元件進行改名,以及參考元件的名稱,以便於未來能夠容易閱讀。

 

10-hello_world-xml.jpg

圖2.10. 開啟 values 目錄中的 strings.xml 檔案,以便去修改 hello_world 變數的值。

 

11-hello_world-changed-xml.jpg

圖2.11. strings.xml 中 變數 hello_world 已修改後的結果。

 

 

 

12-changed-gui.jpg

圖2.12. 兩個 TextView 元件修改其顯示值後的結果。

 

13-new-edittext1.jpg

圖2.13. 新增一個 EditText 元件。

 

 

14-new-edittext1-xml.jpg

圖2.14. 新增一個 EditText 元件後,開啟 activtiy_sample_shape.xml 視窗元件配置檔的內容。

15-new-edittext1-changed-xml.jpg

圖2.15. 對所新增的 EditText 元件進行更名。

 

16-new-another-textview-gui.jpg

圖2.16. 新增第二個 TextView 元件。

 

 

 

17-new-another-textview-xml.jpg

圖2.17. 新增的第二個 TextViw 元件於 activity_sample.shape.xml 中的預設值情況。

 

18-new-another-textview-changed-xml.jpg

圖2.18. 對新增的第二個 TextView 元件進行更名與設定要顯示的值。

 

19-new-another-textview-changed-gui.jpg

圖2.19. 新增的第二個 TextView 元件完成更名與設定顯示值後的結果。

 

20-new-another-textview.jpg

圖2.20. 新增第3個 TextView 元件。

 

21-new-another-textview-xml.jpg

圖2.21. 所新增第3 個 TextView 元件於 activity_sample_shape.xml 中的預設值。

 

22-new-another-textview-changed-xml.jpg

圖2.22. 對新增的第三個 TextView 元件進行更名,並設定預設顯示的值為空字串,亦即不顯示任何的值。

 

23-new-another-textview-changed-gui.jpg

圖2.23. 新增的第三個 TextView 元件進行更名與設定顯示值後的結果。

 

24-new-button.jpg

圖2.24. 新增第一個 Button 元件。

 

25-new-button-xml.jpg

圖2.25. 所新增的第一個 Button 元件於 activity_sample.shape.xml 檔案中的預設值。

 

26-new-button-changed-xml.jpg

圖2.26. 對所新增的第一個 Button 元件進行更名與設定顯示的值。

 

27-new-button-changed-gui.jpg

圖2.27. 對新增的第一個 Button 元件更名與設定顯示值後的結果。

 

28-new-another-button.jpg

圖2.28. 新增第二個 Button 元件。

 

 

29-new-another-button-xml.jpg

圖2.29. 所新增的第二個 Button 元件於 activity_sample_shape.xml 中的預設值。

 

30-new-another-button-changed-xml.jpg

圖2.30. 對新增的第二個 Button 元件進行更名與設定顯示的值。

 

31-new-another-button-changed-gui.jpg

圖2.31. 所新增的第二個 Button 元件更名與設定顯示值後的結果。

 

32-no-drawable-dir.jpg

圖2.32. 查核 res 目錄中所存在的 drawable 開頭的子目錄。

在 Android 中,由 drawable 開頭的目錄,其功能是用來存放圖片 (image),圖示 (icon),或是顯示格式 (display format)。其中,顯示格式可以用來設定顯示的框線、網底等。

本問題主要就是要處理與設計使用者自訂的顯示格式。而所設定的顯示格式可以被許多不同類型的元件所共用。因此我們可以在 res 目錄中新增一個名為 「drawable」的子目錄,以存放使用者自的的顯示格式 xml 檔。

 

33-new-folder-menu.jpg

圖2.33. 右點選 res 目錄後,再點按 New 以及 Folder 以進入新建一個目錄的視窗。

 

34-new-folder-drawable.jpg

圖2.34. 設定新建目錄的名稱為 drawable。

 

35-new-folder-drawable-created.jpg

圖2.35. 在 res 目錄中,新增一個名為 drawable 子目錄後的結果。

 

38-new-other-menu.jpg

圖2.36. 右點選 drawable 目錄,再點選 New 以及 Other 以進入進階新增不同類型檔案的視窗。

由於我們要新增的 Android 顯示格式 xml 檔內容必須是 Android 看得懂的顯示格式 xml 檔案格式,所以不可以點按 New 及 File 的方式來建立一個 附檔名為 xml 的檔案,否則會出現錯誤。

 

39-new-other-xml-file.jpg

圖2.37. 選擇要建立的檔案類型為 Android XML File。接著點按 Next 以進行更進階的設定。

 

40-new_box_red.xml.jpg

圖2.38. 設定 Android XML 檔案的名稱為 box_red,其中 .xml 附檔名不用輸入,並選擇 shape 以表示此 xml 檔是用來設定顯示格式。記得不要選錯。

 

41-box_red.xml.jpg

圖2.39. 接著在 res/drawable 階層目錄中開啟 box_red.xml 並按照上圖的內容輸入。box_red.xml 的原始檔案內容如下所示:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <solid android:color="#00ff00"/>
    <corners android:radius="3dp" />
    <padding android:left="10dp" android:top="10dp"
        android:right="10dp" android:bottom="10dp" />
    <stroke android:color="#ff0000" android:width="2dp" />

</shape>

 

其中「<solid android:color="#00ff00"/>」是用來設定網底,#00ff00 是代表綠色。而「<stroke android:color="#ff0000" android:width="2dp" />」是用來設定框線,而 #ff0000 是代表紅色。

有關於 Java 中顏色碼列表,請「參考此處的超連結」來查看。或是利用任何的圖片編輯軟體中設定顏色的功能,就可以去查核到不同顏色的編碼值。

 

42-new_box_blue.xml.jpg

圖2.40. 在 drawable 目錄中新增第二個顯示格式檔 box_blue.xml。

 

43-box_blue.xml.jpg

圖2.41. 新增的 box_blue.xml 的內容。而完整的內容如下所示:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <solid android:color="#ffff4b"/>
    <corners android:radius="3dp" />
    <padding android:left="10dp" android:top="10dp"
        android:right="10dp" android:bottom="10dp" />
    <stroke android:color="#0000ff" android:width="2dp" />

</shape>

 

其中,「<solid android:color="#ffff4b"/>」用以設定網底,#ffff4b代表的是黃色,「<stroke android:color="#0000ff" android:width="2dp" />」用以設定框線,#0000ff 代表紅色。

 

完整的 activity_sample_shape.xml 的檔案內容如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".SampleShape" >

    <TextView
        android:id="@+id/tv_lb_hello"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

    <TextView
        android:id="@+id/tv_lb_keyin_data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/tv_lb_hello"
        android:layout_below="@+id/tv_lb_hello"
        android:layout_marginTop="30dp"
        android:text="請輸入任意的資料:" />

    <EditText
        android:id="@+id/ed_keyin_data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/tv_lb_keyin_data"
        android:layout_alignBottom="@+id/tv_lb_keyin_data"
        android:layout_toRightOf="@+id/tv_lb_keyin_data"
        android:ems="10" >

        <requestFocus />
    </EditText>

    <TextView
        android:id="@+id/tv_lb_output"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/tv_lb_keyin_data"
        android:layout_below="@+id/ed_keyin_data"
        android:layout_marginTop="32dp"
        android:text="您輸入的資料是:" />

    <TextView
        android:id="@+id/tv_msg_output"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/tv_lb_output"
        android:layout_alignBottom="@+id/tv_lb_output"
        android:layout_alignLeft="@+id/ed_keyin_data"
        android:text="" />

    <Button
        android:id="@+id/btn_show_red"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/tv_lb_output"
        android:layout_below="@+id/tv_msg_output"
        android:layout_marginTop="30dp"
        android:text="顯示輸入結果為紅框綠底藍字" />

    <Button
        android:id="@+id/btn_show_blue"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/btn_show_red"
        android:layout_centerVertical="true"
        android:text="顯示輸入結果為藍框黃底紅字" />

</RelativeLayout>

 

接著要進行程式的設計,請點選 scr目錄下的階層目錄,直到看到 SampleShape.java 後,雙擊該檔案以開啟該 java 檔案。並依下面的內容來編輯設程:

package com.example.shape01;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class SampleShape extends Activity {
    
    EditText ed_keyin_data;
    TextView tv_msg_output;
    Button btn_show_red,btn_show_blue;
            
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample_shape);
        doWorks();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.sample_shape, menu);
        return true;
    }
    
    public void doWorks(){
        
        ed_keyin_data = (EditText) findViewById(R.id.ed_keyin_data);
        tv_msg_output = (TextView) findViewById(R.id.tv_msg_output);
        btn_show_red = (Button) findViewById(R.id.btn_show_red);
        btn_show_blue = (Button) findViewById(R.id.btn_show_blue);
                
        btn_show_red.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Drawable box_red = SampleShape.this.getResources().getDrawable(R.drawable.box_red);
                tv_msg_output.setBackgroundDrawable(box_red);
                tv_msg_output.setTextColor(Color.BLUE);
                tv_msg_output.setText(ed_keyin_data.getText().toString());
            }
        });  
        
        Button.OnClickListener btn_show_blue_OnClick =
        new Button.OnClickListener() {
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Drawable box_blue = SampleShape.this.getResources().getDrawable(R.drawable.box_blue);
                tv_msg_output.setBackgroundDrawable(box_blue);
                tv_msg_output.setTextColor(Color.RED);
                tv_msg_output.setText(ed_keyin_data.getText().toString());
            }
        };  
        
        btn_show_blue.setOnClickListener(btn_show_blue_OnClick);
    }
}

 

 其中,import 是用來告訴 Android 會使用到那些元件的 API 函數。

doWorks() 是使用者自訂的函數,用以執行本問題主要的工作。

EditText ed_keyin_data;
TextView tv_msg_output;
Button btn_show_red,btn_show_blue;

 

上述的程式區段主要是用來設定在 Android 程式中的內部變數。

ed_keyin_data = (EditText) findViewById(R.id.ed_keyin_data);
        tv_msg_output = (TextView) findViewById(R.id.tv_msg_output);
        btn_show_red = (Button) findViewById(R.id.btn_show_red);
        btn_show_blue = (Button) findViewById(R.id.btn_show_blue);

 

 上述的程式區段,是用來將內部變數與外部變數 (在 activtiy_sample_shape.xml 檔案中所設定一變數) 進行連結。如此,處理內部變數就等同於處理外部變數。

btn_show_red.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Drawable box_red = SampleShape.this.getResources().getDrawable(R.drawable.box_red);
                tv_msg_output.setBackgroundDrawable(box_red);
                tv_msg_output.setTextColor(Color.BLUE);
                tv_msg_output.setText(ed_keyin_data.getText().toString());
            }
        }); 

 

 上述的程式區段中,「new View.OnClickListener() {... }」是新增一個按下 Click 事件的監聽者,而「public void onClick(View v) {...}」的內容就是設計當按下 Click 時,要如何回應的內容。

Drawable box_red = SampleShape.this.getResources().getDrawable(R.drawable.box_red);」是建立一個 Drawable 物件資料型態的使用者自訂變數 box_red,該指令中,「SampleShape.this.getResources().getDrawable(R.drawable.box_red);」是去讀取 res/drawable/box_red.xml 檔案的內容,而 SampleShape 是指該 Activity 視窗物件的名稱。

tv_msg_output.setBackgroundDrawable(box_red);」是利用 setBackgroundDrawable(box_red) 方法來設定該 tv_msg_output 的 TextView 元件使用 box_red 的顯示格式來顯示網底與框線。

tv_msg_output.setTextColor(Color.BLUE);」是設定以藍色來顯示文字。

 tv_msg_output.setText(ed_keyin_data.getText().toString());」是設定 tv_msg_output 元件的文字內容,成為 ed_keyin_data元件利用getText() 方法取出文字內容後,並利用 toString() 方法轉為字串的結果。

 

Button.OnClickListener btn_show_blue_OnClick =
        new Button.OnClickListener() {
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Drawable box_blue = SampleShape.this.getResources().getDrawable(R.drawable.box_blue);
                tv_msg_output.setBackgroundDrawable(box_blue);
                tv_msg_output.setTextColor(Color.RED);
                tv_msg_output.setText(ed_keyin_data.getText().toString());
            }
        };  
        
        btn_show_blue.setOnClickListener(btn_show_blue_OnClick);

 

上述程式區段,是建立 Click 事件監聽者,並指定該監聽者去監聽那一個特定物件是否發生 Click 事件的另一種方式。其中,「Button.OnClickListener btn_show_blue_OnClick = new Button.OnClickListener() {...}」是利用 new Button.OnClickListener() 方法來建立一個 Button.OnClickListener 物件類型資料型態的使用者自訂變數 btn_show_blue_OnClick。「public void onClick(View v) {...}」的內容就是設計當按下 Click 時,要如何回應的內容,其設計的方式與上上一個程式區段的方式相同。

「 btn_show_blue.setOnClickListener(btn_show_blue_OnClick);」就是將事件監聽者 btn_show_blue_OnClick 專門來監聽 btn_show_blue 該元件是否已發生 Click 的事件。

由上可知,只要是 Android 的元件中,有存在 setBackgroundDrawable() 此一方法時,就可以用上述使用者自訂顯示格式的方式來自訂該元件的顯示框線及網底。程式開發人員應該舉一而反三來應用本範例的程式設計方法。

若是執式執行的過程中,TextView 的框線網底都是保持不變的,因此除了可以採用 setBackgroundDrawable() 的方式來設定框線網底的顯示格式之外,也可以直接在 activtiy_sample_sahpe.xml 的視窗元件配置檔中直接設定,例如:

<TextView
        android:id="@+id/tv_msg_output"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/tv_lb_output"
        android:layout_alignBottom="@+id/tv_lb_output"
        android:layout_alignLeft="@+id/ed_keyin_data"
        android:text=""
        android:backgrdound="@drawable/box_blue" />

 

亦即,在 TextView 元件中,多加了一行 「android:backgrdound="@drawable/box_blue"」將其背景設為自定的 box_blue.xml 中所設定的顯示格式。

而 EditText 元件也可以在 activity_sample_shape.xml 中同樣多加了上述那一行來設定其背景。

但若是要更改整個手機螢幕的背景,則是要去設定 <RelativeLayout ... />的 Layout 類型的標簽中來多加上述那一行的指令。例如,

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:background="@drawable/box_blue" >

 

44-avd-manager-memu.jpg

圖2.42. 點按 Window/Andriod Virtual Device Manager 以開啟 AVD管理視窗。

 

45-avd-manager.jpg

圖2.43. AVD 管理視窗。請點按已建立的存在的其中一個虛擬手機設備,並點按 Start 以開啟該虛擬手機。

 

46-avd-lunch-option.jpg

圖2.44. 設定要開啟虛擬手機時的設定。

 

47-avd-started.jpg

圖2.45. 進入虛擬手機時,可能會出現要要解鎖的畫面。請點按該鎖後,拖曳至右方的聲音圖示以解鎖。

 

48-avd-unlocked.jpg

圖2.46. 虛擬手機開機完成後的預設畫面。

 

49-shape01-run-as.jpg

圖2.47. 在 Eclipse 中,右點按 Shape01 專案名稱後,再選擇 Run As,以及 選擇 Android Application,以將 Android 的程式上傳至已經開啟的虛擬手機或是真實手機。

 

50-avd-auto-monitor-logchat.jpg

圖2.48. 用以設定是否要在 Eclipse 視窗中,同步顯示在執行虛擬手機時的系統訊息。請點按 OK。

 

51-avd-shape01-default.jpg

圖2.49. 程式啟動時的初始畫面。

 

52-avd-shape01-btn-red.jpg

圖2.50. 點按「顯示輸入結果為紅框綠底藍字」按鈕後的結果。

 

53-avd-shape01-btn-blue.jpg

圖2.51. 點按「顯示輸入結果為藍框黃底紅字」的結果畫面。

 

54-avd-shape01-stop-unexpectedly.jpg  

圖2.52. 執行虛擬手機時發生錯誤的畫面。

上圖是 Android 程式開發人員在測試程時時可能會發生的錯誤情況。例如將下面原本正確的指令碼

btn_show_red.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Drawable box_red = SampleShape.this.getResources().getDrawable(R.drawable.box_red);
                tv_msg_output.setBackgroundDrawable(box_red);
                tv_msg_output.setTextColor(Color.BLUE);
                tv_msg_output.setText(ed_keyin_data.getText().toString());
            }
        }); 

 

 改為,將「 Drawable box_red = SampleShape.this.getResources().getDrawable(R.drawable.box_red);」該行指令放置在別的地方,例如在「public class SampleShape extends Activity {...}」的正下方,成為

EditText ed_keyin_data;
TextView tv_msg_output;
Button btn_show_red,btn_show_blue;

Drawable box_red = SampleShape.this.getResources().getDrawable(R.drawable.box_red);

 

 如此就會在啟動虛擬手機時發生上述的錯誤情況。

當啟動虛擬手機就立即發生錯誤情況時,是最麻煩的一件事,因為在 Eclipse 編輯畫面中並沒有出現邏輯上的錯誤,因此也無法立即得知那裏出錯,所以,只好去查核系統在執行過程中的系統內部運作方式來找出此一 Runtime 的錯誤了。

arrow
arrow

    xx3d2ybnf 發表在 痞客邦 留言(0) 人氣()