Android基礎知識(1)——UI編程

閱讀前,請瀏覽此處上方目錄。

Android UI編程

本章內容爲個人筆記,參考書籍有:《瘋狂的android》第3版、《第一行代碼》

———————————————————————————————————————————————————

  在學校裏聽老師講課,總會讓學生誤會程序員的主要工作不是界面美化,那都是美工做得事情。但隨着移動開發的不斷髮展,在軟件開發的過程中,界面設計和功能開發同樣重要。界面美觀的應用不僅可以大大增加用戶粘性,還可以幫我們吸引更多新用戶。如果善用UI控件,可以做出讓人賞心悅目的應用。

  Android應用絕大部分UI組件都放在android.widget包及其子包、android.view包及其子包中,Android應用的所有UI都繼承了View類。View類還有一個重要的子類,ViewGroup,但ViewGroup通常作爲其他組件其他組件的容器使用。Android的所有UI組件都是建在View、ViewGroup基礎之上,ViewGroup是View的子類,因此ViewGroup也可以被當成View使用。但由於ViewGroup是一個抽象類,因此實際使用中通常總是使用ViewGroup的子類來作爲容器,例如各種佈局管理器。



1、佈局管理器

  1.1 LinearLayout 線性佈局

  LinearLayout  是最常用的佈局,它會把容器裏面的組件一個挨一個的排列起來,LinearLayout 可以控制各組件橫縱向排列(通過android:orientation屬性控制)。設置排列方式可以設置爲 android:orientation="vertical" (垂直排列),android:orientation="horizontal"(水平排列)。還有一個XML屬性是 android:gravity對齊方式,有很對齊方式。學習LinearLayout還有另外一個重要屬性android:layout_weight,這個屬性允許我們使用比例方式來指定控件的大小,在手機屏幕適配性方面起到非常重要的作用。

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="right"
    android:orientation="vertical">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="按鈕" />
</LinearLayout>


  1.2 TableLayout  表格佈局

TableLayout繼承了LinearLayout,因此它的本質依然是線性佈局管理器。表格佈局採用行、列的形式來管理UI組件,TableLayout並不需要明確聲明包含多少行多少列,而是通過添加TableRow來控制表格的行數和列數。每次向TableLayout中添加一個TableRow,該TableRow就是一個表格行。接下來示範:

    <TableRow>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="按鈕1" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="按鈕2" />
    </TableRow>
    <TableRow>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="按鈕3" />
    </TableRow>
</TableLayout>


TableLayout 還有三個屬性需要認知,

  • android:collapseColumns(設置需要被隱藏列序號)
  • android:shrinkColumns(設置需要被收縮列序號)
  • android:stretchColumns(設置需要被拉伸列序號)


    1.3 FrameLayout  幀佈局

FrameLayout  相對於其他佈局管理器來說比較簡單,但應用的場景也減少。FrameLayout直接繼承了ViewGroup組件,爲每個加入其中的組件創建一個空白區域,把組件一個個地疊加在一起。

 <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="New Button"
            android:id="@+id/button" />
        <ImageButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/a4"/>
    </FrameLayout>

顯然兩個組件重疊在左上角,這種佈局可能用到的地方可以不多。


  1.4 RelativeLayout相對佈局

RelativeLayout也是一種比較常用佈局,相對佈局容器內子組件的位置總是相對於兄弟組件、父容器來決定的,因此這種佈局方式被稱爲相對佈局。

以下是隻能設爲boolean值得屬性:

android:layout_centerHorizontal
控制該子組件是否位於佈局容器的水平居中
android:layout_centerVertical
控制該子組件是否位於佈局容器的垂直居中
android:layout_centerInParent
控制該子組件是否位於佈局容器的中央位置
android:layout_alignParentTop 控制該子組件是否與佈局容器頂端對齊
android:layout_alignParentBottom 控制該子組件是否與佈局容器低端對齊
android:layout_alignParentLeft 控制該子組件是否與佈局容器左端對齊
android:layout_alignParentRight 控制該子組件是否與佈局容器右邊對齊
以下只能設爲其他UI組件ID的屬性:
android:layout_above 控制該子組件位於給出ID組件的上方
android:layout_below 控制該子組件位於給出ID組件的下方
android:layout_toLeftOf 控制該子組件位於給出ID組件的左側
android:layout_toRightOf
控制該子組件位於給出ID組件的右側
android:layout_alighTop 控制該子組件與給出ID組件的上邊界對齊
android:layout_alighBottom
控制該子組件與給出ID組件的下邊界對齊
android:layout_alighLeft 控制該子組件與給出ID組件的左邊界對齊
android:layout_alighRight
控制該子組件與給出ID組件的右邊界對齊
【實例】梅花布局效果:

 <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <!--定義按鈕Bt1位於父容器中間-->
        <Button
            android:id="@+id/bt1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="按鈕1" />
        <!--定義Bt2位於按鈕Bt1上方-->
        <Button  
            android:id="@+id/bt2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_above="@id/bt1"
            android:layout_alignLeft="@id/bt1"
            android:text="按鈕2" />
        <!--定義Bt3位於按鈕Bt1下方-->
        <Button
            android:id="@+id/bt3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/bt1"
            android:layout_alignLeft="@id/bt1"
            android:text="按鈕3" />
        <!--定義Bt4位於按鈕Bt1左方-->
        <Button
            android:id="@+id/bt4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toLeftOf="@id/bt1"
            android:layout_alignTop="@id/bt1"
            android:text="按鈕4" />
        <!--定義Bt2位於按鈕Bt1右方-->
        <Button
            android:id="@+id/bt5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignTop="@id/bt1"
            android:layout_toRightOf="@id/bt1"
            android:text="按鈕5" />
    </RelativeLayout>

  1.5 GridLayout  網格佈局

GridLayout的作用類似於HTML中的Table標籤,它把整個容器劃分成rows*columns個網格,每個網格可以放置一個組件。除此之外也可以設置一個組件橫跨多少列、縱跨多少行。

首先要說的是GridLayout與LinearLayout佈局一樣,也分爲水平和垂直兩種方式,默認是水平佈局:

android:orientation horizontal  水平
vertical 垂直

第二就是GridLayout的屬性:

android:rowCount 設置該網格的列數量
android:columnCount 設置該網格的行數量
android:layout_rowSpan 設置該子組件在容器縱跨幾行
android:layout_columnSpan 設置該子組件在容器橫跨幾行

【實例】計算器界面:

<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:columnCount="4"
    android:orientation="horizontal"
    android:rowCount="6">

    <TextView
        android:layout_columnSpan="4"
        android:layout_gravity="fill"
        android:background="#000"
        android:gravity="right"
        android:text="0"
        android:textColor="#fff"
        android:textSize="80dp" />
    <Button
        android:id="@+id/bt1"
        android:text="AC" />
    <Button
        android:id="@+id/bt2"
        android:text="+/-" />
    <Button
        android:id="@+id/bt3"
        android:text="%" />
    <Button
        android:id="@+id/bt4"
        android:text="+" />
    <Button
        android:id="@+id/bt5"
        android:text="7" />
    <Button
        android:id="@+id/bt6"
        android:text="8" />
    <Button
        android:id="@+id/bt7"
        android:text="9" />
    <Button
        android:id="@+id/bt8"
        android:text=" - " />
    <Button
        android:id="@+id/bt9"
        android:text="4" />
    <Button
        android:id="@+id/bt10"
        android:text="5" />
    <Button
        android:id="@+id/bt11"
        android:text="6" />
    <Button
        android:id="@+id/bt12"
        android:text="*" />
    <Button
        android:id="@+id/bt13"
        android:text="1" />
    <Button
        android:id="@+id/bt14"
        android:text="2" />
    <Button
        android:id="@+id/bt15"
        android:text="3" />
    <Button
        android:id="@+id/bt16"
        android:text="/" />
    <Button
        android:id="@+id/bt17"
        android:layout_columnSpan="2"
        android:layout_gravity="fill"
        android:text="0" />
    <Button
        android:id="@+id/bt18"
        android:text="." />
    <Button
        android:id="@+id/bt19"
        android:text="=" />
</GridLayout>
當0需要橫跨2列時

        android:layout_columnSpan="2"
        android:layout_gravity="fill"

  1.6 AbsoluteLayout絕對佈局

       AbsoluteLayout絕對佈局猶如div指定了absolute屬性,用X,Y座標來指定元素的位置!
  該佈局目前已經淘汰,知道就行了!
-----------------------------------------------------

2、常用控件的使用方法

  2.1 TextView文本框

TextView是Android中最簡單的控件,它主要用於界面顯示一段文本信息,有點類似Swing編程中的JLabel,但又比JLabel強大。還有些 樣式、文本轉換autoLink和autoText、文本超長ellipsize等等不一一多說。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Text" />
</LinearLayout>

  

  2.2 EditText編輯框

  EditText 是程序中用於和用戶進行交互十分重要的控件,它允許用戶在控件裏輸入和編輯內容,應用的場景最常見就是輸入賬號密碼。

  EditText 與 TextView非常相似,他甚至與TextView共用了絕大部分XML屬性和方法,他們之間最大的區別就是:EditText 可以接受用戶的輸入。

  • android:hint:指定編輯框的提示信息;
  • android:inputType:指定編輯框輸入內容的類型(textPassword、numberPassword、number、date、phone、text)

【實例】簡單登錄界面


賬號密碼同樣輸入songsong123時在密碼框就會顯示點點,這是android:inputType的功能。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical">
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="請輸入賬號"
        android:id="@+id/editText" />
    <EditText
        android:inputType="textPassword"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="請輸入密碼"
        android:id="@+id/editText2" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="登  錄"
        android:textAllCaps="false"
        android:id="@+id/button" />
</LinearLayout>
EditText  還有另外一種情況就是隨着輸入內容越來越多,EditText在界面中會被不斷拉長,導致界面變得非常凌亂,這時我們就應該使用android:maxLines來限制佈局走形的情況出現。或者使用 android:maxLength來限制字數都可以達到目的。

        android:maxLines="1"
        android:maxLength="10"


  2.3 Button按鈕

Button是程序用於和用戶交互的一個重要控件,Button繼承了TextView。它主要是在UI界面上生成一個按鈕,該按鈕可以供用戶單擊,當用戶單擊按鈕時,就會觸發onClick時間。

實例依然是剛剛那個:

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="登  錄"
        android:textAllCaps="false"
        android:id="@+id/button" />
在Java代碼中:
public class MainActivity extends Activity {

    private Button button;
    private EditText editText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.text4);

        button = (Button) findViewById(R.id.button);
        editText = (EditText) findViewById(R.id.editText);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String str = editText.getText().toString();
                Toast.makeText(getApplicationContext(), str, Toast.LENGTH_SHORT).show();
            }
        });
} 


  2.4 ImageView圖片

ImageView是繼承自View組件,主要功能不僅用於顯示ImageView,而且還可以顯示任何Drawable對象。

  <ImageView
        android:id="@+id/imageView"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:src="@drawable/a4"/>

ImageView所支持的android:scaleType屬性可指定如下屬性

  •     fitXY:拉伸圖片(不按比例)以填充View的寬高。
  •     fitStart:按比例拉伸圖片,拉伸後圖片的高度爲View的高度,且顯示在View的左邊。
  •     fitCenter:按比例拉伸圖片,拉伸後圖片的高度爲View的高度,且顯示在View的中間。
  •     fitEnd:按比例拉伸圖片,拉伸後圖片的高度爲View的高度,且顯示在View的右邊。
  •     center:按原圖大小顯示圖片,但圖片寬高大於View的寬高時,截圖圖片中間部分顯示。
  •     centerCrop:按比例放大原圖直至等於某邊View的寬高顯示。
  •     centerInside:當原圖寬高或等於View的寬高時,按原圖大小居中顯示;反之將原圖縮放至View的寬高居中顯示。

【實例】圖片的動態切換:

通過單擊ImageView的setImageResource()方法動態完成切換圖片:

public class MainActivity extends ActionBarActivity {

    int[] images = new int[]{
            R.drawable.img1,
            R.drawable.img2,
            R.drawable.img3,
    };
    private ImageView img1;
    int currentImg = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        img1 = (ImageView) findViewById(R.id.img1);
        img1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                img1.setImageResource(images[++currentImg % images.length]);
            }
        });
    }


  2.5 RadioButton單選按鈕 和 CheckBox複選框

RadioButton和CheckBox是用戶界面中最普通的UI控件,他們都繼承了Button類,因此都可直接調用Button支持的各種屬性和方法。RadioButton和CheckBox和普通Button不同的是他們多了個可選中的功能android:checked屬性。RadioButton和CheckBox的不同點在於一組RadioButton只能選中一個,因此RadioButton通常要與RadioGroup一起使用,用於一組單選按鈕。

【實例】獲取用戶信息的簡單實例:


界面佈局代碼:

<LinearLayout 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:orientation="vertical"
    tools:context="songsong.com.imageviewtext.MainActivity2">

   <TextView
        android:id="@+id/tv1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="性別:" />
    <RadioGroup
        android:id="@+id/rg1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <RadioButton
            android:id="@+id/male"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:checked="true"
            android:text="男" />
        <RadioButton
            android:id="@+id/female"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="女" />
    </RadioGroup>
    <TextView
        android:id="@+id/tv2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="喜歡的顏色:" />
    <CheckBox
        android:id="@+id/checkBox1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="紅色" />
    <CheckBox
        android:id="@+id/checkBox2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="藍色" />
    <TextView
        android:id="@+id/tv3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="性別爲男"/>
    <TextView
        android:id="@+id/tv4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="喜歡的顏色是:"/>
</LinearLayout>
java代碼爲:
public class MainActivity2 extends ActionBarActivity {

    RadioGroup radioGroup;
    TextView show;
    CheckBox checkBox1;
    CheckBox checkBox2;
    TextView showbox;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        radioGroup = (RadioGroup) findViewById(R.id.rg1);
        show = (TextView) findViewById(R.id.tv3);

        checkBox1 = (CheckBox) findViewById(R.id.checkBox1);
        checkBox2 = (CheckBox) findViewById(R.id.checkBox2);
        showbox = (TextView) findViewById(R.id.tv4);

        radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                String tip = checkedId == R.id.male ? "性別爲男" : "性別爲女";
                show.setText(tip);
            }
        });
        checkBox1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    String str = showbox.getText().toString();
                    showbox.setText(str + checkBox1.getText().toString());
                }
            }
        });
        checkBox2.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    String str = showbox.getText().toString();
                    showbox.setText(str + checkBox2.getText().toString());
                }
            }
        });

    }
}

  

  2.6 ProgressBar進度條

 進度條也是UI界面中一種非常實用的空間,通常用於向用戶顯示某些耗時操作完成的百分比。進度條可以動態顯示進度,因此避免長時間執行某個耗時操作時,讓用戶感覺程序失去了響應,從而更好提高用戶的友好性。

通過style屬性可以爲ProgressBar指定風格:

  • @android:style/Widget.ProgressBar.Horizontal:水平進度條
  • @android:style/widget.ProgressBar.Inverse:普通大小的環形進度條
  • @android:style/widget.ProgressBar.Large:大環形進度條
  • @android:style/widget.ProgressBar.Large.Inverse:大環形進度條
  • @android:style/widget.ProgressBar.Small:小環形進度條
  • @android:style/widget.ProgressBar.Small.Inverse:小環形進度條

ProgressBar常用的XML屬性:

  • android:max:設置該進度條的最大值
  • style:樣式
  • android:progress:設置該進度條已完成進度值

<LinearLayout 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:orientation="vertical"
    tools:context="songsong.com.imageviewtext.ProgressBarText">
    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/progressBar" />
</LinearLayout>
【實例】最簡單的ProgressBar的佈局:

當數據加載完成時,我們就需要另外一個屬性android:visibility進行指定

  • visible:可見的,這是默認值;
  • invisible:不可見的,仍然佔據着原來位置和大小;
  • gone:不僅不可見,而且不再佔用任何屏幕空間;

也可以在代碼中設置setVisibiliy():

  • View.VISIBLE
  • View.INVISIBLE
  • View.GONE

【實例】ProgressBar進度條隱藏

<LinearLayout 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:orientation="vertical"
    tools:context="songsong.com.imageviewtext.ProgressBarText">

    <ProgressBar
        style="@android:style/Widget.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:id="@+id/probar2" />
    <Button
        android:id="@+id/bt1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="GONE隱藏/顯示"/>
    <Button
        android:id="@+id/bt2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="增加進度"/>
</LinearLayout>
java文件的代碼:

public class ProgressBarText extends ActionBarActivity {
    ProgressBar progressBar;
    Button bt1;
    Button bt2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_progress_bar_text);
        progressBar = (ProgressBar) findViewById(R.id.probar2);
        bt1 = (Button) findViewById(R.id.bt1);
        bt2 = (Button) findViewById(R.id.bt2);
        bt1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (progressBar.getVisibility() == View.GONE) {
                    progressBar.setVisibility(View.VISIBLE);
                } else {
                    progressBar.setVisibility(View.GONE);
                }
            }
        });
        bt2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int progress = progressBar.getProgress();
                if (progress>=100){
                    progressBar.setVisibility(View.GONE);
                    Toast.makeText(getApplicationContext(),"加載完成",Toast.LENGTH_SHORT).show();
                }else {
                    progress = progress + 10;
                    progressBar.setProgress(progress);
                }
            }
        });
    }
}
【實例】顯示在標題上的進度條

public class TitleProgressBar extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //設置窗口特徵:啓用顯示進度的進度條
        requestWindowFeature(Window.FEATURE_PROGRESS);  //①
        //設置窗口特徵:啓用不顯示進度的進度條
//		requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); //②
        setContentView(R.layout.activity_title_progress_bar);

        Button bn1 = (Button) findViewById(R.id.bn1);
        Button bn2 = (Button) findViewById(R.id.bn2);

        bn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                setProgressBarIndeterminateVisibility(true); //顯示不帶進度的進度條
                setProgressBarVisibility(true); //顯示帶進度的進度條
                setProgress(4500);
            }
        });
        bn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                setProgressBarIndeterminateVisibility(false); //顯示不帶進度的進度條
                setProgressBarVisibility(false); //顯示帶進度的進度條
            }
        });

    }
}

  2.7 SeekBar拖動條

SeekBar允許用戶改變拖動條的滑塊外觀,改變滑塊外觀通過android:thumb屬性來指定:
  • android:thumb:指定一個Drawable對象,該對象將作爲自定義滑塊;

【實例】該程序的界面佈局中需要兩個組件:一個ImageView用於顯示圖片,一個SeekBar用於動態改變圖片的透明度,界面佈局如下:

<LinearLayout 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:orientation="vertical"
    tools:context="songsong.com.imageviewtext.SeekBarTest">

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="200dp"
        android:scaleType="fitCenter"
        android:src="@drawable/img1" />

    <SeekBar
        android:id="@+id/sbk1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="255"
        android:progress="255"
        android:thumb="@drawable/black" />
</LinearLayout>
程序爲拖動條綁定一個監聽器,當滑塊位置發生改變時動態改變ImageView的透明度。

public class SeekBarTest extends Activity {
    ImageView imageView;
    SeekBar seekBar;
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_seek_bar);
        seekBar = (SeekBar) findViewById(R.id.sbk1);
        imageView = (ImageView) findViewById(R.id.imageView1);
        //當拖動條的滑塊位置發生變化的時候觸發該方法
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                imageView.setImageAlpha(progress);//動態改變透明度
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
        });
    }
}
效果:


  2.8 AlertDialog對話框

【實例】創建簡單對話框,界面只有一個按鈕,在代碼中爲此按鈕綁定監聽器:

public class AlertDialogText extends Activity {
    protected void onCreate(Bundle savedInstanceState) {
      ...
          //爲按鈕綁定單擊事件
         public void onClick(View v) {

                AlertDialog.Builder builder = new AlertDialog.Builder(AlertDialogText.this);
                builder.setTitle("簡單的標題");   //設置對話框標題
                builder.setMessage("對話框的內容\n,這是測試");    //設置對話框內容
                builder.setIcon(R.drawable.black);     //設置對話框圖標
                builder.setCancelable(false);          //可否取消

                builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {     //爲builder添加確定按鈕
                 @Override
                    public void onClick(DialogInterface dialog, int which) {

                    }
                });
                builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {  //爲builder添加取消按鈕
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                    }
                });
                builder.show();
            }
        });
    }
} 

效果:

上面這種樣式是最簡單的,AlertDialog還提供瞭如下6中方法來指定對話框的內容:

  • setMessage():設置對話框內容爲簡單文本;
  • setltems():設置對話框內容爲簡單列表項;
  • setSingleChoiceltems():設置對話框內容爲單選列表項;
  • setMultiChoiceltems():設置對話框內容爲多選列表項;
  • setAdapter():設置對話框內容爲自定義列表項;
  • setView():設置對話框內容爲自定義View;

【實例】用setView來設置登錄界面:

1、定義界面佈局login.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id="@+id/lg"
    android:padding="30dp">
    <EditText
        android:id="@+id/et1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="請輸入賬號" />
    <EditText
        android:id="@+id/et2"
        android:inputType="textPassword"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="請輸入密碼" />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <EditText
            android:id="@+id/et3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1" />
        <Button
            android:id="@+id/bt2"
            android:layout_width="220dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_weight="1"
            android:text="短信驗證" />
    </LinearLayout>
</LinearLayout>
2、在MainActivity代碼中寫:

public class ViewAlertDialogText extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_alert_dialog_text);

        findViewById(R.id.bt1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                LinearLayout lg = (LinearLayout) getLayoutInflater().inflate(R.layout.login, null);
                new AlertDialog.Builder(ViewAlertDialogText.this)
                        .setTitle("登錄界面")
                        .setIcon(R.drawable.black)
                        .setView(lg)
                        .setCancelable(false)
                        .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                            }
                        })
                        .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                            }
                        })
                        .show();
            }
        });
    }
}
在主佈局文件中僅有一個按鈕,代碼就不貼出來了。以下是效果圖:

  2.9 ProgressDialog進度對話框

ProgressDialog和AlertDialog有點類似,但ProgressDialog一般用來表示當前操作比較耗時,讓用戶耐心等待。創建ProgressDialog進度對話框有如下兩種方式:

  1. 如果只是創建簡單的進度對話框,那麼調用ProgressDialog提供的靜態show()方法顯示對話框即可。
  2. 創建ProgressDialog,然後調用方法對對話框裏的進度條進行設置,設置完成後將對話框顯示即可。

爲了對進度對話框的進度條進行設置,ProgressDialog包含了如下常用的方法:

  • setIndeterminate(boolean indeterminate):設置對話框裏的進度條不顯示進度值;
  • setMax(int):設置對話框裏進度條的最大值;
  • setMessage(CharSequece):設置對話框裏的消息;
  • setProgress(int value):設置對話框裏進度條的進度值;
  • setProgressStyle (int style):設置對話框裏進度條的風格;

【實例】ProgressDialog簡單實例

public class ProgressDialog_text extends Activity {

    final static int MAX_PROGRESSS = 100;  //最大的進度值
    private int[] data = new int[50];      //模擬填充長度爲100的數組
    int progressStatus = 0;                //記錄對話框的完成的百分比
    int hasData = 0;
    ProgressDialog pd2;

    //定義一個負責更新進度的handler
    Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            if (msg.what == 0x123) {       //表明消息是由該程序發送的
                pd2.setProgress(progressStatus);
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_progress_dialog_text);
    }

    //調用靜態方法顯示環形進度條btn1
    public void showSpinner(View source) {
        ProgressDialog.show(this, "任務執行中", "任務執行中,請稍等", false, true);

    }

    //顯示進度的進度條btn2
    public void showProgress(View source) {
        progressStatus = 0;             //將進度條的完成進度重設爲0
        hasData = 0;                    //重新開始填充數組
        pd2 = new ProgressDialog(this);
        pd2.setMax(MAX_PROGRESSS);      //設置最大值
        pd2.setTitle("任務完成百分比"); //設置對話框標題
        pd2.setMessage("耗時任務的完成百分比");  //設置內容
        pd2.setCancelable(false);  //設置是否響應back鍵
        pd2.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);   //設置樣式
        pd2.setIndeterminate(false);  //設置對話框是否顯示進度
        pd2.show();
        new Thread() {
            public void run() {
                while (progressStatus < MAX_PROGRESSS) {
                    progressStatus = MAX_PROGRESSS * doWork() / data.length;    //獲取耗時操作的完成百分比
                    handler.sendEmptyMessage(0x123);            //發送空消息到Handler
                }
                if (progressStatus >= MAX_PROGRESSS) {
                    pd2.dismiss();    //如果認爲完成,關閉對話框
                }
            }
        }.start();
    }

    //模擬一個耗時的操作
    public int doWork() {

        data[hasData++] = (int) (Math.random() * 100);
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return hasData;
    }
} 
佈局界面爲兩個按鈕:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="showSpinner"
        android:text="環形進度條" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="showProgress"
        android:text="顯示進度的進度條" />
</LinearLayout>
效果圖

      

  2.10 Menu菜單

菜單是用戶界面中最常見的元素之一。在Android中,菜單被分爲如下三種,選項菜單(OptionsMenu)、上下文菜單(ContextMenu)和子菜單(SubMenu)。

  • 選項菜單(OptionsMenu):最常規的菜單,不支持勾選標記。
  • 子菜單(SubMenu):子菜單點擊後單出的子菜單項,不支持菜單項圖標,不支持嵌套子菜單。
  • 上下文菜單(ContextMenu):長按視圖控件後出現的菜單,不支持菜單快捷鍵和圖標。

常用方法:

  • add():用於添加菜單項;
  • addSubMenu():用於添加子菜單。

需要重寫的方法:

  • public boolean onCreateOptionsMenu(Menu menu):當用戶單擊Menu鍵時觸發的方法。
  • public boolean onOptionsItemSelected(MenuItem item):選項菜單的菜單項被單擊後的回調方法。

 add(int groupid,int itemid,int order,charSequence title)方法的四個參數,依次是:

  1. 組別:如果不分組的話就寫0。
  2. ID:這個很重要,Android根據這個Id來確定不同的菜單。
  3. 順序:那個菜單現在在前面由這個參數的大小決定,從1到6一次是同上往下,從左到右排。
  4. 標題:菜單的顯示文本。

【實例】如何爲Android應用添加菜單和子菜單。

該程序的java代碼如下:

public class MainActivity extends Activity {
    // 定義字體大小菜單項的標識
    final int FONT_10 = 0x111;
    final int FONT_12 = 0x112;
    final int FONT_14 = 0x113;
    final int FONT_16 = 0x114;
    final int FONT_18 = 0x115;
    // 定義普通菜單項的標識
    final int PLAIN_ITEM = 0x11b;
    // 定義字體顏色菜單項的標識
    final int FONT_RED = 0x116;
    final int FONT_BLUE = 0x117;
    final int FONT_GREEN = 0x118;
    private EditText edit;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        edit = (EditText) findViewById(R.id.edt1);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        SubMenu fontMenu = menu.addSubMenu("字體大小");
        fontMenu.setIcon(R.drawable.font);
        fontMenu.setHeaderIcon(R.drawable.font);
        fontMenu.add(0, FONT_10, 0, "10號字體");
        fontMenu.add(0, FONT_12, 0, "12號字體");
        fontMenu.add(0, FONT_14, 0, "14號字體");

        menu.add(0, PLAIN_ITEM, 0, "普通菜單項");

        SubMenu colorMenu = menu.addSubMenu("字體顏色");
        colorMenu.setIcon(R.drawable.color);
        colorMenu.setHeaderIcon(R.drawable.color);
        colorMenu.setHeaderTitle("選擇文字顏色");
        colorMenu.add(0, FONT_RED, 0, "紅色");
        colorMenu.add(0, FONT_GREEN, 0, "綠色");

       return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
            case FONT_10:
                edit.setTextSize(10 * 2);
                break;
            case FONT_12:
                edit.setTextSize(12 * 2);
                break;
            case FONT_14:
                edit.setTextSize(14 * 2);
                break;
            case FONT_RED:
                edit.setTextColor(Color.RED);
                break;
            case FONT_BLUE:
                edit.setTextColor(Color.BLUE);
                break;
            case FONT_GREEN:
                edit.setTextColor(Color.GREEN);
                break;
            case PLAIN_ITEM:
                Toast toast = Toast.makeText(MainActivity.this, "您單擊了普通菜單項", Toast.LENGTH_SHORT);
                toast.show();
                break;
        }
        return true;
    }
}
上面程序中添加了三個菜單的代碼,其中有兩個菜單帶有子菜單。運行程序,單擊Menu按鍵,將會看到效果:


接下來是上下文菜單:當用戶長按該組件時顯示上下文菜單,首先要學會開發上下文菜單的步驟:

  • 重寫Activity的onCreateContextMenu()方法;
  • 調用Activity的registerForContextMenu()方法爲view組件註冊上下文菜單;
  • 重寫onContextItemSelected()方法爲菜單項提供相應;

【實例】通過長按組件改變組件的背景顏色:

public class OtherActivity extends Activity {

    //爲每個菜單定義一個標識
    final int Menu1 = 0x111;
    final int Menu2 = 0x112;
    final int Menu3 = 0x113;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_other);
        textView = (TextView) findViewById(R.id.txt);

       registerForContextMenu(textView);   //爲textView綁定事件
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        //創建上下文菜單時觸發該方法
        menu.add(0, Menu1, 0, "紅色");
        menu.add(0, Menu2, 0, "綠色");
        menu.add(0, Menu3, 0, "藍色");

        menu.setGroupCheckable(0, true, true);  //將3個菜單項設置爲 單選項

        menu.setHeaderTitle("選擇背景色");  //設置標題
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        //創建上下文菜單項被單擊時觸發該方法

        switch (item.getItemId()) {
            case Menu1:
                item.setCheckable(true);
                textView.setBackgroundColor(Color.RED);
                break;
            case Menu2:
                item.setCheckable(true);
                textView.setBackgroundColor(Color.GREEN);
                break;
            case Menu3:
                item.setCheckable(true);
                textView.setBackgroundColor(Color.BLUE);
                break;
        }
        return true;
    }
}
效果如下:

  接下來還要學習的是使用XML文件定義菜單:android提供了兩種創建菜單的方式,一種是在Java代碼中創建,另外一種是使用XML資源文件定義。我之前做的都是java代碼中創建,但在java代碼中定義菜單會有很多不足的地方。

  • 在java代碼中定義菜單、菜單項,必然檔子程序代碼臃腫
  • 需要程序員採用硬編碼方式爲每個菜單項分配ID,爲每個菜單組分配ID,會導致應用可擴展性、維護性降低。
  • 使用XML資源文件來定義菜單,可以提供更好的解耦。

  用於android studio在創建android項目時,會默認在res目錄下新建menu子目錄,並在該子目錄下提供menu_main.xml菜單資源文件,由此可見,android更推薦使用XML資源文件來定義菜單。

  • <item.../>元素:定義菜單項;
  • <group.../>子元素:將多個<item.../>定義的菜單項包裝成一個菜單組;
  • checkableBehavior:指定改組菜單的選擇行爲。none不選、all多選、single單選。
  • menuCategory:對菜單進行分類,指定菜單的優先級。container、system、secondary、alternative。
  • visible:指定該組菜單是否可見。
  • enable:指定該組菜單是否可用。

  需要注意的是:<item.../>元素用於定義菜單項,<item.../>元素又可包含<menu.../>元素,位於<item.../>元素內部的<menu.../>元素就代表子菜單。

【實例】使用XML資源文件定義 選項菜單 上下文菜單

首先爲選項菜單編寫XML資源文件:menu_main.xml,在<menu.../>元素裏包含三個<item.../>子元素,這表明該菜單裏有三個菜單項。第一、第三菜單項都包含子菜單。

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="songsong.com.menutext.MenuText_XML">

    <item android:title="字體大小">
        <menu>
            <group android:checkableBehavior="single">
                <item
                    android:id="@+id/font_10"
                    android:title="10號字體" />
                <item
                    android:id="@+id/font_11"
                    android:title="11號字體" />
                <item
                    android:id="@+id/font_12"
                    android:title="12號字體" />
            </group>
        </menu>
    </item>
    <item
        android:id="@+id/putongitem"
        android:title="普通菜單"></item>
    <item
        android:id="@+id/Font_color"
        android:title="字體顏色">
        <menu>
            <group>
                <item
                    android:id="@+id/ren_font"
                    android:title="紅色" />
                <item
                    android:id="@+id/blue_font"
                    android:title="藍色" />
                <item
                    android:id="@+id/green_font"
                    android:title="綠色" />
            </group>
        </menu>
    </item>
</menu>
接下來定義該應用上下文菜單的資源文件,代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/red"
            android:alphabeticShortcut="r"
            android:title="紅色" />
        <item
            android:id="@+id/blue"
            android:alphabeticShortcut="b"
            android:title="藍色" />
        <item
            android:id="@+id/green"
            android:alphabeticShortcut="g"
            android:title="綠色" />
    </group>
</menu>
定義了上面兩份菜單資源後,接下來可以在Activity中的onCreateOptionsMenu、onCreateContextMenu方法中加載這兩份菜單資源。

public class MenuText_XML extends Activity {
    private TextView txt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_menu_text__xml);
        txt = (TextView) findViewById(R.id.txt);
        registerForContextMenu(txt);                //爲上下文菜單綁定事件txt
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = new MenuInflater(this);
        inflater.inflate(R.menu.menu_main, menu);      //綁定選項菜單R.menu.menu_main
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        MenuInflater inflater = new MenuInflater(this);
        inflater.inflate(R.menu.context, menu);         //綁定上下文菜單R.menu.context
        menu.setHeaderTitle("請選擇背景色");
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {    //選項菜單被單擊後回調的方法

        if (item.isCheckable()) {  //是否選中
            item.setCheckable(true); //設置爲選中
        }
        switch (item.getItemId()) {
            case R.id.font_10:
                txt.setTextSize(10 * 2);
                break;
            case R.id.font_11:
                txt.setTextSize(11 * 2);
                break;
            case R.id.font_12:
                txt.setTextSize(12 * 2);
                break;
            case R.id.putongitem:
                Toast toast = Toast.makeText(MenuText_XML.this, "你點擊了普通菜單項", Toast.LENGTH_SHORT);
                toast.show();
                break;
            case R.id.ren_font:
                txt.setTextColor(Color.RED);
                break;
            case R.id.blue_font:
                txt.setTextColor(Color.BLUE);
                break;
            case R.id.green_font:
                txt.setTextColor(Color.GREEN);
                break;
        }
        return true;
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {    //上下文菜單被單擊時觸發該方法
        item.setCheckable(true);
        switch (item.getItemId()) {
            case R.id.red:
                item.setCheckable(true);
                txt.setBackgroundColor(Color.RED);
                break;

            case R.id.blue:
                item.setCheckable(true);
                txt.setBackgroundColor(Color.BLUE);
                break;

            case R.id.green:
                item.setCheckable(true);
                txt.setBackgroundColor(Color.GREEN);
                break;
        }
        return true;
    }
}
代碼運行效果和上個實例的一樣:

             

最後一種是PopupMenu彈出式菜單:PopupMenu會在指定的組件上彈出一個列表,它的菜單選項來自Menu資源。以下是創建步驟:

【實例】簡單的PopupMenu使用

先定義Menu資源文件XML:

<?xml version="1.0" encoding="UTF-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/search"
        android:icon="@android:drawable/ic_menu_search"
        android:title="查找" />
    <item
        android:id="@+id/add"
        android:icon="@android:drawable/ic_menu_add"
        android:title="添加" />-
    <item
        android:id="@+id/edit"
        android:icon="@android:drawable/ic_menu_edit"
        android:title="編輯">-
        <menu>
            <item
                android:id="@+id/copy"
                android:title="複製" />
            <item
                android:id="@+id/cut"
                android:title="剪切" />
            <item
                android:id="@+id/paste"
                android:title="粘貼" />
        </menu>
    </item>

    <item
        android:id="@+id/exit"
        android:title="隱藏菜單" />
</menu>
然後在代碼中定義:

public class PopupMenuText extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_popup_menu);

        final Button bt1 = (Button) findViewById(R.id.bt1);
        bt1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final PopupMenu popup = new PopupMenu(PopupMenuText.this, bt1);
                popup.getMenuInflater().inflate(R.menu.popup_menu, popup.getMenu());

               popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                    public boolean onMenuItemClick(MenuItem item) {

                        switch (item.getItemId()) {
                            case R.id.exit:
                                popup.dismiss();// 隱藏該對話框
                                break;
                            default:
                                Toast toast = Toast.makeText(PopupMenuText.this, "您單擊了【"
                                        + item.getTitle() + "】菜單項", Toast.LENGTH_SHORT); // 使用Toast顯示用戶單擊的菜單項
                                toast.show();
                        }
                        return true;
                    }
                });
                popup.show(); //showing popup menu

            }
        });
    }
}
效果:


  2.11 ActionBar活動條

本段內容參考與:http://www.cnblogs.com/yc-755909659/p/4290784.html

2.11.1.ActionBar介紹

  活動條(ActionBar)是Android3.0的重要更新之一,ActionBar位於傳統標題欄title bar的位置,也就是顯示在屏幕的頂部。對於Android平板設備來說屏幕更大它的標題使用ActionBar來設計可以展示更多豐富的內容,方便操控。

2.11.2.ActionBar功能


  1. ActionBar的圖標,可顯示軟件圖標,也可用其他圖標代替。當軟件不在最高級頁面時,圖標左側會顯示一個左箭頭,用戶可以通過這個箭頭“向上導航”;
  2. 如果你的應用要在不同的View中顯示數據,這部分允許用戶來切換視圖。一般的作法是用一個下拉菜單或者是Tab選項卡。如果只有一個界面,那這裏可以顯示應用程序的標題或者是更長一點的商標信息;
  3. 兩個action按鈕,這裏放重要的按鈕功能,爲用戶進行某項操作提供直接的訪問;
  4. overflow按鈕,放不下的按鈕會被置於“更多...”菜單項中,“更多...”菜單項是以下拉形式實現的。

2.11.3.如何使用

    2.11.3.1、添加ActionBar

最新的Android版本已經默認啓用了ActionBar,因此只要在AndroidManifest.xml文件的SDK配置中指定該應用的目標版本高於11,默認就會啓用ActionBar。


   2.11.3.2、取消ActionBar

如果希望關閉ActionBar,則可以設置該應用的主題爲NoActionBar。

<<application
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.AppCompat.Light.NoActionBar" >
       ...
    </application>
一旦關閉了ActionBar,該Android應用就不能使用ActionBar。在實際項目中,通常推薦使用代碼來控制ActionBar的顯示、隱藏。

ActionBar actionBar = getActionBar();
actionBar.show(); //顯示
actionBar.hide();  //隱藏


    2.11.3.3、修改Action Bar的圖標和標題

  默認情況下,系統會使用<application>或者<activity>中icon屬性指定的圖片來作爲ActionBar的圖標,但是我們也可以改變這一默認行爲。如果我們想要使用另外一張圖片來作爲ActionBar的圖標,可以在<application>或者<activity>中通過logo屬性來進行指定,而標題中的內容使用label屬性來指定。

<activity
            android:name=".MainActivity"
            android:logo="@drawable/black"
            android:label="ActionBar學習">
           ...
        </activity>
效果如下:



   2.11.3.4、添加Action按鈕,顯示選項菜單項

Android不再強制要求手機必須提供MENU按鍵,這樣可能導致用戶無法打開選項菜單。爲了解決這個問題Android提供ActionBar作爲解決方案。

ActionBar還可以根據應用程序當前的功能來提供與其相關的Action按鈕,這些按鈕都會以圖標或文字的形式直接顯示在ActionBar上。當然,如果按鈕過多,ActionBar上顯示不完,多出的一些按鈕可以隱藏在overflow裏面,點擊一下overflow按鈕就可以看到全部的Action按鈕了。

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/select_id"
        android:icon="@drawable/a5"
        android:showAsAction="always"
        android:title="查詢" />
    <item
        android:id="@+id/baohu_id"
        android:icon="@drawable/a6"
        android:showAsAction="always"
        android:title="保護" />
    <item
        android:id="@+id/delete_id"
        android:icon="@drawable/a7"
        android:showAsAction="always"
        android:title="刪除" />

</menu>
相對定義Menu選項菜單項新增了android:showAsAction屬性,該屬性可有空子將這些菜單項顯示在ActionBar上。瞭解一下支持的參數值:
  • fRoom:會顯示在ActionBar,但如果滿了就會顯示在溢出列表。
  • never:永遠不會顯示在ActionBar,只會在溢出列表中。
  • always:無論是否滿了都要顯示在ActionBar。
  •  withText:示意在ActionBar中顯示文本標題。
  • collapseActionView :聲明瞭這個操作視窗應該被摺疊到一個按鈕中,當用戶選擇這個按鈕時,這個操作視窗展開。

在MainActivity.java文件中重寫onCreateOptionsMenu方法:

   public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = new MenuInflater(this);
        inflater.inflate(R.menu.menu_main, menu);
        return super.onCreateOptionsMenu(menu);
    }
現在重新運行一下程序,結果如下圖所示:

   2.11.3.5、響應Action按鈕的點擊事件

接着在Activity中重寫onOptionsItemSelected()方法,通過方法傳入的MenuItem參數,我們可以調用它的getItemId()方法和menu資源中的id進行比較,從而辨別出用戶點擊的是哪一個Action按鈕。

 @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.select_id:
                Toast.makeText(this, "你點擊了“查詢”按鍵!", Toast.LENGTH_SHORT).show();
                return true;
            case R.id.baohu_id:
                Toast.makeText(this, "你點擊了“保護”按鍵!", Toast.LENGTH_SHORT).show();
                return true;
            case R.id.delete_id:
                Toast.makeText(this, "你點擊了“刪除”按鍵!", Toast.LENGTH_SHORT).show();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
【實例】通過Action Bar圖標進行導航

  啓用ActionBar圖標導航的功能,可以允許用戶根據當前應用的位置來在不同界面之間切換。比如,A界面展示了一個列表,點擊某一項之後進入了B界面,這時B界面就應該啓用ActionBar圖標導航功能,這樣就可以回到A界面。

爲了將應用程序圖標轉變成可以點擊的圖標,可以調用以下方法:

  • setDisplayHomeAsUpEnabled(boolean):設置是否將應用程序圖標轉變成可點擊的圖標,並在圖標上添加向左的箭頭。
  • setDisplayOptions(int):通過傳人int類型常量來控制該ActionBar的顯示選項。
  • setDisplayShowHomeEnabled(boolean):設置是否顯示應用程序圖標。
  • setHomeButtonEnabled(boolean):設置是否將應用程序圖標轉變成可點擊的按鈕。

先來看看效果:

實例中,通過點擊action按鈕,啓動另一個Activity(TwoActivity),發現TwoActivity的程序圖標多了個向左的箭頭,點擊是返回父Activity(MainActivity)。

第一步:MainActivity.java通過點擊“查詢”action按鈕創建TwoActivity:

    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.select_id:

                Intent intent = new Intent(this, TwoActivity.class);  //啓動TwoActivity
                startActivity(intent);
                return true;
         ...
       }
第二步:爲TwoActivity添加setDisplayHomeAsUpEnabled可被點擊和顯示左箭頭,然後爲程序圖標添加點擊事件:

1、在TwoActivity的onCreate中:

 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_two);
        ActionBar actionBar = getActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true); //設置爲true
    }
2、需要在AndroidManifest.xml中配置父Activity:

 <activity
            android:name=".TwoActivity"
            android:label="@string/title_activity_two"
            android:parentActivityName=".MainActivity">

        </activity>
3.、對程序圖標點擊事件進行處理:

</pre><pre name="code" class="java">public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                Intent upIntent = NavUtils.getParentActivityIntent(this);
                if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
                    TaskStackBuilder.create(this)
                            .addNextIntentWithParentStack(upIntent)
                            .startActivities();
                } else {
                    upIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                    NavUtils.navigateUpTo(this, upIntent);
                }
                return true;
        }
        return super.onOptionsItemSelected(item);
    }
其中,調用NavUtils.getParentActivityIntent()方法可以獲取到跳轉至父Activity的Intent,然後如果父Activity和當前Activity是在同一個Task中的,則直接調用navigateUpTo()方法進行跳轉,如果不是在同一個Task中的,則需要藉助TaskStackBuilder來創建一個新的Task。

    2.11.3.6、添加Action View

爲了在ActionBar上添加Action View,可以來用如下兩種方式:

  • android:actionLayout屬性:指定Action View的實現類。
  • android:actionViewClass屬性:指定Action View對應的視圖資源。

【實例】標題上的搜索和時鐘

本實例在菜單資源文件中定義兩個Action Item,但這兩個Action Item都是使用Action View。資源文件代碼如下(menu_main.xml):

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="songsong.com.actionbartest.ActionViewTest">

    <item
        android:id="@+id/search"
        android:actionViewClass="android.widget.SearchView"
        android:orderInCategory="50"
        android:showAsAction="always" />
    <item
        android:id="@+id/progress"
        android:actionLayout="@layout/clock"
        android:orderInCategory="100"
        android:showAsAction="always" />

</menu>
定義界面佈局資源爲@layout/clock

<?xml version="1.0" encoding="utf-8"?>
<AnalogClock xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
</AnalogClock>
該界面佈局文件僅僅定義了AnalogClock,這表明該ActionBar的第二個Action View只是一個模擬鬧鐘。效果如下:

  2.11.3.7、Overflow按鈕

Overflow按鈕是顯示在ActionBar右邊的三個點,其意爲“更多”,當actionbar上面顯示內容滿了的時候將會自動填充進Overflow列表。但更多時候,如果手機有Menu按鍵的情況下,Overflow按鈕是不顯示的。所有如果要想在有Menu手機中顯示,就要加入一段大神已經寫好的代碼:

public class ActionViewTest extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        setOverflowShowingAlways();//調用方法
    }
<pre name="code" class="java">private void setOverflowShowingAlways() {
        try {
            ViewConfiguration config = ViewConfiguration.get(this);
            Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
            if (menuKeyField != null) {
                menuKeyField.setAccessible(true);
                menuKeyField.setBoolean(config, false);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


效果圖:

   2.11.3.9、讓Overflow中的選項顯示圖標

爲了讓Action按鈕在Overflow中能顯示圖標,就要在Activity中重寫onMenuOpened()方法

  @Override
    public boolean onMenuOpened(int featureId, Menu menu) {
        if (featureId == Window.FEATURE_ACTION_BAR && menu != null) {
            if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
                try {
                    Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
                    m.setAccessible(true);
                    m.invoke(menu, true);
                } catch (Exception e) {
                }
            }
        }
        return super.onMenuOpened(featureId, menu);
    }
顯示圖標是由MenuBuilder這個類的setOptionalIconsVisible變量來決定的,如果我們在overflow被展開的時候將這個變量賦值爲true,那麼裏面的每一個Action按鈕對應的圖標就都會顯示出來了。

  2.11.3.10添加導航Tabs :暫未完成

  2.11.3.11添加下拉列表導航:暫未完成


  2.12 ListView的使用

【實例】ListView簡單的使用

第一步,在Layout_main.xml中定義ListView控件:

<LinearLayout 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"
    tools:context=".MainActivity">

    <ListView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:divider="#f00"
        android:dividerHeight="2px"
        android:entries="@array/books"
        android:headerDividersEnabled="false"></ListView>

</LinearLayout>

第二步,在Java文件中:

public class ArrayAdapterTest extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_arrayadaptertest);

        ListView ls = (ListView) findViewById(R.id.list);

        String arr1[] = new String[]{"堅持", "不懈", "努力", "到底"};

        ArrayAdapter<String> adapter1 = new ArrayAdapter<String>(ArrayAdapterTest.this, R.layout.array_item, arr1);

        ls.setAdapter(adapter1);
    }
}

如果想要對ListView的外觀、行爲進行定製,就需要通過Adapter控制每個列表項的外觀和行爲。

Adapter適配器:Adapter本身只是一個接口,他常用的實現類如下:

  • ArrayAdapter:簡單、易用的Adapter,通常用於數組或list集合的多個值包裝成的多個列表項。
  • SimpleAdapter:並不簡單,功能強大的Adapter,可用於將list集合的多個對象包裝成多個列表項。
  • BaseAdapter:通常用於被擴展。擴展BaseAdapter可用對各列表項進行最大限度的定製。

剛剛的簡單實例就用到了ArrayAdapter適配器

ArrayAdapter<String> adapter1 = new ArrayAdapter<String>(ArrayAdapterTest.this, R.layout.array_item, arr1);

        ls.setAdapter(adapter1);
在創建ArrayAdapter時必須指定如下三個參數:

  • Context:這個參數無需多說,它代表了訪問整個Android應用的接口,幾乎創建所有的組件都需要傳入Context對象。
  • textViewResourcele:一個資源ID,該資源ID代表一個TextView。
  • 數組或list:該數組或list將負責爲多個列表項提供數據。

在最後爲listView設定適配器 :ls.setAdapter(adapter1);

【實例】使用SimpleAdapter創建ListView

先定義界面佈局文件:

<LinearLayout 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"
    tools:context="songsong.com.listviewtext.SimpleAdapterTest">

    <ListView
        android:id="@+id/lv1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"></ListView>

</LinearLayout>
下面是Activity代碼:

public class SimpleAdapterTest extends Activity {
    private String[] title = new String[]{"我是標題1", "我是標題2", "我是標題3", "我是標題4"};
    private String[] content = new String[]{"我是內容1", "我是內容2", "我是內容3", "我是內容4"};
    private int[] ImageIds = new int[]{R.drawable.a1, R.drawable.a2, R.drawable.a3, R.drawable.a4};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simpleadaptertest);
          //創建一個List集合,List集合的元素是Map.
        List<Map<String, Object>> listItems = new ArrayList<Map<String, Object>>();  

        for (int i = 0; i < title.length; i++) {
            Map<String, Object> listItem = new HashMap<String, Object>();

            listItem.put("A1", ImageIds[i]);
            listItem.put("A2", title[i]);
            listItem.put("A3", content[i]);
            listItems.add(listItem);
        }
        SimpleAdapter simpleAdapter = new SimpleAdapter(
                SimpleAdapterTest.this, 
                listItems,
                R.layout.simple_item,
                new String[]{"A1", "A2", "A3"},
                new int[]{R.id.img1, R.id.tv1, R.id.tv2});

        ListView listView = (ListView) findViewById(R.id.lv1);

        listView.setAdapter(simpleAdapter);
    }
}
先要學習的是SimpleAdapter創建需要5個參數:

  • 第1個參數:仍然是Context。
  • 第2個參數:該參數應該是一個List<? extends Map<String,?>>類型的集合對象,該集合對象中米格Map<String,?>對象生成一個列表項。
  • 第3個參數:該參數指定一個界面佈局的ID。例如我的佈局文件名叫R.layout.simple_item。
  • 第4個參數:該參數應該是一個String[]類型的參數,該參數決定提取Map<String,?>對象中哪些Key對應的Value來生成列表項(數組名)。
  • 第5個參數:該參數應該是一個int[]類型的參數,該參數決定填充哪些組件。

R.layout.simple_item對應的佈局文件代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:padding="15dp">
    
    <ImageView
        android:id="@+id/img1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20dp" />

        <TextView
            android:id="@+id/tv2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="14dp" />

    </LinearLayout>
</LinearLayout>
效果如下:

如果需要監聽用戶單擊、選中某個列表項的時間,則可以通過AdapterView的setOnItemClickListener()方法來監聽單擊事件,setOnItemSelectedListener()方法來監聽選中事件。

 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {   //第position項被單擊時激發該方法
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                System.out.println(title[position] + "被單擊了");
            }
        });
        listView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {    //選中事件綁定監聽器
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                System.out.println(title[position] + "被選中了");
            }
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

【實例】擴展BaseAdapter實現不存儲列表項ListView: 暫未寫



  2.13、Spinner的功能與用法

Spinner組件與Swing編程中的Spinner不同,此處的Spinner其實就是一個列表選擇框,不過Android的列表選擇框並不需要顯示下拉列表,而是相當於彈出一個菜單供用戶選擇。

以下是XML屬性及其相關方法:

  • android:entries:使用數組資源設置該下拉列表框的列表項。
  • android:prompt:設置該列表選擇框的提示信息。

有兩種定義Spinner的方式,第一種是定義數組資源:

<LinearLayout 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:orientation="vertical"
    tools:context=".MainActivity">

    <Spinner
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:entries="@array/books"
        android:prompt="@string/tishi"></Spinner>

    <Spinner
        android:id="@+id/spinner_id"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"></Spinner>
</LinearLayout>

另外一種是java代碼:

public class MainActivity extends Activity {
    Spinner spinner;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        spinner = (Spinner) findViewById(R.id.spinner_id);

        String[] data = {"堅持", "不懈", "努力", "奮鬥"};

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, data);
        spinner.setAdapter(adapter);
    }
}
效果如圖:

取得用戶的選擇代碼可以使用getSelectedItem()方法取得用戶的選擇,如下所示:

String sp = spinner.getSelectedItem().toString();



  2.14自動完成文本框AutoCompleteTextView的功能與用法 :暫未完成


  2.15自定義AndroidUI組件

【實例】自定義標題欄

新建一個title.xml佈局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:background="#005">

    <Button
        android:id="@+id/title_back"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="返回" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_weight="1"
        android:gravity="center"
        android:text="標題" />

    <Button
        android:id="@+id/title_edit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="修改" />
</LinearLayout>
修改layout_main.xml去使用title.xml:

<LinearLayout 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"
    tools:context=".MainActivity">

    <include layout="@layout/title"></include>
</LinearLayout>
最後一步就是在MainActivity.java文件中隱藏系統自帶的title:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
    }
效果如下:

爲了要按鈕能響應事件,需要修改代碼,新建Java文件TitleLayout,並繼承LinearLayout,代碼如下

public class TitleLayout extends LinearLayout {

    public TitleLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        LayoutInflater.from(context).inflate(R.layout.title, this);

        Button back = (Button) findViewById(R.id.title_back);
        back.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                ((Activity) getContext()).finish();
            }
        });

        Button edit = (Button) findViewById(R.id.title_edit);
        edit.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getContext(), "edit", Toast.LENGTH_SHORT).show();
            }
        });
    }
}
然後要在layout_main.xml中重新定義title.xml文件

    <songsong.com.zidingyikongjian.TitleLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </songsong.com.zidingyikongjian.TitleLayout>
效果如下:


——————————————————————

學習內容:

  • 掌握View和ViewGroup類
  • 學習各個常用控件的使用方法
  • 瞭解View的本質
  • 熟練掌握自定義AndroidUI組件
  • 熟練掌握Canvas和Drawable畫自定義組件以及事件
  • 熟練NinePatch圖像的使用(9圖):保存局部不變,其餘拉伸
  • 日記工具Log
  • 瞭解Android界面事件機制

考察問題:

  • View是所有控件的基類,能否說一下他與Activity的關係。
  • View的核心是什麼,能否說一下里面的onDraw函數。
  • 自定義組件如何實現自定義事件。
  • NinePatch是幹什麼的
  • 簡單描述下Android界面事件機制
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章