I'm facing a problem. In Settings menu I have a CheckboxPreference and an other Preference. They are in the same Category. I want that: when checkbox is checked, Preference (which lies below) appears. And when checkbox is unchecked, Preference disappears. I don't know what is the best way to do it. So I try this way:
- First off all: find PreferenceCategory.
- To hide Preference: remove it from Category.
- To show Preference: add it to Category.
Preference immediately disappear after removing. But after adding nothing appears. Can anybody help me?
Assuming you are using a PreferenceFragment:
First you find your CheckBoxPreference and the other Preference in your onResume by:
CheckBoxPreference cb = (CheckBoxPreference) findPreference('CHECKBOX_PREF_KEY');
OtherPreference otherPref = (OtherPreference) findPreference('OTHER_PREF_KEY');
now you set an OnPreferenceChangeListener on cb and then disable / enable the other pref in the listener by:
if (!cb.isChecked()) {
if (otherPref != null){
getPreferenceScreen().removePreference(otherPref);
}
} else {
if (otherPref == null) {
otherPref = new OtherPref();
otherPref.inti...
getPreferenceScreen().addPreference(otherPref);
}
}
Related
I'm building my first Android app, so apologies in advance for my lack of expertise. I've been banging away at this issue for 2 days so far. When I set the sound to mute in my Settings Activity via Shared Preferences, the setting does not 'stick'. Here is the code from my Main Activity:
SharedPreferences settingsSP;
boolean muteSound;
Then in onCreate:
settingsSP = getApplicationContext().getSharedPreferences("PlayerPreferences", Context.MODE_PRIVATE);
muteSound = settingsSP.getBoolean("muteSound", false);
Then I obviously use the muteSound variable to determine whether or not to play sounds within the MainActivity. Now when I go the Settings activity I have this code:
SharedPreferences settingsSP;
boolean muteSound;
Then in onCreate I have this:
settingsSP = getApplicationContext().getSharedPreferences("PlayerPreferences", Context.MODE_PRIVATE);
if (muteSound) {
activitySettingsBinding.displayMuteCheckBox.setChecked(true);
} else {
activitySettingsBinding.displayMuteCheckBox.setChecked(false);
}
activitySettingsBinding.displayMuteCheckBox.setOnClickListener(v -> {
if (activitySettingsBinding.displayMuteCheckBox.isChecked()) {
muteSound = true;
SharedPreferences.Editor editor = settingsSP.edit();
editor.putBoolean("muteSound", muteSound);
editor.apply();
} else {
muteSound = false;
SharedPreferences.Editor editor = settingsSP.edit();
editor.putBoolean("muteSound", muteSound);
editor.apply();
soundPool.play(bubble, 1, 1, 1, 0, 1);
}
The xml code:
<CheckBox
android:id="#+id/displayMuteCheckBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:gravity="center_vertical"
android:layoutDirection="rtl"
android:paddingLeft="40dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="Mute Sound"
android:textColor="#FFFFFF"
android:textSize="20sp"
android:textStyle="bold"
android:theme="#style/CheckBoxStyle" />
I placed a number of log.d tags throughout the code so that I observe what was happening. For example after I cold booted the app in Android Studio:
Open MainActivity, onCreate muteSound = false
Tap Settings button and the Settings onCreate lists muteSound = false
I check the checkbox to set it to muteSounds = true
I tap return button within Settings to return to MainActivity
MainActivity onCreate muteSound = true
Tap Settings button and the Settings onCreate lists muteSound = false
And the checkbox is unchecked - because muteSound = false
I can't figure out why the settings is not sticking. When I checked to set the muteSound to be true, that settings is lost when I return to the Settings Activity. I've searched the code to see if I set muteSound = true on accident somewhere else, but when searching the usages I did not find any. Is my assumption about sharePreferences incorrect. It doesn't appear to hold the settings. Or perhaps am I using the checkbox incorrectly, maybe I should be using another type of button here. I would like to use checkboxes to control the display of the score, time and other items on the MainActivity and throughout other app Activities, but if I can't figure this gap in my knowledge I won't be able to. What am I doing incorrectly?
For displayMuteCheckBox, use setOnCheckedChangeListener instead of setOnClickListener and use settingsSP variable to store value in SharedPreferences instead of creating new object of SharedPreferences.Editor:
activitySettingsBinding.displayMuteCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
settingsSP.edit().putBoolean("muteSound", isChecked).apply();
if (isChecked)
soundPool.play(bubble, 1, 1, 1, 0, 1);
}
});
I have a PreferenceActivity containing a number of CheckBoxPreference and I want to make sure that at least one of them is selected, any suggestion on how to do it?
Thanks
I ended up registering the same instance of Preference.OnPreferenceChangeListener on all my CheckBoxPreference. The listener keeps a set with my CheckBoxPreference and reacts when the user unchecks one, returning false if it's the only one checked.
Cant you use .setChecked(true) on the checkbox control
i.e.
// get the control
final CheckBox chkRemember = (CheckBox) findViewById(R.id.checkbox);
// pull th evalue from your preferences
strChecked = rwPref.readWriteUserSetting(DevDroidSLX.this, "Read", "CheckboxValueA" , "" );
if ( strChecked.equalsIgnoreCase("True"))
{
chkRemember.setChecked(true);
}
else
{
chkRemember.setChecked(false);
}
I have a ListPreference and want to verify if there is no selection to make some code/treatement. How can i do this ?
I have this to verify the selection:
if (Integer.valueOf(choice) == 0) {
What code to verify if not selection?
Thank you for your help.
If there is a preference selected for this ListPreference, then it will be saved in your SharedPreferences. You can test against this value by doing something like this:
private Boolean prefHasSelection(String prefId){
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
String yourPref = sp.getString(prefId, null);
return (yourPref != null);
}
prefHasSelection("yourPrefId"); // returns true if something is set
You could call this method at any point in your application lifecycle to determine if the preference has been set.
Hey everyone, I'm trying to make an activity so that when a CheckBox Preference is enabled (true), programmatically the on-screen keyboard InputType will change. I want the user to have the option to turn on/off the keyboard's email address option while keeping the inputType's already set.
Essentially doing the equivalent of changing:
android:inputType="textAutoCorrect|textCapSentences|textMultiLine"
to
android:inputType="typeAutoCorrect|textCapSentences|textmultiLine|textEmailAddress"
Preferences.xml
<CheckBoxPreference android:key="pref_key_enable_email"
android:title="#string/pref_title_enable_email"
android:summary="#string/pref_summary_enable_email"
android:defaultValue="false" />
This is what I have as of now.
public void setInputType(int type) {
boolean showEmail = false;
// Show the Email keyboard if the pref_key_enable_email preference is TRUE
mTextEditor = (EditText) findViewById(R.id.embedded_text_editor);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if(prefs.getBoolean("pref_key_enable_email",false)== true){
showEmail = true;
if (showEmail) {
mTextEditor.setInputType(InputType.TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_EMAIL_ADDRESS); w
} else {
mTextEditor.getInputType();
}
}
I've checked the /data/data/myappname/shared_prefs com.myappnamehere.preferences.xml. I at least know that the boolean values do change from false to true when the box is checked. It just doesn't do anything :(
Consider cleaning your code a little bit
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean showEmail = prefs.getBoolean("pref_key_enable_email",false);
mTextEditor = (EditText) findViewById(R.id.embedded_text_editor);
if(showEmail) {
mTextEditor.setInputType( mTextEditor.getInputType() | TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
}
I'm assuming you have your "default" flags in the xml for your layout:
android:inputType="textAutoCorrect|textCapSentences|textMultiLine"
Is there a way to dynamically show and hide preferences? In my case, I have a checkbox preference that would disable or enable one of 2 preference groups ("with-" and "without-handicap" groups). While this would be the ideal GUI in a desktop environment, the "with-handicap" takes up nearly the whole screen, while the other, "without-handicap" takes up only a small portion of the screen.
Rather than showing both groups at the same time, I'd like to show only one of them at a time, and dynamically show or hide the 2 groups when the checkbox changes. Is there a way to do this?
From a PreferenceActivity call
Preference somePreference = findPreference(SOME_PREFERENCE_KEY);
PreferenceScreen preferenceScreen = getPreferenceScreen();
preferenceScreen.removePreference(somePreference);
you can later call:
preferenceScreen.addPreference(somePreference);
The only a little bit tricky part is getting the order correct when adding back in. Look at PreferenceScreen documentation, particularly it's base class, PreferenceGroup for details.
Note: The above will only work for immediate children of a PreferenceScreen. If there is a PreferenceCategory in between, you need to remove the preference from its parent PreferenceCategory, not the PreferenceScreen. First to ensure the PreferenceCategory has an android:key attribute set in the XML file. Then:
Preference somePreference = findPreference(SOME_PREFERENCE_KEY);
PreferenceCategory preferenceCategory = (PreferenceCategory) findPreference(SOME_PREFERENCE_CATEGORY_KEY);
preferenceCategory.removePreference(somePreference);
and:
preferenceCategory.addPreference(somePreference);
Not exactly hiding/showing but if you only want disabling/enabling preference depending on another preference you can specify android:dependency="preferenceKey" or Preference.setDependency(String)
Example from developer.android.com:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:key="pref_sync"
android:title="#string/pref_sync"
android:summary="#string/pref_sync_summ"
android:defaultValue="true" />
<ListPreference
android:dependency="pref_sync"
android:key="pref_syncConnectionType"
android:title="#string/pref_syncConnectionType"
android:dialogTitle="#string/pref_syncConnectionType"
android:entries="#array/pref_syncConnectionTypes_entries"
android:entryValues="#array/pref_syncConnectionTypes_values"
android:defaultValue="#string/pref_syncConnectionTypes_default" />
</PreferenceScreen>
I recommend using V7 preference, it has setVisible() method. But I have not tried it yet.
If you want to implement the hiding of the preference completely in the Preference, here is one example. Does not allow to make it visible again, though.
public class RemovablePreference extends Preference {
#Override
protected void onBindView(View view) {
super.onBindView(view);
updateVisibility(); // possibly a better place available?
}
private void updateVisibility() {
Context context = getContext(); // should be a PreferenceActivity
if (context instanceof PreferenceActivity) {
updateVisibility((PreferenceActivity)context);
}
}
private void updateVisibility(PreferenceActivity activity) {
updateVisibility(getPreferenceScreen(activity));
}
private PreferenceScreen getPreferenceScreen(PreferenceActivity activity) {
if (activity.getPreferenceScreen() != null) {
return activity.getPreferenceScreen(); // for old implementations
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
Fragment fragment = activity.getFragmentManager().findFragmentById(android.R.id.content);
if (fragment instanceof PreferenceFragment) {
return ((PreferenceFragment) fragment).getPreferenceScreen();
}
}
return null;
}
private void updateVisibility(PreferenceScreen screen) {
if (!isVisible() && screen != null) {
hidePreference(screen, this);
}
}
private boolean hidePreference(PreferenceGroup prefGroup, Preference removedPreference) {
boolean removed = false;
if (prefGroup.removePreference(removedPreference)) {
removed = true;
}
for (int i = 0; i < prefGroup.getPreferenceCount(); i++) {
Preference preference = prefGroup.getPreference(i);
if (preference instanceof PreferenceGroup) {
PreferenceGroup prefGroup2 = (PreferenceGroup)preference;
if (hidePreference(prefGroup2, this)) {
// The whole group is now empty -> remove also the group
if (prefGroup2.getPreferenceCount() == 0) {
removed = true;
prefGroup.removePreference(prefGroup2);
}
}
}
}
return removed;
}
protected boolean isVisible() {
return true; // override
}
I needed something similar: toggling a switch to hide or show two extra preferences. Check out the sample app from Android-Support-Preference-V7-Fix which bring some new preference types and fixes some issues from the official library. There's an example there to toggle a checkbox to show or hide a preference category.
In the fragment that extends PreferenceFragmentCompatDividers, you could use something like:
findPreference("pref_show_extra_stuff").setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
findPreference("pref_extra_stuff_01").setVisible((Boolean) newValue);
findPreference("pref_extra_stuff_02").setVisible((Boolean) newValue);
return true;
}
});
pref_extra_stuff_01 and pref_extra_stuff_02 are the two preferences that are hidden when pref_show_extra_stuff is toggled.
For hiding preferences dynamically, I created an if-condition upon whose value I decide whether I want the pref to show or not. To do the actual hiding, I have been using:
findPreference(getString(R.string.pref_key)).setLayoutResource(R.layout.hidden);
The tricky part is to make it visible again. There is no direct way to do it except to recreate the layout. If the value of the if-condition is false, which means the pref should be visible, then the code to hide the pref will never be executed, thus resulting in a visible pref. Here is how to recreate the layout (in my case, I am extending a PreferencesListFragment):
getActivity().recreate();
I hope that was helpful.
Instead of doing this in onCreate in the settings activity:
getSupportFragmentManager().beginTransaction()
.replace(R.id.settings_container, new SettingsFragment()).commit();
You can initialize a global variable for the settings fragment and set it up like this:
settingsFragment = new SettingsFragment();
getSupportFragmentManager().beginTransaction()
.replace(R.id.settings_container, settingsFragment).commit();
Then further down you can set up an OnSharedPreferenceChangeListener with a global SharedPreferences.OnSharedPreferenceChangeListener to set up what should be shown or hidden when you change preferences:
// Global SharedPreferences.OnSharedPreferenceChangeListener
sharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener()
{
Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key)
{
if (key.equals("switch key"))
{
boolean newPref = preferences.getBoolean("switch key", true);
settingsFragment.findPreference("seekbar key").setVisible(newPref);
}
}
};
sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
Then in onCreate in the settings fragment you can do something like this to set what should be hidden based on existing preferences:
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext());
if (!sharedPreferences.getBoolean("switch key", true)
{
SeekBarPreference seekBarPreference = findPreference("seekbar key");
seekBarPreference.setVisible(false);
}