- Android開發:從0到1 (清華開發者書庫)
- 趙志榮
- 2192字
- 2020-11-28 16:13:41
7.6 進度欄
進度欄(Progress Bar)可以反饋出后臺任務是否正在處理或處理的進度,從而消除用戶的心理等待時間。
在Android中,進度欄是android.widget.ProgressBar類,類圖如圖7-23所示,從圖中可見android.widget.ProgressBar直接繼承了android.view.View類。

圖7-23 ProgressBar類圖
7.6.1 進度欄相關屬性和方法
進度欄有很多屬性。下面是常用的幾個屬性:
? android:max。設置進度最大值。
? android:progress。設置當前進度。
? android:secondaryProgress。第二層進度欄進度。
? android:indeterminate。設置不確定模式進度欄,true為不確定模式。進度欄(ProgressBar)類中的常用方法如下:
? getMax()。返回進度最大值。
? getProgress()。返回進度值。
? getSecondaryProgress()。返回第二層進度欄進度值。
? incrementProgressBy(int diff)。設置增加進度。
? isIndeterminate()。判斷是否為不確定模式。
? setIndeterminate(boolean indeterminate)。設置為不確定模式。
說明 什么是不確定模式(indeterminate)?一個任務的進度可以分為兩種:可確定進度和不可確定進度。可確定進度是通過計算能夠知道當前任務的進展情況,可以給用戶一個完成的進度比例,還可以估算任務結束的時間。例如,估算Windows的安裝進度,會顯示安裝了百分之幾,還有多長時間完成。可確定進度模式能夠給用戶很好的體驗;不可確定進度,是一些無法計算進展情況的任務,這些任務不知何時結束,但可以知道任務是進行還是停止。
Android系統提供了多種進度欄樣式。其中一些與系統主題無關,如圖7-24(a)、圖7-24(d)、圖7-24(f)所示;還有一些與系統主題有關,如圖7-24(b)、圖7-24(c)、圖7-24(e)所示。下面是系統主題無關的6種樣式:

圖7-24 進度欄樣式
? Widget.ProgressBar.Horizontal。水平條狀進度欄。
? Widget.ProgressBar.Small。小圓形進度欄。
? Widget.ProgressBar.Large。大圓形進度欄。
? Widget.ProgressBar.Inverse。圓形進度欄。
? Widget.ProgressBar.Small.Inverse。小圓形進度欄。
? Widget.ProgressBar.Large.Inverse。大圓形進度欄。
在XML中,可以通過style="@android:style/ 進度欄樣式 "進行設置,代碼如下:
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@android:style/Widget.ProgressBar.Small"/>
另外,還有與系統主題有關的8種樣式:
? progressBarStyleHorizontal。水平條狀進度欄。
? progressBarStyleSmall。小圓形進度欄。
? progressBarStyle。圓形進度欄。
? progressBarStyleLarge。大圓形進度欄。
? progressBarStyleSmallInverse。小圓形進度欄。
? progressBarStyleInverse。圓形進度欄。
? progressBarStyleLargeInverse。大圓形進度欄。
? progressBarStyleSmallTitle。標題欄中進度欄。
在XML中,可以通過style="? android:attr/ 進度欄樣式 "進行設置,代碼如下:
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="? android:attr/progressBarStyleSmall"/>
注意 前文style屬性中帶有Inverse和不帶有Inverse的區別;當進度欄控件所在的背景顏色為白色時,需要使用帶有Inverse的樣式。它們的區別不是旋轉方向相反。
7.6.2 實例1:水平條狀進度欄
水平條狀進度是樣式設置為Horizontal進度欄,條狀進度欄非常適合可確定進度(indeterminate = true)的情況,但也可展示不可確定進度(indeterminate = false)的情況。
下面通過實例了解它們的使用情況。實例如圖7-25所示,單擊-和+按鈕可改變進度,條狀進度還可以有雙層進度欄樣式。
布局文件activity_main.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"> … <ProgressBar android:id="@+id/progress_horizontal01" android:layout_width="200dip" android:layout_height="wrap_content" style="@android:style/Widget.ProgressBar.Horizontal" ① android:max="100" ② android:progress="50"/> ③ <!--包含按鈕欄--> <include android:id="@+id/button_bar1"layout="@layout/button_bar"/> … <ProgressBar android:id="@+id/progress_horizontal02" style="? android:attr/progressBarStyleHorizontal" ④ android:layout_width="200dip" android:layout_height="wrap_content" android:max="100" ⑤ android:progress="50" ⑥ android:secondaryProgress="75"/> ⑦ … <!--包含按鈕欄--> <include android:id="@+id/button_bar2" layout="@layout/button_bar"/> … <!--包含按鈕欄--> <include android:id="@+id/button_bar3" layout="@layout/button_bar"/> … <ProgressBar android:id="@+id/progress_horizontal03" style="? android:attr/progressBarStyleHorizontal" ⑧ android:layout_width="200dip" android:layout_height="wrap_content" android:indeterminate="true"/> ⑨ </LinearLayout>

圖7-25 條狀進度欄實例
上述代碼第①行是設置系統主題無關的水平條狀進度欄。而代碼第④行和第⑧行是設置系統主題相關的水平條狀進度欄。
由于id為progress_horizontal01和progress_horizon-tal02的進度欄都是可確定進度的,因此需要知道設定最大值屬性android:max,見代碼第②行和第⑤行;當前進度an-droid:progress屬性見代碼第③行和第⑥行。另外,progress_horizontal02的進度欄有兩層進度欄,需要設定android:sec-ondaryProgress屬性,見代碼第⑦行。
id為progress_horizontal03的進度欄是不可確定進度的,需要android:indeterminate屬性設置為true,見代碼第⑨行。而android:max、android:progress和android:second-aryProgress這些屬性對于它沒有意義,不需要設定。
說明 布局文件activity_main.xml中使用include標簽的原因是界面中有三組-和+按鈕,形式上完全一樣,功能類似。因此將-和+兩個按鈕在另外一個布局button_bar.xml中聲明。然后,在三個不同的地方通過include標簽載入。這樣,減少維護-和+兩個按鈕布局的工作量。
聲明-和+兩個按鈕的布局文件button_bar.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"> <Button android:id="@+id/decrease" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/progressbar_1_minus"/> <Button android:id="@+id/increase" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/progressbar_1_plus"/> </LinearLayout>
MainActivity.java代碼如下:
public class MainActivity extends AppCompatActivity{ @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); … final ProgressBar progressHorizontal02 =(ProgressBar) findViewById(R.id.progress_ horizontal02); //獲取被包含按鈕欄button_bar2 LinearLayout buttonBar2 =(LinearLayout) findViewById(R.id.button_bar2); ① Button bar2IncreaseButton=(Button) buttonBar2.findViewById(R.id.increase); ② bar2IncreaseButton.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ progressHorizontal02.incrementProgressBy(1); ③ } }); Button bar2DecreaseButton=(Button) buttonBar2.findViewById(R.id.decrease); ④ bar2DecreaseButton.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ progressHorizontal02.incrementProgressBy(-1); ⑤ } }); //獲取被包含按鈕欄button_bar3 LinearLayout buttonBar3 =(LinearLayout) findViewById(R.id.button_bar3); Button bar3IncreaseButton=(Button) buttonBar3.findViewById(R.id.increase); ⑥ bar3IncreaseButton.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ progressHorizontal02.incrementSecondaryProgressBy(1); ⑦ } }); Button bar3DecreaseButton=(Button) buttonBar3.findViewById(R.id.decrease); ⑧ bar3DecreaseButton.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ progressHorizontal02.incrementSecondaryProgressBy(-1); ⑨ } }); } }
上述代碼第③行和第⑤行是通過進度欄的incrementProgressBy方法增加和減少第一層進度欄的進度。代碼第⑦行和第⑨行是通過進度欄的incrementSecondaryProgressBy方法增加和減少第二層進度欄的進度。
說明 在布局文件activity_main.xml中加載的button_bar.xml布局文件中聲明了-和+兩個按鈕,它們的id是decrease和increase,如何獲得這些按鈕對象?解決辦法是先通過MainActivity的findViewById方法,獲得這些按鈕所在的父視圖(LinearLayout)對象,然后通過調父視圖對象的findViewById方法獲得按鈕對象。例如,上述代碼第①行findViewById(R.id.button_bar2)是獲得父視圖對象,參數id是在布局文件activity_main.xml的include android:id="@+id/button_bar2"layout="@layout/button_bar"/ 代碼中聲明的,代碼第②行是調用父視圖對象buttonBar2的findViewById獲得+按鈕。代碼第④行是獲得buttonBar2中-按鈕,代碼第⑥行是獲得buttonBar3中的+按鈕。
7.6.3 實例2:圓形進度欄
圓形進度欄一般應用在不可確定進度的任務,不需要設置android:max、android:progress和android:secondaryProgress等屬性。
下面通過實例了解它們的使用情況。實例如圖7-26所示,屏幕中有兩個界面圓形進度欄和一個ToggleButton,通過單擊ToggleButton可以隱藏或顯示進度欄。

圖7-26 圓形進度欄實例
布局文件activity_main.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"> <ProgressBar android:id="@+id/progressBar1" style="? android:attr/progressBarStyleLarge" ① android:layout_width="wrap_content" android:layout_height="wrap_content"/> <ProgressBar android:id="@+id/progressBar2" style="@android:style/Widget.ProgressBar.Small" ② android:layout_width="wrap_content" android:layout_height="wrap_content"/> <ToggleButton ③ android:id="@+id/toggleButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textOff="隱藏" ④ android:textOn="顯示"/> ⑤ </LinearLayout>
上述布局文件聲明了兩個進度欄,代碼第①行是設置progressBar1進度欄樣式中與系統主題有關的大圓形進度欄,代碼第②行設置progressBar2進度欄樣式中與系統主題無關的小圓形進度欄。
代碼第③行聲明了ToggleButton來實現進度欄隱藏和顯示兩種狀態的切換。由于ToggleButton默認兩種狀態的標題是OFF或NO,手機設置為中文顯示是“關閉”或“開啟”,但是本例中需要顯示“隱藏”或“顯示”。
MainActivity.java代碼如下:
public class MainActivity extends AppCompatActivity{ @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ProgressBar progressBar1 =(ProgressBar) findViewById(R.id.progressBar1); final ProgressBar progressBar2 =(ProgressBar) findViewById(R.id.progressBar2); final ToggleButton button=(ToggleButton) findViewById(R.id.toggleButton); button.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ boolean checked = button.isChecked(); if(checked){ progressBar1.setVisibility(ProgressBar.GONE); ① progressBar2.setVisibility(ProgressBar.INVISIBLE); ② }else{ progressBar1.setVisibility(ProgressBar.VISIBLE); ③ progressBar2.setVisibility(ProgressBar.VISIBLE); ④ } } }); } }
上述代碼第①、②、③、④行都是通過setVisibility方法設置進度欄的隱藏或顯示,setVisibility方法中的參數有三個:
? ProgressBar.VISIBLE。顯示,見代碼第③和④行。
? ProgressBar.INVISIBLE。隱藏,占有空間。例如,上述代碼progressBar2設置ProgressBar.INVISIBLE,結果如圖7-26(b)所示,按鈕頂部的空白是隱藏的progressBar2。
? ProgressBar.GONE。隱藏,不占有空間。例如,上述代碼progressBar1設置ProgressBar.GONE,結果如圖7-26(b)所示,按鈕位置向上一段距離,事實上這個距離是progressBar1的高度。
- Advanced Quantitative Finance with C++
- Design Principles for Process:driven Architectures Using Oracle BPM and SOA Suite 12c
- Python量化投資指南:基礎、數據與實戰
- 騰訊iOS測試實踐
- Cocos2d-x游戲開發:手把手教你Lua語言的編程方法
- 樂學Web編程:網站制作不神秘
- Java FX應用開發教程
- 硅谷Python工程師面試指南:數據結構、算法與系統設計
- HTML5從入門到精通(第4版)
- Building Serverless Web Applications
- Modernizing Legacy Applications in PHP
- Python 3快速入門與實戰
- Isomorphic Go
- Python GUI設計tkinter菜鳥編程(增強版)
- Continuous Integration,Delivery,and Deployment