I've a settings fragment which load a xml with a default settings page, I also added one click listener to one specific preference
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.settings);
preferences.findPreference(getString(R.string.pref_custom_list)).setOnPreferenceChangeListener(this);
//other stuff.....
this works fine, when user clicks triggers an event and i can check some info about the switch including deny the change...
But i would like to turn on/off other switches in the same screen when this even happen
i tried to
preferences.findPreference(getString(R.string.xpto)).setEnabled(true);
but it doesn't turn any switch on or off... it just set the view enabled or disabled for clicks
if i do something like
PreferenceManager.getDefaultSharedPreferences(this).edit().putBoolean("xpto",true).apply();
It does change the preference, but the changes are not loaded to the screen so user doesn't know
how can i switch some preference on or off programatically and make it reflect to the preference screen
You can use SwitchPreferenceCompat.
<SwitchPreferenceCompat
app:key="key"
app:title="Some Confs" />
Try this in your fragment if you are using SwitchPreferenceCompat as above.
SwitchPreferenceCompat switchPref = findPreference("key");
switchPref.setChecked(true);
You're looking for setChecked(), not setEnabled():
preferences.findPreference(getString(R.string.xpto)).setChecked(true);
I think you need to implement a listener when the SharedPreferences change.
SharedPreferences.OnSharedPreferenceChangeListener spChanged = new
SharedPreferences.OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
// change the Switch Preference state here
}
};
Then when the prefs change, you can change the user's screen to match it.
For your reference:
How to detect if changes were made in the preferences?
Related
I'm trying to create a very basic preferences activity, extending PreferenceActivity. In the documentation, I read:
The PreferenceActivity automatically persists the settings associated with each Preference when the user makes a change.
However, when I:
Change a setting (any setting)
Close the app
Remove the app from the recently used list
Relaunch the app
The setting is reset to the default value, which seems to conflict the quoted documentation above. Do I misunderstand something here, is the template faulty, or do I perhaps need additional permissions or other settings to use the PreferenceActivity auto-persist feature?
public class SettingsActivity extends PreferenceActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsFragment()).commit();
}
public static class SettingsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
}
And preferences.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference
android:key="pref_language_reading"
android:title="#string/pref_title_language_dailyreading"
android:entries="#array/pref_languages_dailyreading_entries"
android:entryValues="#array/pref_languages_dailyreading_values"
android:defaultValue="#string/pref_language_dailyreading_default"
android:persistent="true" />
</PreferenceScreen>
The strings and arrays exist, and I can select a language properly. The setting is saved when I go to another activity, and then back. But closing the app and relaunching discards the saved value.
When I read out the SharedPreference corresponding to this preference (before relaunching), I see the correct setting. After relaunching, the SharedPreference does not exist anymore though.
The code should work. There is likely something else in your code that causes this behaviour.
In my specific case, it turned out there was a line
PreferenceManager.getDefaultSharedPreferences(this).edit().clear().commit();
In the onCreate() method of the main Activity, causing the SharedPreferences to clear on every launch of the app.
I have a main activity that loads a PreferenceFragment (its part of an actionBar).
Within the PreferenceFragment I load my preferences from a XML File:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
}
The Problem is if I change the Tab (remember it is getting managed by an ActionBar), change one of the preferences in a different fragment and coming back to my preferenceFragment its not getting updated. Particularly the problem is a SwitchPreference(true/false) which can be changed from different fragments and even by remote calls (then the preference is getting changed in shared preferences. YES I did commit the change).
I searched for different solutions, but to be honest I didn´t find a working one.
My own ideas are the following:
My Problem would be solved if I could get the Switch Element of the switch, so I could set the switch to true in the onStart() or onResume() method. But is there a change to get the Switch Object?
If I would load a usual layout I could access the switch like this:
View v = inflater.inflate(R.layout.start_fragment, container, false);
Switch status = (Switch) v.findViewById(R.id.switch1);
Afterwards I would be able to set the Position of the Switch like this:
status.setChecked(true);
Another solution would be to destroy the actual view and call addPreferencesFromResource() again, but to be honest I have no idea how this could be done....
The third solution could be to use a OnCheckedChangeListener in my PreferenceFragment, but the problem would again be how to change/update the switch.
I am sure that the Preference is updated correctly, because I´m running a OnSharedPreferenceChangeListener in one of my services and to debug this problem I made the listener log the status of my switchPreference.
Can you help me somehow?
unfortunately I cannot answer my own question before tomorrow morning, so I edit my question:
Thank you guys, I don´t want to restart the underlying activity, but only the fragment.
Fortunately I found a clue in this thread: How do you refresh PreferenceActivity to show changes in the settings?
I can really access the SwitchPreference that simple.
My solution is:
private SwitchPreference pref_phone_locked;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
status = (SwitchPreference) findPreference("status");
}
public void onStart(){
super.onStart();
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
if(sharedPref.getBoolean("status", false)){
status.setChecked(true);
}else{
status.setChecked(false);
}
}
This way I can simply cast the Preference to a SwitchPreference and modify it after every onStart() call. I guess this is the best solution for my problem.
Hopefully this answer will save someones time in future =)
Thanks you guys again!
I'm not sure if this will work for you ( I've a very basic knowlege of Android ) but I found this solution in a similar question and it works very well for me
private void simulateRefresh(){
Intent intent = getIntent();
overridePendingTransition(0, 0);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
overridePendingTransition(0, 0);
startActivity(intent);
}
Basically this destroy and recreate the activity without animation in between.
Found here
I have got an activity where the user can enter host name, user name and password and then click on a "Verify credentials" button. Then the credentials will be checked, which will take some time. In the meantime the user should neither be able to change the credentials nor to click on "Verify" again. So, a modal dialog like the ProgressDialog seems perfect for this.
Unfortunately, ProgressDialog has the well-know limitations regarding orientation changes etc. The guide (UI/Dialogs) tells to avoid ProgressDialog at all and use a ProgressBar in the layout instead (like in Progress & Activity). What does this mean? Shall I create another activity with just one progress bar? Or disable all input fields and put a progress bar on top of it? Sounds quite weird to me... whats your preferred solution?
Best thing which I use is:
Put a ProgressBar just beside the Login Button.
I have put a progressbar beside it(Whose visibility is set to View.GONE) in the OnCreate method.
When the user clicks on the Login/Submit button, I set the visibility of the button to View.GONE and visibility of ProgressBar to View.VISIBLE.
It looks good and the user cannot click on the button until the work is done, If an error occurs, toggle the visibility to let the user try again
Like #micro.pravi mentioned in his answer, you can implement the ProgressBar inside your layout. To keep the state after an orientation change you have to use onSaveInstanceState and onRestoreInstanceState to save and restore important values, i.e. private variables, like the private boolean isChecking
public class MyActivity extends Activity {
public boolean isProcessing;
#Override
public void onCreate(Bundle stateBundle) {
super.onCreate(stateBundle);
// Set Layout
setContentView(R.layout.main);
if(stateBundle!=null) {
// read your data here from the bundle
isProcessing = stateBundle.getBoolean("isProcessing");
}
setUiState(isChecking);
}
#Override
protected void onRestoreInstanceState(Bundle stateBundle) {
// Second value of getBoolean is the default value
isProcessing = stateBundle.getBoolean("isProcessing", false);
super.onRestoreInstanceState(stateBundle);
}
#Override
protected void onSaveInstanceState(Bundle stateBundle) {
// Save the critical data
stateBundle.putString("isProcessing", isProcessing);
super.onSaveInstanceState(stateBundle);
}
#Override
protected onResume() {
setUiState(isProcessing);
}
private setUiState(boolean processing) {
textView.setEnabled(!processing);
button.setEnabled(!processing);
progressbar.setVisibility(processing?View.VISIBLE:View.GONE);
}
}
This should be used to saved any critical data on orientation change or when the App is being killed and later restored by the OS. You don't have to save your TextView data, as the defautl View elements already handle this by themselves. Also do not store Image data this way. Instead store the Uri or path to the Url and load it on restore
For temporarily solving your problem, you can continue using the Progress Dialog and put this line in your Login Activity's tag in Manifest.xml file :
android:configChanges="orientation|keyboardHidden|screenSize"
Using this line of code will not affect the Progress Dialog on orientation changes. But it is considered a wrong practice according to Android Development's Documentation.
In the long run, i recommend you to Preserve the states for orientation changes.
I need an example-tutorial how to activate and deactivate an element in preference activity.
For example in the picture below when the Wi-Fi check box is unselected I can not touch the Network notification check box and it turns gray, when the Wi-Fi check box is selected then I can touch the other check box.
Also how can I populate the Add Wi-Fi network tab when the whi-fi checkbox is enabled?
We need to add in out preferences.xml file
in the preference which is depending from another preference the android:dependency="" code.
For example :
<CheckBoxPreference
android:key="checkBox"
android:summary="On/Off"
android:title="Enable" />
<ListPreference
android:entries="#array/listOptions"
android:entryValues="#array/listValues"
android:key="listpref"
android:summary="List preference example"
android:title="List preference"
android:dependency="checkBox" />
Your preferences activity should implement OnSharedPreferenceChangeListener. Be sure to register and unregister the activity with the listener.
Then in both onResume() and onSharedPreferenceChanged methods evaluate the state of the controlling preference to determine if the dependant preference should be enabled or disabled.
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
final String key) {
if (key.equals(PREFERENCE_KEY)) {
// handle setting enabled or disabled depending on value of preference
if (sharedPreferences.getBoolean(key, false)) {
// prefField.setenabled(true);
} else {
// prefField.setenabled(false);
}
}
}
If you also use a PreferenceCategory then you may also look to enable or disable the category as a whole.
When preference activity starts in onResume method check wifi connection status, or whatever you want and enable/disable appropriate preference.
It may looks similar to this, simple example, just to give you a general idea.
#Override
protected void onResume() {
super.onResume();
boolean isConnected = getConnectionStatus();
if(isConnected) {
connPreference.setEnabled(false);
} else {
connPreference.setEnabled(true);
}
}
I want to have an element in my preference menu that does the following:
Show a list of options.
Many are selectable
Maximum amount of options to be chosen 2.
Possibilities I thought of:
Doing a separated PreferenceScreen and showing options as checkBoxes, but I don't know where to place the logic of max 2 options.
Extending DialogPreference and doing it by hand.
What's the best way?
Extending DialogPreference would get you the closest in terms of look-and-feel; the Preference classes are fairly unflexible and un-extendable in my experience.
I can't remember too much about PreferenceScreen, but I imagine it's similar.
In an app I worked on, we ended up using separate activities, launched via Intent from a Preference item onClick. This allowed us to easily develop preference screens that require validation logic a bit more complex than the usual.
You can put the logic of maximum two options in a OnSharedPreferenceChangeListener.
So you just listen to all the preferences as they change and update them if an invalid combination is selected.
So your code would be something like the following:
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,String key) {
//Code to calcuate how many are selected
int code = numberSelected();
if (count > 2) {
sharedPreferences.edit().putBoolean(key,false).commit();
Toast.makeText(this,"Can't select more than two!",Toast.LENGTH_LONG).show();
}
}
If you create your own PreferenceActivity that implements OnSharedPreferenceChangeListener you can enable the listener to be listening only when required doing something like this:
#Override
protected void onResume() {
super.onResume();
//Register the listener
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
#Override
protected void onPause() {
super.onPause();
// Unregister the listener
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}