Monday, December 17, 2012

Android beginner tutorial: Part 23 - ProgressBar

In this tutorial we'll learn how to use the ProgressBar widget.

There are 3 main slider and indicator classes in Android. Those are ProgressBar, RatingBar and SeekBar. Today we'll cover the first of the three.

A ProgressBar is used to display the progress of a usually long process, for example, downloading or uploading of a file. This process is being run in a separate thread, so we will need to use a Handler to connect that thread with our ProgressBar. We've covered Handlers in the previous tutorial.

The four main commonly used methods of the ProgressBar class are setProgress(), getProgress(), incrementProgressBy() and setMax().

The setProgress() method sets the progress value of the process.

The getProgress() method returns that value.

The incrementProgressBy() method adds to the progress value.

The setMax() mehod sets the maximum limit for the progress value.

Let's create a simple application that creates a background Thread, which is a simple process that increases the progress bar's value by 1 each 100 milliseconds, until the value reaches the default maximum 100.

Go to activity_main.xml and add a TextView and a ProgressBar with these values:

<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"
    android:gravity="center"
    tools:context=".MainActivity" >
    
    <TextView android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        />

    <ProgressBar android:id="@+id/progress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="?android:attr/progressBarStyleHorizontal"
        />
    
</LinearLayout>

Note that I've set the style attribute of the ProgressBar object. This makes sure that the ProgressBar becomes a horizontal progress bar.

Now go to the MainActivity.java class.

First of all, declare 2 new variables that will later reference the existing progress bar and text view:

private ProgressBar progressBar;
private TextView textView;

Declare a handler object, which has a handleMessage() function, that increases the value of progress bar by 1 and updates the text:

private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg){
progressBar.incrementProgressBy(1);
textView.setText("Progress: " + progressBar.getProgress() + "%");
}
};

Now, find the onCreate() function. Here, after the 2 default lines of code, set values to progressBar and textView:

progressBar = (ProgressBar)findViewById(R.id.progress);
textView = (TextView)findViewById(R.id.text);

After tgat set the progress of the progress bar to 0:

progressBar.setProgress(0);

Then we create a new Thread. Call it background, and set its value to an instance of the Thread class. Inside the parameter of the constructor, add an anonymous Runnable class instance, which includes a function called run(). The run() method is a method that is run once by default. To make it run multiple times, we can add a loop inside of it. Add a while() loop that executes cycles if the progress of the progress bar is less than 100. Add a try...catch statement that makes the Thread sleep() for 100 milliseconds, and in case of error, log the error using the Log.e() method. After the statement, send a message to the handler. It doesn't really carry any important data, but it does make the handler execute its handleMessage() function.

Thread background = new Thread(new Runnable(){
public void run(){
while(progressBar.getProgress()<100){
try{
Thread.sleep(100);
}catch(InterruptedException e){
Log.e("ERROR", "Thread has been interrupted");
}
handler.sendMessage(handler.obtainMessage());
}
}
});

Then we start the background thread:

background.start();

Full class:

package com.kircode.codeforfood_test;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainActivity extends Activity{

private ProgressBar progressBar;
private TextView textView;
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg){
progressBar.incrementProgressBy(1);
textView.setText("Progress: " + progressBar.getProgress() + "%");
}
};

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

progressBar = (ProgressBar)findViewById(R.id.progress);
textView = (TextView)findViewById(R.id.text);

progressBar.setProgress(0);

Thread background = new Thread(new Runnable(){
public void run(){
while(progressBar.getProgress()<100){
try{
Thread.sleep(100);
}catch(InterruptedException e){
Log.e("ERROR", "Thread has been interrupted");
}
handler.sendMessage(handler.obtainMessage());
}
}
});
background.start();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}

}

Test the application on a device or an emulator and you'll see something similar to this:


Thanks for reading!

No comments:

Post a Comment