How to show a ProgressBar example with percentage in Android
Asked Answered
G

3

10

I have a task to add a ProgressBar with percentage values on it to show a value when the user wants to predict something. I'm not using ProgressDialog since it's now deprecated. Here, the percentage value depends on how long it is from start a request until it's completed. I'm using Volley to fetch data from server.

Here goes a sample image of what I'm trying to achieve:

ProgressBar Percentage Value

i already did like this

i have implement a horizontal progress bar inside an alert dialog (i'm using this way because progress dialog is deprecated). i want to setProgress the progress bar like this.

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    view =  inflater.inflate(R.layout.fragment_result_prediction, container, false);
    predictProgress = (ProgressBar) view.findViewById(R.id.progressbarPredict);
    AlertDialog.Builder(view.getContext());
    builder.setCancelable(false); // if you want user to wait for some process to finish,
    View v = inflater.inflate(R.layout.layout_loading_dialog, null);
    builder.setView(v);
    final AlertDialog dialog = builder.create();
    submitPredictPlant.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
                dialog.show();
                predictProgress.setProgress(25);
                predictProgress.setProgress(50);
                predictProgress.setProgress(75);
                predictProgress.setProgress(100);
                dialog.dismiss();

i want to dismiss the dialog when the progress is 100. but this give an error like

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ProgressBar.setProgress(int)' on a null object reference

i already refer the progress bar from layout_loading_dialog that is used in builder.setview.

here is the layout_loading_dialog.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<TextView
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_weight="4"
    android:gravity="center"
    android:text="Please wait! This may take a moment." />

<ProgressBar
    android:layout_width="match_parent"
    android:id="@+id/progressbarPredict"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    style="?android:attr/progressBarStyleHorizontal"/>

Glasgow answered 17/6, 2019 at 8:35 Comment(6)
Hi and welcome on SO. Please read How to Ask and minimal reproducible exampleBroglie
dont use progressDialog as it is deprecated, you can use progress barAdenocarcinoma
can you check my question again ? i already add some code, thxGlasgow
yeah, creating one with progress barAdenocarcinoma
now the problem is i getting null object reference when i want to setprogress the progress bar on layout_loading_progress.xmlGlasgow
kindly check the below code, it will auto dismiss when prgress equal to 100Adenocarcinoma
A
10

Following is the code to create a progress dialog with percentage like in the picture.

int status = 0;
Handler handler = new Handler();

public void showDialog(Activity activity, String msg) {
    final Dialog dialog = new Dialog(activity);
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    dialog.setCancelable(false);
    dialog.setContentView(R.layout.dialog);

    final ProgressBar text = (ProgressBar) dialog.findViewById(R.id.progress_horizontal);
    final TextView text2 = dialog.findViewById(R.id.value123);


    new Thread(new Runnable() {
        @Override
        public void run() {
            while (status < 100) {

                status += 1;

                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                handler.post(new Runnable() {
                    @Override
                    public void run() {

                        text.setProgress(status);
                        text2.setText(String.valueOf(status));

                        if (status == 100) {
                            dialog.dismiss();
                        }
                    }
                });
            }
        }
    }).start();


    dialog.show();

    Window window = dialog.getWindow();
    window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
}

Layout File : dialog

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical">

<ProgressBar
    android:id="@+id/progress_horizontal"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="16dp" />

<RelativeLayout
    android:layout_width="wrap_content"
    android:paddingLeft="20dp"
    android:layout_margin="16dp"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/value123"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
      />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/value123"
        android:text="%" />
</RelativeLayout>

Result :

enter image description here With Asyntask :

int status = 0;
Handler handler = new Handler();
Dialog dialog;
ProgressBar text;
TextView text2;

public void showDialog(Activity activity, String msg) {
    dialog = new Dialog(activity);
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    dialog.setCancelable(false);
    dialog.setContentView(R.layout.dialog);

    text = (ProgressBar) dialog.findViewById(R.id.progress_horizontal);
    text2 = dialog.findViewById(R.id.value123);


    dialog.show();

    Window window = dialog.getWindow();
    window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);

    new Thread(new Runnable() {
        @Override
        public void run() {
            while (status < 100) {

                status += 1;

                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                handler.post(new Runnable() {
                    @Override
                    public void run() {

                        text.setProgress(status);
                        text2.setText(String.valueOf(status));

                        if (status == 100) {
                            status = 0;
                        }
                    }
                });
            }
        }
    }).start();

}


private class AsyncTaskRunner extends AsyncTask<String, String, String> {

    @Override
    protected String doInBackground(String... params) {


        // it will fill the progress bar to 100
        // and will refill again and again



        /*
         *
         * Make your api call here
         * MAke request to API and return data when response comes
         *
         *
         * */

        /*
        * 
        * I have just add sleep to thead for example purposes
        * 
        * */
        try {
            Thread.sleep(30 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return resp;
    }


    @Override
    protected void onPostExecute(String result) {


        /*
         *
         *
         * Do your processing there on the api result
         *
         *
         * */
        dialog.dismiss();
    }


    @Override
    protected void onPreExecute() {
        showDialog(MainActivity.this,"");

    }


    @Override
    protected void onProgressUpdate(String... text) {

    }
}

For start the Asyntask :

    new AsyncTaskRunner().execute("fs");

I am not sure if this is the best approach

Adenocarcinoma answered 17/6, 2019 at 9:11 Comment(9)
but progress dialog is deprecated is it okay to use it ?Glasgow
it will auto dismiss when progress is equal to 100Adenocarcinoma
now if i want to use this percentage progress bar when i want to do a request into server using volley. how to make it 100% until i got the request json string (that means the request is successfull). thanksGlasgow
use asyntask, show the dialog on on onPreExecute and make a volley call in the doInBackgoround, and on postExecute dismiss the dialogAdenocarcinoma
use global variable so you can access it in the asyntaskAdenocarcinoma
so in onPreExecute i declare all the code you give except the thread and setProgress(0),then in the doInBackground i call a function to request to the server and in postExecute i set the progress to 100 and then dismiss the dialog then intent to a new page ? am i correct ?Glasgow
but where should i update the progress ? in your code it use thread to update it, how about in asyntask ?is it update it self ?Glasgow
In your first code, is it safe to be updating the progress inside the thread? Shouldn't you do that on the UI thread?Thereon
We have a handler, which is communicating with UI.Adenocarcinoma
P
2

If anyone is looking for a circular Progress bar with percentages, here is the Kotlin version.

class PercentageProgressBar : ProgressBar {

    private lateinit var textPaint: Paint
    private lateinit var circlePaint: Paint
    private var currentProgress = 0

    constructor(context: Context) : super(context) {
        init()
    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        init()
    }

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        init()
    }

    private fun init() {
        setWillNotDraw(false)

        circlePaint = TextPaint(Paint.ANTI_ALIAS_FLAG)
        val whileColor = ContextCompat.getColor(context, android.R.color.white)
        circlePaint.color = whileColor

        textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)
        val blackColor = ContextCompat.getColor(context, android.R.color.black)
        textPaint.color = blackColor
        textPaint.textSize = 20F
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val w = MeasureSpec.getSize(widthMeasureSpec)
        val h = MeasureSpec.getSize(heightMeasureSpec)
        val size = w.coerceAtMost(h)
        setMeasuredDimension(size, size)
    }

    private val r: Rect = Rect()

    override fun onDraw(canvas: Canvas) {

        val circleX = (width / 2).toFloat()
        val circleY = (height / 2).toFloat()
        val radius = (width / 2.5).toFloat()
        canvas.drawCircle(circleX, circleY, radius, circlePaint);

        // https://mcmap.net/q/117371/-android-center-text-on-canvas
        val textToPrint = "$currentProgress %"
        canvas.getClipBounds(r)
        val cHeight: Int = r.height()
        val cWidth: Int = r.width()
        textPaint.textAlign = Paint.Align.LEFT
        textPaint.getTextBounds(textToPrint, 0, textToPrint.length, r)
        val x: Float = cWidth / 2f - r.width() / 2f - r.left
        val y: Float = cHeight / 2f + r.height() / 2f - r.bottom
        canvas.drawText(textToPrint, x, y, textPaint)
        super.onDraw(canvas)
    }

    override fun setProgress(progress: Int) {
        super.setProgress(progress)
        
        // Hide when progress is 100
        if (progress == 100) {
            visibility = View.GONE
            return
        }
        currentProgress = progress
        invalidate()
    }
}
Poniard answered 14/7, 2021 at 11:50 Comment(2)
How to use it please?Ninnette
@زياد use it as you would use the default ProgressBar.Poniard
C
0

I used this method

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="16dp">



    <ProgressBar
        android:id="@+id/dialog_progress_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        style="?android:attr/progressBarStyleHorizontal"
        android:indeterminate="false"
        android:progress="0"
        />

    <TextView
        android:id="@+id/progress_percentage_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/dialog_progress_bar"
        android:layout_alignParentStart="true"
        android:text="0%"
        android:textSize="16sp"/>

    <TextView
        android:id="@+id/total_number_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/dialog_progress_bar"
        android:layout_alignParentEnd="true"
        android:text="0/0"
        android:textSize="16sp"/>

</RelativeLayout>

 percentageTextView.setText((int)(((double)progress / total) * 100) + "%");
 totalNumberTextView.setText(progress + "/" + total);
Cida answered 11/3 at 8:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.