閱讀前,請瀏覽此處上方目錄。
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 | 控制該子組件是否與佈局容器右邊對齊 |
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進度對話框有如下兩種方式:
- 如果只是創建簡單的進度對話框,那麼調用ProgressDialog提供的靜態show()方法顯示對話框即可。
- 創建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)方法的四個參數,依次是:
- 組別:如果不分組的話就寫0。
- ID:這個很重要,Android根據這個Id來確定不同的菜單。
- 順序:那個菜單現在在前面由這個參數的大小決定,從1到6一次是同上往下,從左到右排。
- 標題:菜單的顯示文本。
【實例】如何爲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功能
- ActionBar的圖標,可顯示軟件圖標,也可用其他圖標代替。當軟件不在最高級頁面時,圖標左側會顯示一個左箭頭,用戶可以通過這個箭頭“向上導航”;
- 如果你的應用要在不同的View中顯示數據,這部分允許用戶來切換視圖。一般的作法是用一個下拉菜單或者是Tab選項卡。如果只有一個界面,那這裏可以顯示應用程序的標題或者是更長一點的商標信息;
- 兩個action按鈕,這裏放重要的按鈕功能,爲用戶進行某項操作提供直接的訪問;
- 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界面事件機制