How to use setProgressDrawable() correctly? - android

I am having problem with setting a new Drawable to my ProgressBar.
If I use the setProgressDrawable() inside onCreate() method it works great. But when I try to call the same method inside a Handler post callback it doesn't work and the progressbar disapears.
Can someone explain this behaviour? How can I solve this problem?

downloadingBar.setProgress(0);
Drawable progressDrawable = getResources().getDrawable(R.drawable.download_progressbar_pause_bg);
progressDrawable.setBounds(downloadingBar.getProgressDrawable().getBounds());
downloadingBar.setProgressDrawable(progressDrawable);
downloadingBar.setProgress(mCurrentPercent);
First you should reset the progress to zero
Set the progress drawable bounds
Set new progress drawable
Set new progress

Bumped into this problem myself and I managed to get it working :)
I used the AsyncTask to handle the background tasks/threads, but the idea should be the same as using Runnable/Handler (though AsyncTask does feel nicer imo).
So, this is what I did... put setContentView(R.layout.my_screen); in the onPostExecute method! (ie. instead of the onCreate method)
So the code looks something like this:
public class MyScreen extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.my_screen); !!! Don't setContentView here... (see bottom)
new MySpecialTask().execute();
}
private int somethingThatTakesALongTime() {
int result;
// blah blah blah
return result;
}
private void updateTheUiWithResult(int result) {
// Some code that changes the UI
// For exampe:
TextView myTextView = (TextView) findViewById(R.id.result_text);
myTextView.setText("Result is: " + result);
ProgressBar anyProgressBar = (ProgressBar) findViewById(R.id.custom_progressbar);
anyProgressBar.setProgressDrawable(res.getDrawable(R.drawable.progressbar_style));
anyProgressBar.setMax(100);
anyProgressBar.setProgress(result);
}
private class MySpecialTask extends AsyncTask<String, Void, Integer> {
ProgressDialog mProgressDialog;
#Override
protected void onPreExecute() {
mProgressDialog = ProgressDialog.show(MyScreen.this, "", "Calculating...\nPlease wait...", true);
}
#Override
protected Integer doInBackground(String... strings) {
return somethingThatTakesALongTime();
}
#Override
protected void onPostExecute(Integer result) {
mProgressDialog.dismiss();
setContentView(R.layout.my_screen); // setContent view here... then it works...
updateTheUiWithResult(result);
}
}
}
To be honest, why you need to call setContentView in onPostExecute I have no idea... but doing so means you can set custom styles for your progress bars (and they don't disappear on you!)

Maybe you put the code in a thread which is not main thread.
If you want to work with the UI, you must do that in the main thread :)

I was also facing the same issue but in my case it is due to the use of Drawable.mutate() method. When i removed that method it started working fine. I also noticed that this issue exist below api level-21(lollipop).

Related

Android setContentView suppressed by AsyncTask in onCreate

I want to show some message and a progress bar while my app initializes.
I need to insert some dictionaries of words into a SQLite database the first time my app is run. To do this I have an AsyncTask which opens my SQLiteOpenHelper and closes it again, just so the database initialization is done once.
private class AsyncDbInit extends AsyncTask<Void, Void, Void> {
private Context context;
private Intent intent;
public AsyncDbInit(Context context, Intent intent){
this.context = context;
this.intent = intent;
}
#Override
protected Void doInBackground(Void... params) {
DatabaseHandler db = new DatabaseHandler(this.context);
db.close();
return null;
}
#Override
protected void onPostExecute(Void param) {
context.startActivity(this.intent);
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... params) {}
}
This AsyncTask is called in my onCreate() method, but I've also tried to run it from onStart() and onResume() without succes.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dispatcher);
... //some code finding the right intent
new AsyncDbInit(this, nextIntent).execute();
}
Somehow this last line, which calls the AsyncTask, stops my UI from showing up; the screen just stays blank until the AsyncTask is completed and the new activity is started.
When I comment that line out, the UI shows up just fine.
The only thing I can come up with is that the SQLiteOpenHelper somehow blocks the UiThread, but I couldn't find anything about that either.
In the AsyncTask we have some methods. Just like in doInBackground() we do the things we wants to be done in the background and there are two methods also whch are onPreExecute() and onPostExecute(). Create and progress dialog and show the dialog in onPreExecute() method and dismiss it in onPostExecute() method.
Try using AsynTask.executeOnExecutor() with the thread pool executor. If this works, it means something involved with loading your UI is also using an AsyncTask. AsyncTasks by default run sequentially on a single work thread and this can introduce contention. This serial execution is often what you want, but not always.
Does you UI use any libraries to load strings or other content? Can you provide your layout XML?

One activity, two views. How and where do I inflate the second view?

I have an activity that can show two different layouts. Both of the layouts are pre-defined (XML). Basically, if a condition is met, then layout A should be displayed. If the condition fails, then layout B should be displayed.
Layout A is a simplistic Linear Layout - it's my main "form", so to speak.
Layout B is a simplistic Relative Layout - it's a placeholder until some data can be downloaded. Once the data is downloaded (and a notification is sent), then I want to remove Layout B and display Layout A.
I've tried calling the invalidate() method on Layout B in the onResume() method of my Activity but that doesn't work.
I'm not sure what approach I should take, in (1) where to "correctly" switch the layouts, and (2) how I should go about displaying it. I'm assuming I need to inflate Layout A when my condition is met, but I'm not 100% sure about that.
Edit:
Snipped of my onCreate() method:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layoutA); // will happen 99% of the time
...
if (!dbHelper.tableIsPopulated()) {
setContentView(R.layout.layoutB); // show placeholder bc no data exists
getData();
}
}
Unless you have a reason to not use a background Thread, I suggest using an AsyncTask and using a progress bar. It will be less costly than using a dummy Layout just as a placeholder until you get the data. And you said it won't be used but 1% of the time. Seems like a waste in my opinion
public class TalkToServer extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
#Override
protected String doInBackground(String... params) {
//do your work here
return something;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// do something with data here-display it or send to mainactivity
}
You apparently know about AsyncTask but Here are the Docs for future visitors and it has an example of using the ProgressDialog.
Note
Since it isn't an inner class you will just need to pass your Context to the constructor of your AsyncTask if you are going to show your ProgressDialog from there.

Android loading circle

I need to show standard loading circle on half-opaque background above current layout (with background and buttons etc). I found ProgressBar and how it works, but I need to render it on existing layout, and that's the problem.
To be more clear - imagine login screen with some image and button aka "Register". On click I need to show partly visible black background and a loading circle.
Try and see if this works (use it as an inner class)
private class executeHospitalNameGet extends AsyncTask<String, Void, Void> {
private ProgressDialog Dialog = new ProgressDialog(SettingsActivity.this);
private Context mContext;
public executeHospitalNameGet(Context context) {
mContext = context;
}
protected void onPreExecute() {
Dialog.setMessage("Getting Hospitals...");
Dialog.setTitle("Requesting Hospital Name");
Dialog.show();
}
protected Void doInBackground(String... urls) {
//DO WORK HERE
return null;
}
protected void onPostExecute(Void unused) {
Dialog.dismiss();
}
}
You would call it with this
new executeHospitalNameGet(getApplicationContext()).execute();
Use a RelativeLayout, It will allow you to have overlapping Views, check out this link:
http://developer.android.com/reference/android/widget/RelativeLayout.html
I think you're looking for something like modal dialog with loading animation...
check it out this... http://developer.android.com/guide/topics/ui/dialogs.html#ProgressDialog

how to control indeterminate progress bar in title when pressing back button and going to previous activity

So im trying to use a indeterminate progressbar in my custom title header to show any background work. Right now um using an asynctask to show and hide the progressbar using the pre and post methods:
Here's the class that contains everything:
public abstract class QuadrosMobileActivity extends Activity{
protected static volatile ProgressBar progressHeader = null;
protected static int progressBarstate=ProgressBar.INVISIBLE;
//this method will launch respejcting oncreate logic for each activity
public abstract void initActivity();
public int getProgressBarstate(){
return progressBarstate;
}
public void setProgressBarstate(int state){
progressBarstate=state;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
//set theme first for showing correct header
setTheme(getThemeId());
super.onCreate(savedInstanceState);
//in case the screen will have a header
if(getThemeId()!=R.style.CustomThemeNoHeader){
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(getLayoutId());
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_window_title);
//set text header
((TextView)findViewById(R.id.header_title)).setText(getWindowTitle());
progressHeader= (ProgressBar) findViewById(R.id.progresspinner);
progressHeader.setVisibility(getProgressBarstate());
}else {
setContentView(getLayoutId());
}
//execute activity logic
initActivity();
}
private class ProgressBarThread extends AsyncTask<Void, Void, Void>{
#Override
protected void onPreExecute() {
progressHeader.setVisibility(ProgressBar.VISIBLE);
setProgressBarstate(ProgressBar.VISIBLE);
}
#Override
protected Void doInBackground(Void... params) {
updateResultsInUi();
return null;
}
#Override
protected void onPostExecute(Void result) {
progressHeader.setVisibility(View.INVISIBLE);
setProgressBarstate(View.INVISIBLE);
}
}
}
This is my main activity class where all my screen subactivities extend from.
The problem i have is, if i start the asynctask, the progressbar gets visible(all in Activity A) and while this happens if i go to another activity(B), the progressbar still appears correctly and gets hidden when the background work ends, all correct behaviour. BUT if i press the back button the previous activity(A) shows with the progressbar visible.
Here's a simple diagram:
start Activity A:
launches asynctask
shows progressbar
does background work
go to Activity B:
progressbar still shows
ends background work
hides progressbar *correct behaviour
go back to Activity A:
progressbar is visible *incorrect behaviour
...
I tried this on the onResume method:
#Override
protected void onResume() {
super.onResume();
if(getThemeId()!=R.style.CustomThemeNoHeader){
System.out.println("visible: " + ProgressBar.VISIBLE+" : " + getProgressBarstate());
progressHeader.setVisibility(getProgressBarstate());
};
}
But to no avail, can i really use the onResume to alter the progressbar state when pressing the back button???
This the method i tried:
#Override
public void onRestart ()
{
super.onRestart();
if (getThemeId() != R.style.CustomThemeNoHeader)
{
Toast.makeText(this, "visible(0): " + ProgressBar.VISIBLE+" : Current :" + getProgressBarstate(),Toast.LENGTH_LONG).show();
// doesnt work
QuadrosMobileActivity.progressHeader.setVisibility(getProgressBarstate());
// works
((TextView)findViewById(R.id.header_title)).setText("Tretas");
}
}

Progress bar problem in android

I have create an android quiz application where i loaded all of question from web service. For this in oncreate method i wrote following
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.testlayoutforimage);
loadControls();
getPassingValue();
ParserMethod parserMethod=new ParserMethod();
//questionsObj=parserMethod.parseQuestionDetailsFor(passingFeature,numOfQuestion,passingSubject,passingChapter);
questionsObj=parserMethod.parseQuestionImages(passingSubject,passingFeature,passingChapter;
}
But problem is that when the question is loaded it take some time .
I want to add a progress bar. When the page is loaded then the progress is shown and the question is load . After that the bar is remove and Display the ques .how can i do this.
Using AsyncTask.. just like below.. code is not exactly right.. its just to give an idea..
classs backgrnd extends Asynctask{
protected object onPreExecute(){
//display dialog
}
protected object doInBackgroung(Object... arg){
//fetch data
}
protected object onPostExecute(Object result){
//dismiss dialog
}
}
You can Use AsyncTask class for this.The class is designed so that you can do something in the background.It has overridden method onPreExecute where you can show the ProgressDialog and on doInBackground method load your question.On preExecute method cancel the dialog and update your UI

Categories

Resources