我有一个非常奇怪的问题。当我滚动我的“设置 - 活动”时,一些复选框会在不再显示时发生变化。例如:我取消选中广告复选框,然后向下滚动,当复选框完全取消时,复选框将重置。这只发生在我取消选中一个复选框时,默认值没有任何影响。
我的活动:
public class SettingsActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
/**
* Determines whether to always show the simplified settings UI, where
* settings are presented in a single list. When false, settings are shown
* as a master/detail two-pane view on tablets. When true, a single pane is
* shown on tablets.
*/
private static final boolean ALWAYS_SIMPLE_PREFS = false;
private SharedPreferences prefs;
private Tracker mTracker;
private void analytics() {
if(prefs.getBoolean(Tags.PREF_GOOGLEANALYTICS, true)) {
// Obtain the shared Tracker instance.
AnalyticsApplication application = (AnalyticsApplication) getApplication();
mTracker = application.getDefaultTracker();
mTracker.setScreenName("SettingsActivity");
mTracker.send(new HitBuilders.ScreenViewBuilder().build());
}
}
private void analytics(String category, String action) {
if(prefs.getBoolean(Tags.PREF_GOOGLEANALYTICS, true)) {
if (mTracker == null) {
AnalyticsApplication application = (AnalyticsApplication) getApplication();
mTracker = application.getDefaultTracker();
}
mTracker.send(new HitBuilders.EventBuilder()
.setCategory(category)
.setAction(action)
.build());
}
}
private void setLocale(String lang) {
/*Locale myLocale = new Locale(lang);
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, dm);*/
Locale locale = new Locale(lang);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
Intent refresh = new Intent(this, MainActivity.class);
startActivity(refresh);
finish();
}
@Override
protected void onResume() {
super.onResume();
prefs.registerOnSharedPreferenceChangeListener(this);
}
@Override
protected void onPause() {
super.onPause();
prefs.unregisterOnSharedPreferenceChangeListener(this);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
prefs = PreferenceManager.getDefaultSharedPreferences(this);
analytics();
Toolbar bar;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
LinearLayout root = (LinearLayout) findViewById(android.R.id.list).getParent().getParent().getParent();
bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);
root.addView(bar, 0); // insert at top
} else {
ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
ListView content = (ListView) root.getChildAt(0);
root.removeAllViews();
bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);
int height;
TypedValue tv = new TypedValue();
if (getTheme().resolveAttribute(R.attr.actionBarSize, tv, true)) {
height = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics());
}else{
height = bar.getHeight();
}
content.setPadding(0, height, 0, 0);
root.addView(content);
root.addView(bar);
}
bar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
setupSimplePreferencesScreen();
}
/**
* Shows the simplified settings UI if the device configuration if the
* device configuration dictates that a simplified, single-pane UI should be
* shown.
*/
private void setupSimplePreferencesScreen() {
if (!isSimplePreferences(this)) {
return;
}
// In the simplified UI, fragments are not used at all and we instead
// use the older PreferenceActivity APIs.
// Add 'general' preferences.
addPreferencesFromResource(R.xml.pref_general);
// Add 'notifications' preferences, and a corresponding header.
PreferenceCategory fakeHeader = new PreferenceCategory(this);
fakeHeader.setTitle(getResources().getString(R.string.pref_notifications));
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_notification);
PreferenceCategory fakeHeaderAudio = new PreferenceCategory(this);
fakeHeaderAudio.setTitle(getResources().getString(R.string.pref_audio));
getPreferenceScreen().addPreference(fakeHeaderAudio);
addPreferencesFromResource(R.xml.pref_audio);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences to
// their values. When their values change, their summaries are updated
// to reflect the new value, per the Android Design guidelines.
// bindPreferenceSummaryToValue(findPreference(getString(R.string.key_checkbox)));
}
/**
* {@inheritDoc}
*/
@Override
public boolean onIsMultiPane() {
return isXLargeTablet(this) && !isSimplePreferences(this);
}
/**
* Helper method to determine if the device has an extra-large screen. For
* example, 10" tablets are extra-large.
*/
private static boolean isXLargeTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
/**
* Determines whether the simplified settings UI should be shown. This is
* true if this is forced via {@link #ALWAYS_SIMPLE_PREFS}, or the device
* doesn't have newer APIs like {@link PreferenceFragment}, or the device
* doesn't have an extra-large screen. In these cases, a single-pane
* "simplified" settings UI should be shown.
*/
private static boolean isSimplePreferences(Context context) {
return ALWAYS_SIMPLE_PREFS
|| (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
|| !isXLargeTablet(context);
}
/**
* {@inheritDoc}
*/
@Override
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void onBuildHeaders(List<Header> target) {
if (!isSimplePreferences(this)) {
loadHeadersFromResource(R.xml.pref_headers, target);
}
}
@Override
protected boolean isValidFragment(String fragmentName) {
return NotificationPreferenceFragment.class.getName().equals(fragmentName)
|| GeneralPreferenceFragment.class.getName().equals(fragmentName)
|| AudioPreferenceFragment.class.getName().equals(fragmentName);
}
@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
if(key.equals(Tags.PREF_NOTIFICATION)
|| key.equals(Tags.PREF_NOTIFICATIONTIME)
|| key.equals(Tags.PREF_AUDIO_AUTODOWNLOAD)) {
if(sharedPreferences.getBoolean(Tags.PREF_NOTIFICATION, true)
|| sharedPreferences.getBoolean(Tags.PREF_AUDIO_AUTODOWNLOAD, true)) {
long time = sharedPreferences.getLong(Tags.PREF_NOTIFICATIONTIME, 60 * 7);
Notifications.setNotifications(this, time * 60 * 1000);
} else
Notifications.removeNotifications(this);
}
if(key.equals(Tags.PREF_NOTIFICATION) || key.equals(Tags.PREF_ADS)
|| key.equals(Tags.PREF_GOOGLEANALYTICS) || key.equals(Tags.PREF_SHOWNOTES)) {
//This toast is shown when I scroll down
Toast.makeText( getApplicationContext(), "Notification || Analytics", Toast.LENGTH_SHORT).show();
analytics("Settings", "Settings: " + key + ", " + sharedPreferences.getBoolean(key, true));
}
//Language change
if(key.equals(Tags.PREF_LANGUAGE)) {
try {
setLocale(sharedPreferences.getString(key, "en"));
} catch (Exception e) {
Log.e("Losungen", "Error changing language: " + e.getMessage());
e.printStackTrace();
}
}
//SD-Card change
if(key.equals(Tags.PREF_AUDIO_EXTERNAL_STORGAE)) {
boolean sd_card = sharedPreferences.getBoolean(key, false);
if(sd_card)
MainActivity.toast(this, this.getString(R.string.still_in_internal), Toast.LENGTH_LONG);
else
MainActivity.toast(this, this.getString(R.string.still_in_external), Toast.LENGTH_LONG);
}
}
/**
* This fragment shows general preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class GeneralPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_general);
}
}
/**
* This fragment shows notification preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class NotificationPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_notification);
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class AudioPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_audio);
}
}
}
我的xml文件: pref_general.xml
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<SwitchPreference
android:key="show_notes"
android:title="@string/pref_notes_title"
android:defaultValue="true" />
<SwitchPreference
android:key="show_ads"
android:title="@string/pref_ads_title"
android:summary="@string/pref_ads_summary"
android:defaultValue="false"
/>
<SwitchPreference
android:key="google_analytics"
android:title="@string/pref_google_title"
android:summary="@string/pref_google_summary"
android:defaultValue="true" />
<ListPreference
android:key="language"
android:title="@string/pref_language"
android:summary="@string/pref_language_summary"
android:entries="@array/pref_language_list_titles"
android:entryValues="@array/pref_language_list_values"
android:negativeButtonText="@null"
android:positiveButtonText="@null" />
</PreferenceScreen>
pref_notification.xml
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<!-- A 'parent' preference, which enables/disables child preferences (below)
when checked/unchecked. -->
<SwitchPreference
android:key="notifications_losung"
android:title="@string/pref_notifications"
android:defaultValue="true" />
<ListPreference
android:key="notifications_art"
android:dependency="notifications_losung"
android:title="@string/pref_notification_art"
android:defaultValue="0"
android:entries="@array/pref_notifications_list_titles"
android:entryValues="@array/pref_notifications_list_values"
android:negativeButtonText="@null"
android:positiveButtonText="@null" />
<de.schalter.losungen.preferences.TimePreference
android:key="notification_time"
android:defaultValue="420"
android:title="@string/pref_time"
android:dependency="notifications_losung"
/>
</PreferenceScreen>
pref_audio.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<!-- oder stream -->
<SwitchPreference
android:key="audio_download"
android:title="@string/pref_audio_download_title"
android:summaryOn="@string/pref_audio_download_summary_on"
android:summaryOff="@string/pref_audio_download_summary_off"
android:defaultValue="true" />
<!-- oder erst bei Nutzer interaktion -->
<SwitchPreference
android:key="audio_autodownload"
android:dependency="audio_download"
android:title="@string/pref_audio_autodownload_title"
android:summaryOn="@string/pref_audio_autodownload_summary_on"
android:summaryOff="@string/pref_audio_autodownload_summary_off"
android:defaultValue="true" />
<ListPreference
android:key="audio_autodownload_network"
android:dependency="audio_autodownload"
android:title="@string/pref_audio_autodownload_network_title"
android:defaultValue="0"
android:entries="@array/pref_audio_autodownload_network_entries"
android:entryValues="@array/pref_audio_autodownload_network_values"
android:negativeButtonText="@null"
android:positiveButtonText="@null" />
<SwitchPreference
android:key="audio_external_storage"
android:dependency="audio_download"
android:title="@string/pref_audio_externalstorage_title"
android:summaryOff="@string/pref_audio_externalstorage_summary_off"
android:summaryOn="@string/pref_audio_externalstorage_summary_on"
android:defaultValue="false" />
</PreferenceScreen>
我不知道为什么会这样。 有些评论是德语,但我认为你可以理解任何东西。有什么想法吗?
这是一个类似的问题,但没有有用的答案:Android Preferences - On/Off Switch Icons Reset When Scrolled Offscreen
答案 0 :(得分:1)
请参阅Preference items being automatically re-set?上的答案,它建议您将SwitchPreference子类化为仅调用super的构造函数,然后使用它代替标准的SwitchPreference。我注意到这发生在早期版本的Android(特别是在我们的情况下为4.x),但不是5 +。
我怀疑这种作用的原因是因为Preference的构造函数中的这些行:
从API 17(需要此修改):
if (!getClass().getName().startsWith("android.preference")) {
// For subclasses not in this package, assume the worst and don't cache views
mHasSpecifiedLayout = true;
}
或者从API 23(无需修改即可正常工作):
if (!getClass().getName().startsWith("android.preference")
&& !getClass().getName().startsWith("com.android")) {
// For non-framework subclasses, assume the worst and don't cache views.
mCanRecycleLayout = false;
}
通过PreferenceGroupAdapter向下看,它看起来像回收视图时设置的东西,然后通知侦听器偏好已经改变。我无法找到实际更改偏好的位置/原因,因此我也不确定为什么更新的API会修复它,但这似乎正在发生的事情。