So I'm trying to create a progress bar for achievements in my application. These progress bars should show their progresses once the activity opens. I'm familiar with regular progress bars in which you update your list status and setprogress on the progress bar, but somehow I couldn't manage to complete this task. In below code, I tried to create a progress bar that fills up to 30/100 and then stops, as if the "achievement progress" was 30. For the ease of understanding, I'm working with simple integers. Current behaviour is not even close, as the progress bar is just spinning without any progress update. Note that the progress is not related to any other component other than simple integers.
Edit: This is the behaviour I want: https://dribbble.com/shots/2758323-Ring-Progress
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_points);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
progressBar.setIndeterminate(false);
new TimedProgress();
}
class TimedProgress {
Timer timer;
public TimedProgress() {
timer = new Timer();
timer.schedule(new ProgressTask(), 0, 500);
}
class ProgressTask extends TimerTask {
int progress = 0;
public void run() {
if (progress <30) {
updateProgress(progress);
progress++;
} else {
timer.cancel();
}
}
}
}
public void updateProgress(final int progress) {
if (null != progressBar) {
progressBar.setVisibility(View.VISIBLE);
progressBar.setProgress((int) progress);
}
}
Layout:
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/progressBar"
android:layout_centerVertical="true"
android:layout_alignParentEnd="true"/>
Use a timer to count the progress steps, e.g. every 1/2 second (500 ms). Here is a basic java timer that you can have fun converting into an AsyncTask for Android! Execute the AsyncTask, and every 1/2 second the timer will update the progress bar.
class TimedProgress {
Timer timer;
public TimedProgress() {
timer = new Timer();
timer.schedule(new ProgressTask(), 0, 500);
}
class ProgressTask extends TimerTask {
int progress = 0;
public void run() {
if (progress <30) {
updateProgress(progress);
progress++;
} else {
timer.cancel();
}
}
}
}
public void updateProgress(final int progress) {
if (null != progressBar) {
progressBar.setVisibility(View.VISIBLE);
progressBar.setProgress((int) progress);
}
}
Related
I am new to android, don't have much experience to manage threads. I am working on an activity where I want to display progress bar for say 5 seconds and then repeat. During those 5 seconds, I will display some text for the user to work on the text. I want to repeat this for say N times.
Currently, I have the following code that works for 1 such progress. I tried looping it but it didn't help, as threads executed at same time. How can I repeat this for N number of times? Am I on the correct path in order to solve my the problem?
public class test extends Activity {
private ProgressBar progressBar;
private int progressStatus = 0;
private TextView textView;
private Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_loop);
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
textView = (TextView) findViewById(R.id.textView1);
progressBar.setScaleY(3f);
// Start long running operation in a background thread
for(int i=0; i<5; i++)
Progress();
}
public void Progress(){
new Thread(new Runnable() {
public void run() {
while (progressStatus < 100) {
progressStatus += 1;
// Update the progress bar and display the
//current value in the text view
handler.post(new Runnable() {
public void run() {
progressBar.setProgress(progressStatus);
textView.setText(progressStatus+"/"+progressBar.getMax());
}
});
try {
// Sleep for 200 milliseconds.
//Just to display the progress slowly
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
I am not sure I would recommend using the pattern you are following but here is the way to get the threads to run one after another rather than all at the same time:
public void progress(final int numberOfRuns) {
if (numberOfRuns <= 0 ) {
return;
}
new Thread(new Runnable() {
public void run() {
while (progressStatus < 100) {
progressStatus += 1;
// Update the progress bar and display the
//current value in the text view
handler.post(new Runnable() {
public void run() {
progressBar.setProgress(progressStatus);
textView.setText(progressStatus + "/" + progressBar.getMax());
// For the UI Changes. Eg update the loop number
myTextView.setText(Integer.toString(totalLoop));
}
});
try {
// Sleep for 200 milliseconds.
//Just to display the progress slowly
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
progressStatus = 0;
totalLoop = totalLoop+1;
progress(numberOfRuns - 1);
}
}).start();
}
then just call progress(numberOfRuns), no need for any loops.
In one activity of my app, there are an imagview and a textview that are changing every 3 seconds.
I first set this up with a handler and thread runnable. It works fine, but when I use removeCallbacks with the pause button, it will not pause in the middle of the Thread. It completes the Thread runnable before pausing. I need it to pause when the button is clicked no matter where it is in the runnable.
I thought about using an asynctask but I'm not sure how this would work.
I know there has to be a way to do this, as you can pause almost any game you download. Does anyone have any suggestions on the best/easiest way to do this?
Thanks so much!! :)
public class Workout extends AppCompatActivity {
private String[] messages = {"1", "2", "3", "4", "5"};
final Handler handler = new Handler();
private int nextIndex;
String mDrawableName[] = {"bodypart70", "equipment70", "settings70", "time70", "bodypart70"};
private int nextImage;
ImageView image;
private ProgressBar progressBar;
private int progressStatus = 0;
Runnable r = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.workout);
image = (ImageView) findViewById(R.id.exerciseImage);
final TextView text = (TextView)findViewById(R.id.textView4);
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
//changing
r = new Runnable(){
#Override
public void run(){
if (messages.length > nextIndex) {
//change textview
text.setText(messages[nextIndex++]);
//change image
int resID = getResources().getIdentifier(mDrawableName[nextImage++] , "drawable", getPackageName());
image.setImageResource(resID);
//restart progress bar
progressStatus = 0;
progress();
//do it after 3 seconds
handler.postDelayed(this, 3000);
}
}
};
handler.postDelayed(r, 0);
}
public void progress(){
new Thread(new Runnable() {
public void run() {
long timerEnd = System.currentTimeMillis() + 3 * 1000;
while (timerEnd > System.currentTimeMillis()) {
progressStatus = 3 - (int) (timerEnd - System.currentTimeMillis()) / 1000;
// Update the progress bar
handler.post(new Runnable() {
public void run() {
progressBar.setProgress(progressStatus);
}
});
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Log.w("App", "Progress thread cannot sleep");
}
}
}
}).start();
}
public void pauseWorkout(View view){
handler.removeCallbacks(r);
}
public void resumeWorkout(View view){
handler.postDelayed(r, 0);
}
}
It looks like the while-loop in your progress() function is still working after you press your pause button.
Try the following: Create a global boolean that indicates you're in a paused or resuming state. Put it at the top of your code:
boolean resume = true;
Update your while condition in progress()
while (resume && timerEnd > System.currentTimeMillis()) {
Update your workout functions:
public void pauseWorkout(View view){
handler.removeCallbacks(r);
resume = false;
}
public void resumeWorkout(View view){
handler.postDelayed(r, 0);
resume = true;
}
I have to wait some seconds in my Android App and I want to show a progress bar during this time, how can I do this?
for example :
#Override
protected void onCreate(Bundle savedInstanceState) {
timeForShow(5 //second);
}
.
.
.
private void timeForShow(long mytime){
myprogress.setVisibility(View.VISIBLE);
Waiting for mytime...
myprogress.setVisibility(View.GONE);
}
this is my code but it does not work:
Long timerforprogressbar ;
#Override
protected void onCreate(Bundle savedInstanceState) {
timerforprogressbar = (long) 5000 ;
new MyProgressBar().execute((Void)null);
}
.
.
.
class MyProgressBar extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
progressbar.setVisibility(View.VISIBLE);
try {
Thread.sleep(timerforprogressbar);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
progressbar.setVisibility(View.GONE);
}
}
my progress bar :
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:indeterminateDrawable="#drawable/progress" >
</ProgressBar>
progressbar is my progress bar,plz help me,tnx.
For your specific use case it would be simpler to use a Handler:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
progressbar.setVisibility(View.GONE);
}
}, timerforprogressbar);
You did not mention how your progressbar is constructed but if you simply want an indeterminate progress to show, then constructing it programatically would be the most simple thing to do I think.
private ProgressDialog working_dialog;
private void showWorkingDialog() {
working_dialog = ProgressDialog.show(context, "","Working please wait...", true);
}
private void removeWorkingDialog() {
if (working_dialog != null) {
working_dialog.dismiss();
working_dialog = null;
}
}
That would make the code look like:
showWorkingDialog();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
removeWorkingDialog();
}
}, timerforprogressbar);
You can always use the CountDownTimer:
public void timer() {
countDownTimer=new CountDownTimer(20000, 1000) { //display a delay of 20 seconds
public void onTick(long millisUntilFinished) {
if (somethingToBreakTheCount)
countDownTimer.onFinish();
txtDebug.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
txtDebug.setText("Done!");
finish();
}
}.start();
}
// We can achieve this by using Coroutines.
// Simply start a coroutine and change the progress of progressbar by changing the dispatcher context after few milliseconds.
// Here I am showing the progress for 1 second before moving to next fragment.
CoroutineScope(Dispatchers.IO).launch {
for (i in 0..100) {
delay(10)
withContext(Dispatchers.Main) {
binding.progressBar.progress = i
}
}
//Navigate to next fragment using nav contorller or with Intents for next Activity
navController.navigate(R.id.action_startFragment_to_listFragment)
}
Updating progress dialog in Activity from AsyncTask
There re is a method for async tasks for progress updates.
Here is a link to a better post on it
As a simpler solution than an AsyncTask, you can always look into using a CountDownTimer for this action.
If you are performing a task in AsyncTask doInBackground(), then you can initiate your progressBar in onPreExecute() and disable it in onPostExecute().
How to bring a progress bar on clicking a button in an activity i have an button in my main activity and if i click the button i want to display a progress bar i dont wanna use a secondary activity for this i have done with 2 activities but i need it to be done in main activity itself.
thank you
My code:
Home Activity :
public void load(View v){
Intent intent = new Intent(this,Splash.class);
this.startActivity(intent);
}
Splash Activity :
public class Splash extends Activity {
private long ms = 0;
private long splashTime = 20000;
private boolean splashActive = true;
private boolean paused = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
Thread mythread = new Thread() {
public void run() {
try {
while (splashActive && ms < splashTime) {
if (!paused)
ms = ms + 100;
sleep(100);
}
} catch (Exception e) {
} finally {
Intent intent = new Intent(Splash.this, Home.class);
startActivity(intent);
}
}
};
mythread.start();
}
}
You can do like this
ProgressDialog progress;
progress = new ProgressDialog(this);
progress.setTitle("Please Wait!!");
progress.setMessage("Wait!!");
progress.setCancelable(true);
progress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progress.show();
call this code where you want to display your ProgressBar.
There is one more method to show the ProgressBar on Button Click.
Put this code in your xml
<ProgressBar
android:id="#+id/progressBar1"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible" />
and just write following code on your Button click in java file.
progressBar.setVisibility(View.VISIBLE);
It will show the Progressbar on your Button Click.
I believe the user2306156 will not be in need of this now, hopefully someone who is looking for this will be glad to know i guess.
put this code in your xml
<ProgressBar
style="#android:style/Widget.Material.Light.ProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/checkBox"
android:layout_centerHorizontal="true"
android:layout_marginTop="57dp"
android:id="#+id/progressBar" />
put this in your activity code
spinner=(ProgressBar)findViewById(R.id.progressBar);
spinner.setVisibility(View.GONE);
and this in your onClick of the activity code
spinner.setVisibility(View.VISIBLE);
See this Android Progress Bar Example
public class MyAndroidAppActivity extends Activity {
Button btnStartProgress;
ProgressDialog progressBar;
private int progressBarStatus = 0;
private Handler progressBarHandler = new Handler();
private long fileSize = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
addListenerOnButton();
}
public void addListenerOnButton() {
btnStartProgress = (Button) findViewById(R.id.btnStartProgress);
btnStartProgress.setOnClickListener(
new OnClickListener() {
#Override
public void onClick(View v) {
// prepare for a progress bar dialog
progressBar = new ProgressDialog(v.getContext());
progressBar.setCancelable(true);
progressBar.setMessage("In Progress ...");
progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressBar.setProgress(0);
progressBar.setMax(100);
progressBar.show();
//reset progress bar status
progressBarStatus = 0;
//reset filesize
fileSize = 0;
new Thread(new Runnable() {
public void run() {
while (progressBarStatus < 100) {
// process some tasks
progressBarStatus = doSomeTasks();
// your computer is too fast, sleep 1 second
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Update the progress bar
progressBarHandler.post(new Runnable() {
public void run() {
progressBar.setProgress(progressBarStatus);
}
});
}
// ok, file is downloaded,
if (progressBarStatus >= 100) {
// sleep 2 seconds, so that you can see the 100%
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// close the progress bar dialog
progressBar.dismiss();
}
}
}).start();
}
});
}
// file download simulator... a really simple
public int doSomeTasks() {
while (fileSize <= 1000000) {
fileSize++;
if (fileSize == 100000) {
return 10;
} else if (fileSize == 200000) {
return 20;
} else if (fileSize == 300000) {
return 30;
}
// ...add your own
}
return 100;
}
}
Another Option is to use the nifty Spezi-Views, it contains a ProgressButton which is quite easy to use:
<de.halfreal.spezi.views.ProgressButton
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Press me"
app:selectedText="I am loaded"
app:unselectedText="Press me again"
app:loadingDrawable="#drawable/spinner"
/>
and in code:
...
//show a rotation spinner, and no text (or the loading text)
progressButton.enableLoadingState();
//show no animation, but the selected/ unselected text
progressButton.disableLoadingState();
...
Can it possible to make a button on screen which automatically visible and gone every 5sec interval?
By using this
b.setVisibility(View.VISIBLE);
we can visible and
b.setVisibility(View.GONE);
we can hide it.But I can't manage to make it by usin the time interval.
Any idea?please share.
There are a few different ways, one is a Handler and Runnable:
public class Example extends Activity {
private Handler mHandler = new Handler();
private Runnable alternate = new Runnable() {
public void run() {
// Alternate visible and not
mHandler.postDelayed(alternate, 5000);
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mHandler.postDelayed(alternate, 5000);
}
}
Use this
new CountDownTimer(9000000, 5000) {
public void onTick(long millisUntilFinished) {
if(b.getVisibility() == View.GONE)
b.setVisibility(View.VISIBLE);
else
b.setVisibility(View.GONE);
}
public void onFinish() {
//Restart timer if you want.
}
}.start();