หัดเขียน Android: การใช้งาน Progress Bar ใน Android
เนื่องจาก ProgressDialog กำลังจะถูกเลิกใช้ใน android api v 26 ซึ่งจะมีการปรับเปลี่ยนให้มาใช้ Progress Bar แทนวันนี้เลยมาเขียนบทความการใช้งานเจ้า Progress Bar สักหน่อย
ก่อนอื่นต้องบอกว่าเจ้า ProgressDialog นั้นถือว่าใช้งานง่ายแต่มันจะมีปัญหาพวก null exception บ่อยๆในจังหวะการกดใช้งาน app ในบาง cycle เพราะฉะนั้นทาง google เลยทำการเลิกใช้ตั้งแต่ api v 26 แล้วให้มาใช้เจ้า Progress bar แทนซึ่งผมมองว่าใช้งานไม่ได้ยากขึ้นเลย แถมยังลดปัญหาพวก null exception ได้เยอะเลยที่เดียว เอาละมาเริ่มกันเลยที่กว่า
เจ้า Progress bar นั้นมีวิธีการใช้ที่ดูจะ simple มากขึ้นให้ทำการสร้าง control ใน layout เลย ในตัวอย่างนี้ผมทำการใช้ project ใหม่ชื่อว่า SimpleProgressBar โดยมี layout ของ MainActivity ดังนี้ครับ
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <ProgressBar android:id="@+id/progress_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPrimary" android:layout_centerInParent="true" style="@android:style/Widget.ProgressBar.Inverse" android:visibility="gone"/> <TextView android:id="@+id/txt_progress" android:layout_height="wrap_content" android:layout_width="match_parent" android:gravity="center" android:textColor="@android:color/white" android:layout_centerInParent="true" android:visibility="gone" /> <Button android:id="@+id/btn_open_progress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Open Progress"/> <Button android:id="@+id/btn_hide_progress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/btn_open_progress" android:text="Hide Progress"/> </RelativeLayout>
ส่วนนั้นโค้ด MainActivity.java มีโค้ดดังนี้ครับ
package com.example.com.simpleprogressbar; import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ProgressBar progressBar = (ProgressBar)findViewById(R.id.progress_bar); final TextView txt_progress = (TextView)findViewById(R.id.txt_progress); Button btn_open_progress = (Button)findViewById(R.id.btn_open_progress); btn_open_progress.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { progressBar.setVisibility(View.VISIBLE); txt_progress.setVisibility(View.VISIBLE); txt_progress.setText("Please Wait"); } }); Button btn_hide_progress = (Button)findViewById(R.id.btn_hide_progress); btn_hide_progress.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { progressBar.setVisibility(View.GONE); txt_progress.setVisibility(View.GONE); } }); } }
จากโค้ดทั้ง layout และ MainActivity นั้นจะเห็นว่าผมทำการสร้าง progressbar ใน layout แล้วสั่ง visible เป็น gone เอาไว้เพื่อไม่ให้กินเนื้อที่ของ control อื่น จากนั้นเมื่อมาฝั่ง code ก็ทำการอ้างอิง control โดย findViewById ปกติแล้วเมื่อกดปุ่ม btn_open_progress ให้ทำการ setVisible เป็น View.VISIBLE ทั้ง Progressbar และ TextView ที่เอาไว้แสดงข้อความ แต่ถ้ากดปุ่ม btn_hide_progress นั้นก็แค่ทำการ setVisible กลับไปเป็น GONE ดังในโค้ดด้านบนครับ จะเห็นว่าการใช้งาน progressbar นั้นแค่ set ค่าต่างๆ แล้ว set ให้แสดงกับซ่อนแค่นั้นเองครับ
จุดสังเกตในไฟล์ layout นั้นคือ
style="@android:style/Widget.ProgressBar.Inverse"
ซึ่งจะเป็นรูปแบบการโหลดของ progressbar ซึ่งแบบในตัวอย่างจะเป็นวงกลมหมุนแบบทั่วไป โดย style ของ progressbar หลักๆจะมีดังนี้
- Horizontal
- Small
- Large
- Inverse
- Small.Inverse
- Large.Inverse
ท่านสามารถอ่านเพิ่มเติ่มได้ที่ ProgressBar
จากตัวอย่างเมื่อลองกดรันดูจะได้ผลลัพธ์ดังนี้


ตัวอย่างต่อมาจะเป็นการใช้ ProgressBar แบบ Horizontal ซึ่งจะเป็น bar โหลด โดยมีการเปลี่ยนแปลงโค้ด layout ของ ProgressBar ดังนี้
<ProgressBar android:id="@+id/progress_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPrimary" android:layout_centerInParent="true" style="@style/Widget.AppCompat.ProgressBar.Horizontal" android:indeterminate="true" android:visibility="gone"/>
จะเห็นมามีการใช้ style ของ Widget.AppCompat ซึ่งใหม่กว่าแบบตัวอย่างแรก และมีการเพิ่ม android:indeterminate=”true” ซึ่งจะเป็นการกำหนดค่าการโหลดของ bar ให้เป็นอิสระไม่แน่นอน เมื่อลองรันจะได้ผลลัพธ์ดังรูป
จะห็นว่า bar มันจะโหลดวนไปเรื่อยๆแต่หากเราต้องการกำหนด percent การโหลดของ bar นั้นต้องทำการกำหนด
android:indeterminate="false"
แล้วทำการ setProgress ในโค้ด java เอา ซึ่งโดยทั่วไปแล้วการ setProgress ต้องทำการสร้าง task มารันแยกจาก task หลักเพื่อให้ทำงานคู่กันไปได้โดยมีโค้ดดังนี้ครับ
package com.example.com.simpleprogressbar; import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private int progressStatus = 0; private Handler handler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ProgressBar progressBar = (ProgressBar)findViewById(R.id.progress_bar); final TextView txt_progress = (TextView)findViewById(R.id.txt_progress); Button btn_open_progress = (Button)findViewById(R.id.btn_open_progress); btn_open_progress.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { progressBar.setVisibility(View.VISIBLE); txt_progress.setVisibility(View.VISIBLE); txt_progress.setText("Please Wait"); progressBar.setMax(100); progressBar.setMin(0); progressStatus = 0; new Thread(new Runnable() { @Override public void run() { while(progressStatus < 100){ // Update the progress status progressStatus +=1; // Try to sleep the thread for 20 milliseconds try{ Thread.sleep(20); }catch(InterruptedException e){ e.printStackTrace(); } // Update the progress bar handler.post(new Runnable() { @Override public void run() { progressBar.setProgress(progressStatus); // Show the progress on TextView txt_progress.setText(progressStatus+""); } }); } } }).start(); // Start the operation } }); Button btn_hide_progress = (Button)findViewById(R.id.btn_hide_progress); btn_hide_progress.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { progressBar.setVisibility(View.GONE); txt_progress.setVisibility(View.GONE); } }); } }
จากโค้ดจะเห็นมามีการ setProgress และ Min = 0, Max = 100 แล้วมีการสร้าง Thread มารันพร้อมกันแล้ว มีการ set sleep เพื่อให้จะได้เห็นการเปลี่ยนแปลงได้ทัน และมีการเซ็ตค่า txt_progress เป็น percent ที่เพิ่มขึ้นอีกด้วย เมื่อลองรันจะได้ผลลัพธ์ดังรูป
ยังไงก็ลองศึกษาและลองเล่นกันดูนะครับ
Download SourceCode