Preference items being automatically re-set? - android

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.

Related

Show current value of SeekBarPreference

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"
/>

Android change PreferenceActivity layout float

by default android PreferenceActivity layouts are left to right and i can not change PreferenceActivity widgets to right from left. for example see this screen shot please:
i want to change this layout like with below screen shot
PreferenceActivity Activity:
public class ActivitySettings extends PreferenceActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.app_settings);
}
}
PreferenceActivity layout:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:icon="#drawable/img_app_setting" >
<PreferenceCategory android:title="#string/settings_alarm_title" >
<CheckBoxPreference
android:key="PLAY_SOUND"
android:summaryOff="#string/settings_summary_off_play_sound"
android:summaryOn="#string/settings_summary_on_play_sound"
android:title="#string/settings_play_sound" />
<CheckBoxPreference
android:key="SHOW_NOTIFICATION"
android:summaryOff="#string/settings_summary_off_show_notification"
android:summaryOn="#string/settings_summary_on_show_notification"
android:title="#string/settings_show_notification" />
</PreferenceCategory>
</PreferenceScreen>

onPreferenceClick listener not working / onPreferenceClick not being called

I am trying to open a website when one of my preferences is clicked (not when the preference is actually changed because there isn't one).
The problem is that the onPreferenceClick() is never called.
This is my PreferenceActivity:
public class About extends PreferenceActivity implements
OnPreferenceClickListener {
TextView tv_developer;
TextView tv_version;
String versionName;
int counter = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.about);
Preference p_developer = (Preference) findPreference("p_developer");
p_developer.setOnPreferenceClickListener(this);
Preference p_licences = (Preference) findPreference("p_licences");
p_licences.setOnPreferenceClickListener(this);
}
#Override
public boolean onPreferenceClick(Preference pref) {
// TODO Auto-generated method stub
Log.i("Anything pressed", "YES");
if (pref.getKey().equals("p_developer")) {
Log.i("p_developer", "YES");
} else {
Log.i("p_developer", "NO");
}
return true;
}
}
This is the xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="about"
android:title="About" >
<Preference
style="?android:preferenceInformationStyle"
android:key="p_licences"
android:title="p_licences" />
<PreferenceCategory android:title="Category" >
<Preference
style="?android:preferenceInformationStyle"
android:key="p_developer"
android:title="p_developer" />
</PreferenceCategory>
</PreferenceScreen>
I have also found that this does not do anything either:
<Preference android:title="#string/prefs_web_page" >
<intent android:action="android.intent.action.VIEW"
android:data="http://www.example.com" />
</Preference>
Add android:enabled="true" to Preference:
<Preference
style="?android:preferenceInformationStyle"
android:key="p2"
android:enabled="true"
android:title="p2" />
You are using:
PreferenceActivity.addPreferencesFromResource(R.layout.about);
Shouldn't it be more like:
PreferenceActivity.addPreferencesFromResource(R.xml.yourxmlfilename);
Since thae preferences you defined are not a layout.
You need to load the name of the .xml file, not the key of the preference in .xml.
So, put your preferences .xml file in the "xml" folder, and give it a name like "mypreferences.xml". Then, load it like that:
PreferenceActivity.addPreferencesFromResource(R.xml.mypreferences);
In my project, the file looks like this: (name "settings.xml")
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="Your Settings" >
<Preference
android:key="delete"
android:title="Delete User"
android:summary="Deletes the user." />
<!-- and so on -->
I add it to the PreferenceActivity by calling:
PreferenceActivity.addPreferencesFromResource(R.xml.settings);
And set the onClickListener:
Preference deletePref = (Preference) findPreference("delete");
deletePref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
// do stuff
return true;
}
});
And it works.
Furthermore, you could try using a different name for title and key.
Fresh answer here.
You need to declare listener first. And then attach that listener for each(!) of end Preference objects. Like these:
final static int CAMERA_SLEEP_TIME=0,
CAMERA_TIME=1,
RESET=2;
private Preference.OnPreferenceClickListener listener =new Preference.OnPreferenceClickListener(){
#Override
public boolean onPreferenceClick(Preference preference) {
String keyLcl = preference.getKey();
if(keyLcl.equals(cameraSleepTime))
triggerPrefsDialog(CAMERA_SLEEP_TIME);
else
if (keyLcl.equals(cameraTime))
triggerPrefsDialog(CAMERA_TIME);
else
if (keyLcl.equals(reset))
triggerPrefsDialog(RESET);
else
return false;
return true;
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
Resources resLcl = getResources();
cameraSleepTime=resLcl.getString(R.string.camera_sleep_time);
cameraTime=resLcl.getString(R.string.camera_time);
reset =resLcl.getString(R.string.reset);
PreferenceScreen sceenLcl = getPreferenceScreen();
PreferenceCategory pcLcl=(PreferenceCategory)sceenLcl.getPreference(1);
pcLcl.getPreference(0).setOnPreferenceClickListener(listener);
pcLcl.getPreference(1).setOnPreferenceClickListener(listener);
pcLcl=(PreferenceCategory)sceenLcl.getPreference(2);
pcLcl.getPreference(0).setOnPreferenceClickListener(listener);
l.a(pcLcl.getTitle());
}
And related preferences.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceCategory
android:title="#string/switch_mode">
<CheckBoxPreference
android:key="#string/enable_switch"
android:defaultValue="true"
android:gravity="center"
android:title="#string/is_switched"
/>
</PreferenceCategory>
<PreferenceCategory
android:title="#string/seconds_category">
<Preference
android:key="#string/camera_time"
android:defaultValue="600000"
android:title="#string/camera_time"
/>
<Preference
android:key="#string/camera_sleep_time"
android:defaultValue="600000"
android:title="#string/camera_sleep_time"
/>
</PreferenceCategory>
<PreferenceCategory
android:title="#string/System">
<Preference
android:key="#string/reset"
android:defaultValue="false"
android:title="#string/reset"
/>
</PreferenceCategory>
<PreferenceCategory
android:title="#string/to_be_added">
</PreferenceCategory>
For me the solution was to extend the existing PreferenceCategory class (in Support Library) and override isEnabled(). This method always returned false so I created a class called ClickablePreferenceCategory and changed it to true.
In addition to that I had to add android:selectable="true" to my custom Preference xml node. The result looks like this:
<PreferenceCategory
android:enabled="true"
android:key="#string/key_category_problem_solving"
android:selectable="true"
android:title="#string/problem_solving">
</PreferenceCategory>
And the ClickablePreferenceCategory:
public class ClickablePreferenceCategory extends PreferenceCategory {
public ClickablePreferenceCategory(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public ClickablePreferenceCategory(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public ClickablePreferenceCategory(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ClickablePreferenceCategory(Context context) {
super(context);
}
#Override
public boolean isEnabled() {
return true;
}
}

Preference Menu on 10 inch tablet

I am trying to figure out why the layout of my Preference menu is displayed in a false way on 10' tablets when using it in landscape mode. It looks like the lines that are to the right of the Checkboxes are actually to the left of them. You can see this here http://imageshack.us/photo/my-images/109/schnappschuss2013052109.png/
On 7' tablets, everything works like expected to do.
My menu looks like that:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory
android:title="#string/pref_message"
android:key="pref_key_message_settings">
<CheckBoxPreference
android:key="pref_key_add_timestamp"
android:summary="#string/pref_summary_addTimestamp"
android:title="#string/pref_addTimestamp"
android:defaultValue="true"/>
<ListPreference
android:dependency="pref_key_add_timestamp"
android:summary="#string/pref_summary_timestamp_option"
android:key="pref_key_timestamp_option"
android:title="#string/pref_timestampOption"
android:dialogTitle="#string/pref_timestampOptionDialog"
android:entries="#array/pref_timestampArray"
android:entryValues="#array/pref_timestampValues"
android:defaultValue="Time" />
<CheckBoxPreference
android:key="pref_key_add_newline"
android:summary="#string/pref_summary_addNewLine"
android:title="#string/pref_addNewLine"
android:defaultValue="true"/>
<ListPreference
android:dependency="pref_key_add_newline"
android:key="pref_key_newline_option"
android:summary="#string/pref_summary_newline_option"
android:title="#string/pref_newLineOption"
android:dialogTitle="#string/pref_newLineOptionDialog"
android:entries="#array/pref_newLineArray"
android:entryValues="#array/pref_newLineValues"
android:defaultValue="LF" />
<CheckBoxPreference
android:key="pref_key_clear_text"
android:summary="#string/pref_summary_clearText"
android:title="#string/pref_clearText"
android:defaultValue="false"/>
</PreferenceCategory>
<PreferenceCategory
android:title="#string/pref_storage"
android:key="pref_key_storage_settings">
<EditTextPreference
android:key="pref_key_change_name"
android:summary="#string/pref_summary_editFilename"
android:title="#string/pref_editFilename"
android:defaultValue="history"/>
<CheckBoxPreference
android:key="pref_key_add_date"
android:summary="#string/pref_summary_addDate"
android:title="#string/pref_addDate"
android:defaultValue="true"/>
<CheckBoxPreference
android:key="pref_key_add_time"
android:summary="#string/pref_summary_addTime"
android:title="#string/pref_addTime"
android:defaultValue="true"/>
<at.rtcmanager.ConfirmPreference
android:key="pref_key_clear_history"
android:summary="#string/pref_summary_clearHistory"
android:title="#string/pref_clearHistory"/>
</PreferenceCategory>
<PreferenceCategory
android:title="#string/pref_time"
android:key="pref_key_time_settings">
<CheckBoxPreference
android:key="pref_key_autosend_time"
android:summary="#string/pref_summary_austosendTime"
android:title="#string/pref_autosendTime"
android:defaultValue="false"/>
<ListPreference
android:key="pref_key_mode_sentTime"
android:title="#string/pref_mode_sentTime"
android:summary="#string/pref_summary_mode_sentTime"
android:dialogTitle="#string/pref_modeSentTimeDialog"
android:entries="#array/pref_sentTimeModeArray"
android:entryValues="#array/pref_sentTimeValues"
android:defaultValue="10Byte" />
</PreferenceCategory>
<PreferenceCategory
android:title="#string/pref_about"
android:key="pref_key_settings_about">
<Preference android:title="#string/prefs_about_app" >
<intent android:action="AboutActivity"/>
</Preference>
</PreferenceCategory>
</PreferenceScreen>
and is loded with:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Show the Up button in the action bar.
getActionBar().setDisplayHomeAsUpEnabled(true);
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsMenuFragment())
.commit();
}
public static class SettingsMenuFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.app_prefs);
}
}
I had the same problem. My solution is to extend SettingsActivity from usual Activity, not from PreferenceActivity. But SettingsFragment should extend PreferenceFragment of course. It helped me, hope this solves your issue too.

Android PreferenceActivity Item Height

I have a PreferenceActivity with two checkboxes. Everything is working correctly, but I have a UI problem; not all of the text for the checkbox fits onto the checkbox row.
Is there a nice way to set the minimum height for these checkbox preferences without hardcoding a value?
EDIT - adding xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:key="alarm_set"
android:title="#string/set_alarm_title"
android:defaultValue="true" />
<CheckBoxPreference
android:key="store_pages"
android:title="#string/store_downloaded_pages_title"
android:summary="#string/store_downloaded_pages"
android:defaultValue="false" />
</PreferenceScreen>
Based off this question about text preference having the same iussue I use this class.
public class LongSummaryCheckBoxPreference extends CheckBoxPreference
{
public LongSummaryCheckBoxPreference(Context ctx, AttributeSet attrs, int defStyle)
{
super(ctx, attrs, defStyle);
}
public LongSummaryCheckBoxPreference(Context ctx, AttributeSet attrs)
{
super(ctx, attrs);
}
#Override
protected void onBindView(View view)
{
super.onBindView(view);
TextView summary= (TextView)view.findViewById(android.R.id.summary);
summary.setMaxLines(4);
}
}
In the xml it then looks like this.
<com.iforpowell.android.ipbike.LongSummaryCheckBoxPreference android:key="#string/key_distance_line_enable"
android:title="#string/title_distance_line_enable" android:summary="#string/summary_distance_line_enable"
android:defaultValue="true" />
<com.iforpowell.android.ipbike.LongSummaryCheckBoxPreference android:key="#string/key_altitude_line_enable"
android:title="#string/title_altitude_line_enable" android:summary="#string/summary_altitude_line_enable"
android:defaultValue="true" />
I have exactly the same thing for EditTextPreference which has the same problem of a max of 2 lines for the summary in Api <= 7
In the xml you can set the height to "wrap_content". At that point it will size it to fit whatever you put in it. So, something along these lines:
<CheckBox
android:id="#+id/checkBox1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CheckBox" />
This should help
Just do it this way:
<!-- Application theme -->
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<!-- Min item height -->
<item name="android:listPreferredItemHeight">10dp</item>
</style>
another styling attributes that can be overridden can be found here preference item layout

Categories

Resources