I'm writing my first Android app and it involves a preference where you set an amount of minutes, from 0 to 60. I've used a SeekBarPreference, and it shows up as a simple slider which you can indeed slide around to edit the value. The preference works fine.
I would like to show the selected value next to the SeekBar (or somewhere in the vicinity), as there by default is no way for the user to see what they've actually selected. There are lots of questions on Stack Overflow about similar sliders and preferences, but since version 25.1.0, released last December, there is SeekBarPreference, which has just what I need:
The seekbar value view can be shown or disabled by setting showSeekBarValue attribute to true or false, respectively.
But among the public methods listed below, there is no method for setting showSeekBarValue? There is a method for setting the adjustable attribute, setAdjustable(boolean adjustable), however?
Ideally I'd just write android:showSeekBarValue="true" in my SeekBarPreference tag in preferences.xml, but that (obviously) doesn't work.
So in a nutshell: how do I set showSeekBarValue to true?
In the app's build.gradle, I had to add
implementation 'com.android.support:preference-v7:26.+
Then, modify the PreferenceScreen's xml to include an app namespace:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
Finally, inside the xml, you can add
<SeekBarPreference
android:key="..."
android:title="..."
android:max="100"
android:min="0"
android:defaultValue="30"
android:dependency="..."
app:showSeekBarValue="true"
/>
This compiles without errors. To be fair, this is not a complete answer, because no value is shown in my case, even after these steps. But formally it does let you set the value in some way.
You need to use PreferenceScreen from android.support.v7.preference
<android.support.v7.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<SeekBarPreference
android:key="size"
android:title="Size"
android:summary="size of progressBar in dp's"
android:max="100"
app:showSeekBarValue="true"
android:defaultValue="25" />
</android.support.v7.preference.PreferenceScreen>
and also PreferenceFragmentCompat from android.support.v7.preference
import android.support.v7.preference.PreferenceFragmentCompat
class SettingsFragment: PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.preferences)
}
}
Related
How would I mimic the design of a preference screen or the "edit Contact" screen of android, without doing too much work?
I have to display ~12 attributes for an object and can't get my head around how to display them in a good way.
not for every attribute an obvious icon exists -> we want labels?
displaying textviews underneath other textviews that have an icon looks horrible, except if you want to manually add margins. (indenting)
PreferenceFragment has a kind of "Title" that can be used as Label and a Value, which would be even more perfect, as I have some interactive elements (item picker).
But using preferencefragment without SharedPreferences and instead to display arbitrary objects is obviously a (bad?) hack.
I've searched a lot and didn't come to a conclusion. Is there an obvious way I missed ?
You can actually create Settings Activity (with full functionality) without much effort.
Go to File > New > Activity > Settings Activity.
It will create the entire functionality - you only need to specify Switches, Lists in
res > xml > prefs_.xml
The values that you set via screen will be saved in SharedPreferences under the specified key.
To intercept the values that are configured via UI to the SharedPreferences you can add this to the SettingsActivity:
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.pref_general, rootKey)
findPreference<ListPreference>("system_theme")?.setOnPreferenceClickListener {
val value = (it as? ListPreference)?.value
//send value to server
return#setOnPreferenceClickListener true
}
}
}
I'm working on a little app with a lot of modifiable preferences, most of them being SeekBarPreferences.
It happens that, since I'm quite not happy with Android default SeekBarPreferences, I'm using the very good MaterialSeekBarPreference library which unfortunately have not been updated for 2 years.
Here is an example of code used by this library:
<com.pavelsikun.seekbarpreference.SeekBarPreference
android:key="#string/param_maxEvent"
android:title="Blahlblahblahblahblah"
android:summary="Blahlblahblahblahblah too"
android:defaultValue="2"
custom:msbp_minValue="0"
custom:msbp_maxValue="5"
custom:msbp_measurementUnit="events"
custom:msbp_interval="1"
custom:msbp_dialogEnabled="false"/>
As you can see, you can use the android:defaultValue xml attribute, and it works perfectly with the UI.
Since I need to load all these default values at app initialization, I use the PreferenceManager.setDefaultValues method:
public class App extends Application {
#Override public void onCreate() {
super.onCreate();
PreferenceManager.setDefaultValues(this, R.xml.preferences, true);
}
}
This works fine with all default preferences (SwitchPreference, ListPreference, Preference), but unfortunately not with these custom SeekBarPreference.
Loading the preferences activity does not set up thoses default values either.
Is there any workaround for this problem ? Else, if I was up to edit the library, what should I change ?
I don't use the method PreferenceManager.getDefaultSharedPreferences(this, R.xml.preferences, true);. Instead, I use preference.setDefaultValue(object); in the Fragment.
I have implemented a custom ListPreference and managed to load a list of items along with checkboxes for each without an issue. However, I need to add a “Select All” checkbox on top in order to select all list of items. How would I achieve this with the following source I have implemented?
The layout:
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="#string/Title_LOCATIONS">
<com.gm.settings.LocationsListPreference
android:defaultValue="null"
android:key="list_locations"
android:title="#string/LocationsListPreference_title"
android:dialogTitle="#string/LocationsListPreference_title"
android:summary="#string/LocationsListPreference_summary"
/>
The class:
public class LocationsListPreference extends ListPreference {
}
I have implemented the class by following a tutorial and it works fine. But it uses a default layout i think and if I were to add this addition checkbox, how would I achieve this?
Update:
I want to know as to how i can add the "Select All" checkbox to the layout? Or should i create a custom layout? Please provide a sample code. (Because i feel the way it is right now, i dont have the control over this checkbox)
What you could do is add a CheckBoxPreference in your PreferenceCategory and attach to it a OnPreferenceChangedListener that sets all of the values to being checked.
An example could probably look a little something like this:
<CheckBoxPreference
android:key="select_all"
android:defaultValue="false"
android:title="Select All"
/>
<com.gm.settings.LocationsListPreference
android:defaultValue="null"
android:key="list_locations"
android:title="#string/LocationsListPreference_title"
android:dialogTitle="#string/LocationsListPreference_title"
android:summary="#string/LocationsListPreference_summary"
/>
And then in your PreferenceFragment (or PreferenceActivity), you would have the following:
SharedPreferences shareprefs = getPreferenceManager().getSharedPreferences();
LocationsListPreference listPreference = getPreference("list_locations");
CheckBoxPreference selectAll = getPreference("select_all");
selectAll.setOnPreferenceChangeListener(new OnPreferenceChangeListener()
{
public boolean onPreferenceChanged(Preference preference, Object newValue)
{
//Do something with your listPreference and/or your sharedPrefs
}
}
Hope this helps, and if you get to a road block, I think this post does a slightly better job at explaining some of the concepts. Good luck!
Found a stackoverflow post which might help others if they come across this kind of implementation:
You can build your custom ListPreference layout.
Cheers!
Is it somehow possible to include one preferences.xml into another, like it can be done for layouts with the <include /> tag?
Let's say:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen
android:title="#string/pref_group_title_visual">
<include
preferences_filename="xml/pref_visual"/>
</PreferenceScreen>
...
Solution here it is to inflate both preference files from PreferencesActivity. For example:
addPreferencesFromResource(R.xml.options);
addPreferencesFromResource(R.xml.additional_options);
The solution soul shows works. It can be expanded to only show preferences if you're the developer using an unsigned version of the app ;)
addPreferencesFromResource(R.xml.options);
addPreferencesFromResource(R.xml.additional_options);
if (BuildConfig.DEBUG) {
addPreferencesFromResource(R.xml.developer_options);
}
I created a blog post regarding this issue and have a complete working code example available for download.
http://androidfu.blogspot.com/2012/05/developer-debug-with-nested-preferences.html
To truly achieve the nesting effect you can use this technique to relocate the loaded preferences to a group already loaded.
PreferenceCategory notifications = (PreferenceCategory) getPreferenceScreen ().findPreference (PreferenceKey.pref_notifications.name ());
addPreferencesFromResource (R.xml.pref_notifications, notifications);
Where the enhanced addPreferencesFromResource is defined as:
private void addPreferencesFromResource (int id, PreferenceGroup newParent) {
PreferenceScreen screen = getPreferenceScreen ();
int last = screen.getPreferenceCount ();
addPreferencesFromResource (id);
while (screen.getPreferenceCount () > last) {
Preference p = screen.getPreference (last);
screen.removePreference (p); // decreases the preference count
newParent.addPreference (p);
}
}
It works for any PreferenceGroup such as PreferenceScreen and PreferenceCategory.
No, it seems to be impossible. But there's a simple workaround. You can make another PreferenceActivity that loads nested PreferenceScreen. And in the main preference.xml file you need to create a Preference object and set an Intent object for it in code (using setIntent() method). This Intent must be used to create the second PreferenceActivity.
I've put a SeekBarPreference in my PreferenceScreen (xml), but the value isn't saved and also the default value isn't taken in account.
The bar is always at zero.
Here the piece of code:
<PreferenceCategory
android:title="mySettings">
<SeekBarPreference
android:key="m_set"
android:defaultValue="210"
android:title="Transparency"
android:max="255"
android:summary="Adjust..." />
</PreferenceCategory>
Any idea?
Other stuff like CheckBoxPreference works fine.
There is no SeekBarPreference, you must create own class, check:
this tutorial