How to add a Progress Bar in a PreferenceFragment in Android? - android

How can I add a progress bar in a PreferenceFragment? I have some async task running that will display some values in my preference upon completion. So while it is doing the background process, I plan to show only a progress bar in the center. After the task is complete, then I plan to show all my preferences.
Here's what I have so far.
PreferenceFragment
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_account);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
new AsyncTask<Void,Void,Void>() {
String firstName, lastName, email;
#Override
protected void doInBackground() {
// Doing something here to fetch values
}
#Override
protected void onPostExecute() {
findPreference("first_name").setSummary(firstName);
findPreference("last_name").setSummary(lastName);
findPreference("email").setSummary(email);
}
}
}
pref_account.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<Preference android:key="first_name"
android:title="#string/prompt_first_name"
android:summary="" />
<Preference android:key="last_name"
android:title="#string/prompt_last_name"
android:summary="" />
<Preference android:key="email"
android:title="#string/prompt_email"
android:summary=""
android:inputType="textEmailAddress" />
<Preference android:key="sign_out"
android:title="#string/action_sign_out" />
</PreferenceScreen>
My question is, since this is a PreferenceFragment and I'm not overriding the method onCreateView, where and how should I add the progress bar?

Here's what I did:
Create a custom Preference class:
public class LoadingPreference extends Preference {
public LoadingPreference(Context context){
super(context);
setLayoutResource(R.layout.preference_loading_placeholder);
}
}
Create a custom Layout (preference_loading_placeholder) while preserving the Preference layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:paddingEnd="?android:attr/scrollbarSize"
android:background="?android:attr/selectableItemBackground" >
<ImageView
android:id="#+android:id/icon"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_gravity="center"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dip"
android:layout_marginEnd="6dip"
android:layout_marginTop="6dip"
android:layout_marginBottom="6dip"
android:layout_weight="1">
<!-- (start) I added this part. -->
<ProgressBar
android:id="#+id/progressBar"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateTintMode="src_atop"
android:indeterminateTint="#color/colorAccent"
android:layout_gravity="center" />
<TextView
android:id="#+id/progressTitle"
android:text="#string/loading"
android:textSize="24sp"
android:textColor="#color/colorAccent"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:layout_toLeftOf="#+id/progressBar" />
<!-- (end) I added this part. -->
<TextView android:id="#+android:id/title"
android:layout_width="0dp"
android:layout_height="0dp"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceLarge"
android:ellipsize="marquee"
android:fadingEdge="horizontal" />
<TextView android:id="#+id/summary"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_below="#android:id/title"
android:layout_alignStart="#android:id/title"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
android:maxLines="4" />
</RelativeLayout>
<!-- Preference should place its actual preference widget here. -->
<LinearLayout android:id="#+id/widget_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical"/>
</LinearLayout>
Used a PreferenceCategory to hold my loading preference:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<SwitchPreference
android:key="#string/pref_key_wifi_enabled"
android:title="#string/pref_title_wifi_enabled"
android:summary="#string/pref_summary_wifi_enabled" />
<Preference
android:key="#string/pref_key_wifi_refresh"
android:title="#string/pref_title_wifi_refresh"
android:summary="#string/pref_summary_wifi_refresh"
android:dependency="#string/pref_key_wifi_enabled"/>
<PreferenceCategory
android:key="#string/pref_key_wifi_section"
android:title="#string/pref_title_wifi_section"
android:summary="#string/pref_summary_wifi_section"
android:dependency="#string/pref_key_wifi_enabled"/>
</PreferenceScreen>
Put the loading preference where needed
((PreferenceCategory)findPreference(WIFI_OPTIONS_SECTION_KEY)).addPreference(new LoadingPreference(getActivity()));
Remove the loading preference after loading is complete:
((PreferenceCategory)findPreference(WIFI_OPTIONS_SECTION_KEY)).removeAll();
Add other preferences after loading is complete:
Preference p = new Preference(getActivity());
p.setTitle("...");
p.setSumary("...")
((PreferenceCategory)findPreference(WIFI_OPTIONS_SECTION_KEY)).addPreferece(p);

I had a similar use case and I used a custom layout for the preference.
In the preference fragment file I had (non relevant attributes are omitted)
<!-- res/xml/somePref.xml -->
<PreferenceScreen>
<PreferenceCategory>
...
<Preference android:widgetLayout="#layout/customLayout" />
...
</PreferenceCategory>
</PreferenceScreen>
Then in the custom layout I placed the progress bar by itself
<!-- res/layout/customLayout.xml -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/progress"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminateOnly="true" />
</RelativeLayout>
Before starting the async task I call
findViewById(R.id.progress).setVisibility(View.VISIBLE)
and when the task is done I set the visibility back to gone. This will allow you to set each preference independently without having to wait for each one to complete. Hope this helps.

I ended up using the following approach.
In my fragment_account.xml layout file.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="#+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</RelativeLayout>
Then on my class:
public class AccountFragment extends PreferenceFragment {
private ListView mListView;
private ProgressBar mProgressBar;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_account, container, false);
mListView = (ListView) view.findViewById(android.R.id.list);
mProgressBar = (ProgressBar) view.findViewById(R.id.progress_bar);
showProgress();
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
addPreferencesFromResource(R.xml.pref_account);
hideProgress();
}
private void showProgress() {
mListView.setVisibility(View.GONE);
mProgressBar.setVisibility(View.VISIBLE);
}
private void hideProgress() {
mListView.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
}
}
}

You could try to apply the following solution:
Use fragments in your preference activity.
When you need to display preferences - display preference fragment.
When you need to display progress - display progress fragment.
Here is a code excerpt:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
showPreferences();
// or call showProgress, launch your task and call showPreferences upon completion
}
private void showPreferences() {
runOnUiThread(new Runnable() {
#Override
public void run() {
getFragmentManager()
.beginTransaction()
.replace(android.R.id.content, new YourPreferenceFragment())
.commit();
}
});
}
private void showProgress() {
runOnUiThread(new Runnable() {
#Override
public void run() {
getFragmentManager()
.beginTransaction()
.replace(android.R.id.content, new YourProgressFragment())
.commit();
}
});
}

Use this approach. Create one Dialog with a custom layout which a progressBar in it and just call show() and dismiss().
#Synchronized
fun showLoader(activity: Activity) {
val activityWeakReference = WeakReference(activity)
if (activityWeakReference.get() != null) {
hideLoader()
dialog = Dialog(activityWeakReference.get()!!, android.R.style.Theme_Translucent)
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
dialog?.setContentView(R.layout.progress_indicator)
dialog?.setCancelable(false)
dialog?.show()
}
}
#Synchronized
fun hideLoader() {
dialog?.dismiss()
dialog = null
}

Use the following concept in AsyncTasks default Methods
private class MyAsynTask extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialog();// show your progressbar
}
#Override
protected String doInBackground(String... urls) {
//your code
}
protected void onProgressUpdate(String... progress) {
progressDialog.setProgress(Integer.parseInt(progress[0]));
// here you get the value of progress
}
#Override
protected void onPostExecute(String result) {
dismissDialog(); //dismiss progressbar
}
}

Related

How to reach Custom Preferences items from Fragment?

In my application Settings Layout i need custom preference for profile Category. I searched and done something .
pref.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="Profil">
<Preference
android:key="custom"
android:title="My Custom Preferenece"
android:layout="#layout/custom">
</Preference>
<Preference
android:icon="#drawable/transparency"
android:key="email"
android:selectable="false"
android:summary=""
android:title="Email"
/>
custom.xml (i used for preference layout)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#android:color/white"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:orientation="horizontal"
>
<android.support.v7.widget.AppCompatImageView
android:id="#+id/custom_image"
android:layout_width="100dp"
android:layout_height="50dp"
android:src="#drawable/no_photo"
android:textColor="#color/black"
/>
<android.support.v7.widget.AppCompatTextView
android:id="#+id/custom_text"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="Custom Text"
android:textColor="#color/black"
android:gravity="center"
/>
</LinearLayout>
I want to reach and set android:id="#+id/custom_image" or android:id="#+id/custom_text" , i didn't reach these items from my fragment.
How can i reach these items from fragment ?
Thank you
My fragment
public class GeneralPreferenceFragmentN extends PreferenceFragment {
private Context mContext;
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_main);
mContext = getActivity().getApplicationContext();
bindPreferenceSummaryToValue(findPreference("phone"));
private static void bindPreferenceSummaryToValue(Preference preference)
{
preference.setOnPreferenceChangeListener(
sBindPreferenceSummaryToValueListener);
SharedPreferences prefs = preference.getSharedPreferences();
Object value;
if (preference instanceof MultiSelectListPreference) {
value = prefs.getStringSet(preference.getKey(), new HashSet<String>
());
} else {
value = prefs.getString(preference.getKey(), "");
}
..................
Try this:
in your onCreate() initialize the view:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_abschliessen_einsatz, container, false);
//#INFO: Create a global View v element if you want to use the view in other funtions (for example on slected and so on). Otherwise just use
this.v = v;
//#INFO: Otherwise just use th View elemnt to to find by ID
myCustomImage = (AppCompatImageView) v.findViewById(R.id.custom_image);
myCustomText = (AppCompatTextView) v.findViewById(R.id.custom_text);
//Set Text or do stuff with the elements afterwards
return v;
}
//Use the view in other fuctions, ex. onSelcted
#Override
public void onSelected() {
//update UI when selected
//#INFO: Use the global View elemnt to to find by ID
myCustomImage = (AppCompatImageView) v.findViewById(R.id.custom_image);
myCustomText = (AppCompatTextView) v.findViewById(R.id.custom_text);
//Set Text or do stuff with the elements afterwards
}

Android pre`loading Activity

I have a question regarding the loading of the first Activity in my App. Before loading it, app shows this screen: https://www.dropbox.com/s/r33n3u3xfmth345/Screenshot_2013-08-16-12-02-08.png , and what I would like, is to load directly my Activity.
I'll mention that Im using SherlockActivity, and I already tried setting the Theme both in Manifest or programatically in onCreate() of my Activity, with same result (pre-loads with that screen for 2-3 secs, then loads my Activity).
Any thoughts ?
You have to use the splash screen Activity and after that you have to start your own activity from that Splash screen Activity.
Here is the code for splashActivity.
public class SplashActivity extends Activity {
private int splashTime = 3000;
private Thread thread;
private ProgressBar mSpinner;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
mSpinner = (ProgressBar) findViewById(R.id.Splash_ProgressBar);
mSpinner.setIndeterminate(true);
thread = new Thread(runable);
thread.start();
}
public Runnable runable = new Runnable() {
public void run() {
try {
Thread.sleep(splashTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
startActivity(new Intent(SplashActivity.this,YourActivityName.class));
finish();
} catch (Exception e) {
// TODO: handle exception
}
}
};
}
Here is code for activity_spalsh.xml file .....
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#48AD83"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginBottom="20dp"
android:layout_marginTop="10dp"
android:gravity="center_horizontal"
android:text=" your app name "
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#A52A2A" />
<ProgressBar
android:id="#+id/Splash_ProgressBar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView1"
android:layout_centerInParent="true"
android:layout_marginTop="5dp" />
</RelativeLayout>

Unclickable button set on a preference activity

I just set a button on a preference activity from one the answers from this question. My main issue is that this button is unclickable while the other elements of the preference activity is click able.
I created a simple example to demonstrate my dilemma it should show the same symptoms as you copy and paste.
public class preferenceTest extends PreferenceActivity{
private Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getFragmentManager().beginTransaction().replace(android.R.id.content, new MyPreferenceFragment()).commit();
button = (Button)findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "I got clicked", Toast.LENGTH_SHORT).show();
}
});
}
public static class MyPreferenceFragment extends PreferenceFragment
{
#Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preftest);
// Do Stuff
}
}
}
res\layout\activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ListView android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textColor="#android:color/black"
android:layout_weight="10"/>
<Button android:text="This is a button on bottom of all preferences."
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/button"
android:textColor="#android:color/black"
android:layout_weight="1"/>
</LinearLayout>
res\xml\preftest.xml
<PreferenceCategory
android:title="New Title"
android:summary="Title">
<ListPreference
android:key="list1"
android:title="List one"
android:summary="List1"
/>
<ListPreference
android:key="list2"
android:title="List two"
android:summary="List2"/>
</PreferenceCategory>
<CheckBoxPreference
android:key="check1"
android:title="check1"
android:summary="CheckBox Test"/>
</PreferenceScreen>
I'm not sure why you would want to add a button in a PreferenceActivity, but what you can do is add a plain Preference and then make that clickable through the activity code.
For instance, on your preferences.xml
<Preference
android:key="#string/pref_key_dummy_pref_button"
android:title="#string/pref_title_dummy_pref_button" />
Then, on your PreferenceActivity, create a Preference object:
Preference mDummyButtonPref;
Initialize it from onCreate:
addPreferencesFromResource(R.xml.preferences);
mDummyButtonPref= findPreference(getString(R.string.pref_key_dummy_pref_button));
Then, add override onPreferenceTreeClicked to handle clicks:
#Override
#Deprecated
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
Preference preference) {
if (preference == mDummyButtonPref) {
Log.v(TAG, "Dummy got clicked");
}
}

ProgressBar just wont show up and show any kind of progress

I have been trying for a while now, Have looked at a few SO posts, and got to this stage. I am sure I am very close to getting it working, but am missing something very basic.
Code Snippets of the activity below
public class SearchResultsMap extends MapActivity {
....
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.searchresultsmap);
...
busy = (LinearLayout) findViewById(R.id.busy);
busy.bringToFront();
progressBar = (ProgressBar) findViewById(R.id.progressBar) ;
progressBar.bringToFront() ;
searchResponse = (HashMap<Integer, CustomJourneyUserInformation>) this.getIntent()
.getSerializableExtra("searchResponse");
new GetProviderAndUserDetails(this).execute(null);
>>edit1 progressBar.setMax(searchResponse.size());
>>edit1 progressBar.setProgress(0) ;
...
}
//Inner Class, type AsyncTask
public class GetProviderAndUserDetails extends AsyncTask<String, Integer, Object> {
public GetProviderAndUserDetails(Activity mapActivity) {
this.mapActivity = mapActivity;
}
protected void onPreExecute() {
busy.setVisibility(View.VISIBLE);
setProgressBarVisibility(true) ;
setProgressBarIndeterminate(true) ;
setProgressBarIndeterminateVisibility(true) ;
}
#Override
protected void onProgressUpdate(Integer... progress) {
if (searchActivity != null) {
searchActivity.setProgress(progress[0]);
>>edit1 progressBar.setProgress(progress[0]) ;
}
}
#Override
protected Object doInBackground(String... args) {
...
//for loop, i
publishProgress(i) ;
//end for loop
...
}
protected void onPostExecute(Object result) {
super.onPostExecute(result);
busy.setVisibility(View.GONE);
setProgressBarVisibility(false) ;
setProgressBarIndeterminate(false) ;
setProgressBarIndeterminateVisibility(false) ;
...
}
}
Layout XML File
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:id="#+id/busy"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:gravity="center_horizontal"
android:orientation="vertical"
android:visibility="visible" >
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyleLarge"
android:indeterminateOnly="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp" />
</LinearLayout>
.....
<com.google.android.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/searchMap"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="#id/tip"
android:layout_alignParentTop="true"
android:apiKey="mykey"
android:clickable="true" />
....
</RelativeLayout>
Device Results : Unable to upload to stackoverflow. Some SO issue.
searchresults image
You're calling setProgressBarIndeterminate() and related functions, which act on your activity's title, not on the progress bar in your layout.
Use progressBar.setIndeterminate() and friends instead.
EDIT: And if you want a progress bar instead of the indeterminate progress indicator, use setIndeterminate(false).
Setting the style to progressBarStyleHorizontal in the xml worked finally. Seems like progressBarStyleLarge cant show progress.
Also the indeterminate thing helped.

Android progressbar in button

Is there any possibility to show a spinning progress bar in a button?
e.g. as background drawable?
I was having the same problem, so I created a specialized button for this: LoadingProgressButton
Include the button like this:
<br.com.simplepass.loading_button_lib.CircularProgressButton
android:id="#+id/btn_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/circular_border_shape"
app:spinning_bar_width="4dp" <!-- Optional -->
app:spinning_bar_color="#FFF" <!-- Optional -->
app:spinning_bar_padding="6dp" <!-- Optional -->
And use it like this:
CircularProgressButton btn = (CircularProgressButton) findViewById(R.id.btn_id)
btn.startAnimation();
[do some async task. When it finishes]
//You can choose the color and the image after the loading is finished
btn.doneLoagingAnimation(fillColor, bitmap);
[or just revert de animation]
btn.revertAnimation();
Yes.
You can create an AnimationDrawable, as described here, and then use the drawableLeft tag (for example) in your button's XML. like so:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/your_background_drawable_resource"
android:drawableLeft="#drawable/your_animation_drawable_resource"
android:text="#string/your_text_res">
</Button>
Yes... Just wrap around both the button and progressBar inside a Relative Layout, like so...
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="1">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/progressBar"
android:layout_gravity="right"
android:layout_alignTop="#+id/btnConnect"
android:layout_alignRight="#+id/btnConnect"
android:layout_alignEnd="#+id/btnConnect" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Connect"
android:id="#+id/btnConnect"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:width="200dp"
android:focusable="false"
android:focusableInTouchMode="false" />
</RelativeLayout>
<TextView
android:id="#+id/txtConnectStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/btnConnect"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="Status : Not connected"
android:textSize="12dp"
android:layout_gravity="center_horizontal" />
<LinearLayout
android:orientation="vertical"
Wanted to post the sample image, but I don't have enough reputation just yet... ;)
I made a sample code like below..
I hope that my codes help you :)
[main.xml]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
>
<Button
android:id="#+id/wheel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/icon_spin_animation"
/>
</LinearLayout>
[icon_spin_animation.xml]
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/selected" android:oneshot="false">
<item android:drawable="#drawable/wheel_db_update01" android:duration="50"/>
<item android:drawable="#drawable/wheel_db_update02" android:duration="50"/>
<item android:drawable="#drawable/wheel_db_update03" android:duration="50"/>
<item android:drawable="#drawable/wheel_db_update04" android:duration="50"/>
<item android:drawable="#drawable/wheel_db_update05" android:duration="50"/>
<item android:drawable="#drawable/wheel_db_update06" android:duration="50"/>
</animation-list>
[Activity Code]
public class ProgressOnTheButtonActivity extends Activity implements OnClickListener {
/** Called when the activity is first created. */
AnimationDrawable mFrameAnimation = null;
boolean mbUpdating = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btnWheel = (Button)findViewById(R.id.wheel_button);
btnWheel.setOnClickListener(this);
mFrameAnimation = (AnimationDrawable) btnWheel.getBackground();
}
public void onClick(View v) {
if(v.getId() == R.id.wheel_button) {
if(!mbUpdating) {
mbUpdating = true;
new AsyncTaskForUpdateDB().execute("");
}
}
}
private class AsyncTaskForUpdateDB extends AsyncTask<String, Integer, ResultOfAsyncTask> {
#Override
protected void onPreExecute() {
mFrameAnimation.start();
super.onPreExecute();
}
#Override
protected ResultOfAsyncTask doInBackground(String... strData) {
ResultOfAsyncTask result = new ResultOfAsyncTask();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return result;
}
#Override
protected void onPostExecute(ResultOfAsyncTask result) {
mFrameAnimation.stop();
mbUpdating = false;
}
#Override
protected void onCancelled() {
mFrameAnimation.stop();
mbUpdating = false;
super.onCancelled();
}
#Override
protected void onProgressUpdate(Integer... progress) {
}
}
private class ResultOfAsyncTask {
int iErrorCode = 0;
}
}
To make Animatable drawables work, you need to extend the Button class and call Animatable.start() for drawables. I've made an implementation for this:
package com.example.yourapplication;
import android.content.Context;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.AppCompatButton;
import android.util.AttributeSet;
public class AnimateCompoundDrawableButton extends AppCompatButton {
public AnimateCompoundDrawableButton(Context context) {
super(context);
}
public AnimateCompoundDrawableButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AnimateCompoundDrawableButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom) {
super.setCompoundDrawables(left, top, right, bottom);
startIfAnimatable(left);
startIfAnimatable(top);
startIfAnimatable(right);
startIfAnimatable(bottom);
}
#Override
public void setCompoundDrawablesRelative(Drawable start, Drawable top, Drawable end, Drawable bottom) {
super.setCompoundDrawablesRelative(start, top, end, bottom);
startIfAnimatable(start);
startIfAnimatable(top);
startIfAnimatable(end);
startIfAnimatable(bottom);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
// Makes a copy of the array, however we cannot do this otherwise.
for (Drawable drawable : getCompoundDrawables()) {
startIfAnimatable(drawable);
}
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
// Makes a copy, however we cannot do this otherwise.
for (Drawable drawable : getCompoundDrawables()) {
stopIfAnimatable(drawable);
}
}
private void startIfAnimatable(Drawable drawable) {
if (drawable instanceof Animatable) {
((Animatable) drawable).start();
}
}
private void stopIfAnimatable(Drawable drawable) {
if (drawable instanceof Animatable) {
((Animatable) drawable).stop();
}
}
}
I have solved this problem by this way: first I have added progressBar and Button to common FrameLayout.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="75dp"
android:background="#color/white"
android:layout_marginRight="20dp"
android:layout_marginLeft="20dp">
<Button
android:id="#+id/buttonOnOff"
android:layout_width="match_parent"
android:layout_height="75dp"
android:text="Включить"
android:layout_gravity="center"
android:visibility="visible"
android:textColor="#FFFFFF"
android:onClick="onClickIn"
tools:ignore="OnClick" />
<ProgressBar
android:id="#+id/loading"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_gravity="center"
android:indeterminate="true"
android:indeterminateTintMode="src_atop"
android:theme="#style/ActionBarProgress"
/>
</FrameLayout>
And after that I have turned on and turned off visibility of progressBar and changed text of Button where I need it.
final Button buttonOnOff = findViewById(R.id.buttonOnOff);
final ProgressBar pB = findViewById(R.id.pB);
buttonOnOff.setEnabled(false);
buttonOnOff.setText("");
pB.setVisibility(false);
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();
...
With Jetpack Compose you can use something like:
var progressIndicatorVisible by remember { mutableStateOf(false) }
Button(onClick = {
scope.launch {
progressIndicatorVisible = true
// Just for example
delay(5000)
progressIndicatorVisible = false
}
}, modifier = Modifier.animateContentSize()){
if (progressIndicatorVisible) {
CircularProgressIndicator(
color = White,
strokeWidth = 2.dp,
modifier = Modifier.size(15.dp)
)
}
Text ("Button",
modifier = Modifier.padding(start = if (progressIndicatorVisible) 8.dp else 0.dp))
}

Categories

Resources