I'm developing an Android app and I have added several SeekBarPreference elements in my settings page to work as sliders. They have different max values, and I think it's a problem that you cannot see what value you selected. So I wonder what's the best way to show the current value of SeekBarPreference in a preferences activity. Right now I think maybe the summary of the seekBarPreference-element is the best way, but I am open to other suggestions.
This is how the settings activity looks like:
Here's the code I tried so far:
public static class SettingsFragment extends PreferenceFragmentCompat {
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.root_preferences, rootKey);
((SeekBarPreference) findPreference(R.id.seekRounds)).setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final int progress = Integer.valueOf(String.valueOf(newValue));
preference.setSummary(String.format("Current value: %d", progress));
}
});
}
And currently I get the error Cannot resolve symbol 'seekRounds'.
Here's my root_preferences.xml:
<androidx.preference.PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory app:title="#string/main_settings_header">
<SeekBarPreference
app:key="seekRounds"
android:title="Number of rounds"
android:summary="This is the summary"
android:max="2"
android:progress="0"
android:theme="#style/Base.Widget.AppCompat.SeekBar"
/>
</PreferenceCategory>
Found the answer. Just add app:showSeekBarValue="true" to your SeekBarPreference.
Like this:
<SeekBarPreference
app:key="seekRounds"
android:title="Number of rounds"
android:summary="This is the summary"
android:max="2"
app:showSeekBarValue="true"
android:progress="0"
android:theme="#style/Base.Widget.AppCompat.SeekBar"
/>
Related
I am trying to make a setting menu with cardView and Preference, but I am not sure how to combine these two... Here's the screenshot and I want to move the ListPreference and PreferenceScreen entries into the setting cardView above.
Here's the preference.xml The layout/setting_group is a cardview
<PreferenceScreen
android:layout="#layout/setting_title_top"
android:title = "Padding" />
<PreferenceScreen
android:layout="#layout/setting_group">
</PreferenceScreen>
<ListPreference
android:id="#+id/list"
android:layout="#layout/setting_menu"
android:dialogTitle = "title one"
android:key = "key_1"
android:title = "ListPreference"
android:summary = "Summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ListPreference>
<PreferenceScreen
android:layout="#layout/setting_menu"
android:key="Key two"
android:summary="Summary"
android:title="PreferenceScreen" />
<PreferenceScreen
android:layout="#layout/setting_title"
android:title = "Another Setting" />
The PreferenceScreen is a container, you are opening and closing him with noting inside.
You can create preferences like that:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<EditTextPreference
android:capitalize="words"
android:defaultValue="#string/default_value" <!--The initial state of the preference -->
android:key="#string/pref_key" <!-- The key for retrieve the preference -->
android:singleLine="true"
android:title="#string/pref_title" /> <!-- The title who is showing above the preference -->
</PreferenceScreen>
Edit: Create a xml file to with the layout of your preferences and create and Activity, example:
public class SettingsActivity extends PreferenceActivity
implements Preference.OnPreferenceChangeListener {
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_general);
bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_key))); // Is deprecated, but still a good option to no need change the values manually.
}
private void bindPreferenceSummaryToValue(Preference preference) {
preference.setOnPreferenceChangeListener(this);
onPreferenceChange(preference, PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getString(preference.getKey(), ""));
}
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
preference.setSummary(stringValue);
return true;
}
}
I have MenuSettings in which I have PreferenceActivity class. In PreferenceActivity I have displayed checkboxPreference like below.
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory
android:title="Options">
<CheckBoxPreference
android:key="pref_opt1"
android:title="Option 1"
android:summary="Tick to set this option"
android:defaultValue="true"
/>
<CheckBoxPreference
android:key="pref_opt2"
android:title="Option 2"
android:summary="Tick to set this option"
android:defaultValue="true"
/>
</PreferenceCategory>
</PreferenceScreen>
I want to use checkboxes to perform function for synchronization that I have build, But Please can any body let me know how to use checkboxes in PreferenceActivity. Is there any need to create another Activity? or we can perform function in same PreferenceActivity?
here is my PreferenceActivity:
public class SharedPref extends PreferenceActivity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.sharedpref);
}
// StorePreference method{
}
// readPreferences method{
}
}
I have PreferenceFragment and a PreferenceActivity from which I add headers from a XML file on this way:
PreferenceActivity
#Override
public void onBuildHeaders(List<Header> target) {
if(DEBUG) Log.i("PreferenceActivity", "onBuildHeaders() -> LogicAnalizerPrefs");
if(android.os.Build.VERSION.SDK_INT >= 12) {
loadHeadersFromResource(R.xml.preference_header_logicanalizer, target);
}
}
PreferenceFragment:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(DEBUG) Log.i("PreferenceFragment", "onCreate() -> LogicAnalizerPrefsFragment");
int res = getActivity().getResources().getIdentifier(getArguments().getString("logicprefsheaders"), "xml", getActivity().getPackageName());
addPreferencesFromResource(res);
}
And the XML file where I have the headers is:
R.xml.preference_header_logicanalizer:
<header
android:fragment="com.protocolanalyzer.andres.LogicAnalizerPrefsFragment"
android:icon="#drawable/settings"
android:title="General" >
<extra
android:name="logicprefsheaders"
android:value="logicgeneral" />
</header>
<header
android:fragment="com.protocolanalyzer.andres.LogicAnalizerPrefsFragment"
android:icon="#drawable/settings"
android:title="Canal 1" >
<extra
android:name="logicprefsheaders"
android:value="c1analizerprefs" />
</header>
<header
android:fragment="com.protocolanalyzer.andres.LogicAnalizerPrefsFragment"
android:icon="#drawable/settings"
android:title="Canal 2" >
<extra
android:name="logicprefsheaders"
android:value="c2analizerprefs" />
</header>
<header
android:fragment="com.protocolanalyzer.andres.LogicAnalizerPrefsFragment"
android:icon="#drawable/settings"
android:title="Canal 3" >
<extra
android:name="logicprefsheaders"
android:value="c3analizerprefs" />
</header>
<header
android:fragment="com.protocolanalyzer.andres.LogicAnalizerPrefsFragment"
android:icon="#drawable/settings"
android:title="Canal 4" >
<extra
android:name="logicprefsheaders"
android:value="c4analizerprefs" />
</header>
And this is one of my xml files which is used to display one of the preferences when a Header is clicked:
c1analizerprefs.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="#string/AnalyzerProtocolTitle1" >
<ListPreference
android:defaultValue="0"
android:entries="#array/protocolList"
android:entryValues="#array/protocolValues"
android:key="protocol1"
android:summary="#string/AnalyzerProtocolSummary"
android:title="#string/AnalyzerProtocolTitle1" />
<ListPreference
android:defaultValue="1"
android:entries="#array/channelNames"
android:entryValues="#array/protocolValues"
android:key="SCL1"
android:summary="#string/AnalyzerSCLSummary"
android:title="#string/AnalyzerSCLTitle" />
<EditTextPreference
android:defaultValue="9600"
android:title="#string/AnalyzerBaudTitle"
android:key="BaudRate1"
android:summary="#string/AnalyzerBaudSummary"
android:inputType="number" />
</PreferenceCategory>
</PreferenceScreen>
So in a large screen I have this result as expected and I use only one PreferenceFragment to add my 4 headers.
But my four Preferences defined in the XML like c1analizerprefs.xml are almost the same the only change is a number (For example: Pref. 1, Pref. 2, ...) so I want to add them in Java so I can use a for() to add 4 or more Preferences easily changing the number of repetitions because the text is always the same I only change a number so on this way I don't need to create one XML file for each preference, I create them dynamically in Java.
How can I add a Preference to a Header in Java instead of using a XML file? In PreferenceFragment I only have addPreferencesFromResource() or addPreferencesFromIntent(). Is any way to add a Preference Object?
Just in case someone is actually looking for some code...
The following example loads some headers from XML and then appends to them programatically.
1st override onBuildHeaders inside your PreferenceActivity:
#Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.preference_headers, target);
// Add layer as a new settings header
Header header = new Header();
header.title = "More Settings";
header.summary = "Change even more settings";
header.fragment = SettingsFragment.class.getName();
Bundle b = new Bundle();
b.putString("category", "MoreSettings");
header.fragmentArguments = b;
target.add(header);
}
Then override onHeaderClick inside your PreferenceActivity. Note that you pass the header's fragmentArguments to the fragment so you can detect which header was clicked (category):
#Override
public void onHeaderClick(Header header, int position) {
this.startPreferencePanel(SettingsFragment.class.getName(), header.fragmentArguments, header.titleRes, header.title, null, 0);
}
Then inside your PreferenceFragment override onCreate:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
mCategory = getArguments().getString("category");
}
else {
// Orientation Change
mCategory = savedInstanceState.getString("category");
}
if (mCategory.equals("Map")) {
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences_map);
}
if (mCategory.equals("MoreSettings")) {
// Load the preferences from an XML resource
PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(getActivity());
// add prefrences using preferenceScreen.addPreference()
this.setPreferenceScreen(preferenceScreen);
}
}
In case you want to see the xml for predefined headers.
res/xml/preference_headers.xml
<?xml version="1.0" encoding="utf-8"?>
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
<header
android:fragment="com.appName.fragments.SettingsFragment"
android:title="#string/pref_category_map_title"
android:summary="#string/pref_category_map_sum" >
<!-- key/value pairs can be included as arguments for the fragment. -->
<extra android:name="category" android:value="Map" />
</header>
</preference-headers>
res/xml/preferences_map.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:key="pref_zoomToCurrentLocationOnStart"
android:title="#string/pref_zoomToCurrentLocationOnStart_title"
android:summary="#string/pref_zoomToCurrentLocationOnStart_sum"
android:defaultValue="true" />
<CheckBoxPreference
android:key="pref_myLocation"
android:title="#string/pref_myLocation_title"
android:summary="#string/pref_myLocation_sum"
android:defaultValue="true" />
</PreferenceScreen>
Adding headers dynamically will not be easy. As android documentation states:
Blockquote Typical implementations will use loadHeadersFromResource(int, List) to fill in the list from a resource.
If you still want to go with a dynamic solution, you might want to take a look at the source code of loadHeadersFromResource (for example, here http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/preference/PreferenceActivity.java#PreferenceActivity.loadHeadersFromResource(int%2Cjava.util.List) )
To sum up,
you need to create a PreferenceActivity.Header object,
prepare it for usage by setting its various properties that can be found in documentation: http://developer.android.com/reference/android/preference/PreferenceActivity.Header.html,
and finally add that created header to the list: target.add(header); (target is the argument that is passed to onBuildHeaders)
Hopefully I haven't misunderstood your question:
getPreferenceScreen().addPreference( preference );
Great answer by #goodies4uall
I will merely add (since i cannot yet edit posts) that you need not do anything fancy in onHeaderClick().
If you wish to add a header outside of onBuildHeaders() the best way to do it is to invalidate them and allow onBuildHeaders() to add the new one when it next fires (invalidateHeaders will cause onBuildHeaders to fire again), like so:
private boolean flagToAddMyNewHeader = false;
public void someEventFiredThatRequiresANewHeader() {
flagToAddMyNewHeader = true;
invalidateHeaders();
}
And then your onBuildHeaders:
#Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.preference_headers, target);
if (flagToAddMyNewHeader) {
flagToAddMyNewHeader = false;
Header header = new Header();
header.titleRes = R.string.my_new_header_title;
header.iconRes = R.drawable.my_new_header_icon;
header.fragment = MyNewHeaderFragment.class.getName();
Bundle b = new Bundle();
b.putString("category", "MyNewHeader");
header.fragmentArguments = b;
// inserts my new header as the 2nd entry
target.add(1, header);
}
}
This appears like a bug to me: When you load many switch preferences in a preference fragment, they somehow re-set themselves , when you scroll the preferences. I have separately tested this with little demo code:
/res/xml/prefs.xml (Just a bunch of switch preferences, just enough to make preferences scroll on screen) :
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:key="my_prefs">
<PreferenceCategory android:key="my_prefs_cat" android:title="Settings">
<SwitchPreference android:key="p1" android:title="p1" android:defaultValue="false" />
<SwitchPreference android:key="p2" android:title="p2" android:defaultValue="false" />
<SwitchPreference android:key="p3" android:title="p3" android:defaultValue="false" />
<SwitchPreference android:key="p4" android:title="p4" android:defaultValue="false" />
<SwitchPreference android:key="p5" android:title="p5" android:defaultValue="false" />
<SwitchPreference android:key="p6" android:title="p6" android:defaultValue="false" />
<SwitchPreference android:key="p7" android:title="p7" android:defaultValue="false" />
<SwitchPreference android:key="p8" android:title="p8" android:defaultValue="false" />
<SwitchPreference android:key="p9" android:title="p9" android:defaultValue="false" />
<SwitchPreference android:key="p10" android:title="p10" android:defaultValue="false" />
</PreferenceCategory>
</PreferenceScreen>
/src/Prefs.java (A simple PreferenceFragment) :
package com.example.preflistbug;
import android.os.Bundle;
import android.preference.PreferenceFragment;
public class Prefs extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.prefs);
}
}
/res/layout/main.xml (Placed PreferenceFragment in Activity layout) :
<?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">
<fragment android:name="com.example.preflistbug.Prefs"
android:id="#+id/frg_prefs"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
/src/MyActivity.java (Demo Activity) :
package com.example.preflistbug;
import android.app.Activity;
import android.os.Bundle;
public class MyActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
Problem: If you change the first switch preference , scroll down, scroll back up, the switch is reset. Same is true for other switch preferences which scroll out of view and are visited later. (specially, in horizontal orientation)
Happens on emulator too. I'm compiling on platform version 15, ICS. As you can see in above code, this is a very simple setup, I can't find anything in this code, that might explain why this is happening.
Update
Bug reported as Issue 26194.
Update 2
It is supposed to be fixed in android L release.
I was able to reproduce this issue. I also found a workaround but I don't know why it works :)
Create a derived class from SwitchPreference like so:
public class Pref extends SwitchPreference {
public Pref(Context context) {
super(context);
}
public Pref(Context context, AttributeSet attrs) {
super(context, attrs);
}
public Pref(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
}
Then, instead of using these in your prefs.xml:
<SwitchPreference ... />
You can use these instead
<com.example.preflistbug.Pref ... />
The derivation seems to somehow fixes the issue where the view recycling in the ListView-driven preference list is reusing the controls without "freeing" them from their previous Preference object first (or so I think). I'll update this answer if I figure out more.
i'm using this code in an activity
protected void onResume() {
super.onResume();
prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
System.out.println(connections);
String dir = prefs.getString("download_directory", "Download");
System.out.println(dir);
}
My preferences.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="Downloads">
<EditTextPreference
android:key="download_directory"
android:title="#string/download_destination"
android:summary="#string/download_description"
android:defaultValue="FacebookPhotos"
android:dialogTitle="#string/download_destination" />
<CheckBoxPreference android:key="subdir_album"
android:title="#string/download_album"
android:summary="#string/download_album_description" />
</PreferenceCategory>
<PreferenceCategory android:title="Gallery">
<EditTextPreference
android:key="connections"
android:title="Concurrent connections"
android:numeric="integer"
android:maxLength="2"
android:defaultValue="7"
android:dialogTitle="Concurrent connections" />
</PreferenceCategory>
</PreferenceScreen>
edited by
public class Preferences extends PreferenceActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
The problem is, when i get "connections" value it gives me the correct int, instead the getString for key "download_directory" always gives me the default value "Download"
getString for key "download_directory" always gives me the default
value "Download"
This can only happen if "download_directory" is not set at all!