[英]How could I use the same set of preference screens for all Android versions from 2.X to 4.X?
注意:請節省一些時間並參考接受的答案,無需閱讀所有問題。
您可以閱讀問題的其余部分以及我提供的替代(盡管不太復雜)方法的答案。
此外,您可能希望通過將相關的代碼片段添加到您的首選項活動類中來利用Android 2.X中背景故障的修復程序。
背景
作為Android編碼的新手,但在其他編程語言/框架方面有一定的經驗,我期待我的Android應用程序編碼將是一個相當愉快的編程。 就是這樣,直到我偶然發現了這個問題:
Android項目的Eclipse向導表明,如果我將最小API設置為8(Android 2.2),我可以達到95%的設備。 無論如何我不需要用我的應用做任何花哨的事情,所以我想,“當然,為什么不呢?”。 一切都還可以,除了偶爾我會發現在最近的API版本中不推薦使用的幾個方法/類,所以我不得不設法繼續使用舊設備的舊方法,並嘗試盡可能多地使用新設備更新Android版本的方法。 這是一個這樣的場合。
在使用Eclipse向導創建首選項活動之后,我意識到Eclipse預編譯器/解析器/檢查器(或其他任何調用的)Lint會抱怨無法使用在舊API版本中創建/管理首選項的新方法。 所以我想,“好吧,擰緊新的方法。讓我們以舊的方式去做,因為新的API版本應該向后兼容,它應該沒問題”,但事實並非如此。 舊方法使用標記為已棄用的方法/類; 對我來說,這意味着,即使它們仍然在當前的API中工作,它們也會在將來的版本中停止工作。
所以我開始尋找正確的方法,最后點擊此頁面: 在PreferenceActivity中使用什么而不是“addPreferencesFromResource”? Garret Wilson解釋了一種以與新方式兼容的方式使用舊的偏好屏幕資源的方法。 這很棒,最后我覺得我可以繼續使用我的應用程序編碼,除非它在定位舊API時不起作用,因為它使用了更新的API代碼。 因此,我必須設計一種方法,使其適用於舊API和更新的API。 經過一段時間的修補后,我設法找到了一種方法,通過使用預編譯器(或其他任何名稱)注釋和偉大的getClass()。getMethod()以及異常。
在創建首選項子屏幕之前,一切似乎都完美無瑕。 它在較新的Android版本中正確顯示,但是當我嘗試使用舊版本時,我只能看到黑屏。 經過大量搜索后,我找到了解釋此問題的頁面: http : //code.google.com/p/android/issues/detail?id = 4611這顯然是一個眾所周知的故障,它已經在幾個Android版本中出現了很長時間。 我閱讀了整個帖子並找到了幾個問題的解決方案,但我真的不完全喜歡它們中的任何一個。 就我而言,我更願意盡可能避免使用靜態內容,並以編程方式執行操作。 我更喜歡自動化而非重復性工作。 一些解決方案建議將子屏幕創建為父屏幕,然后將它們添加到清單文件中,並通過意圖從父屏幕調用它們。 我真的很討厭跟蹤那些事情:清單中的條目,分離的屏幕資源文件,意圖......所以這對我來說是禁忌。 我一直在尋找並找到了一種我更喜歡的程序化方法......卻發現它不起作用。 它包括迭代首選屏幕的整個視圖樹並為偏好子屏幕分配適當的背景,但它只是不起作用,因為我后來在經過大量調試后發現,偏好子屏幕視圖不是偏好屏幕視圖的子項。 我必須找到一種方法來實現這一目標。 我嘗試了許多我能想到的東西,研究和研究無濟於事。 我幾次瀕臨放棄,但經過兩周的持續努力和大量調試后,我找到了一個解決方法,我在評論#35中發布了這個。
意見
它確實不是完美的解決方案/方法,我知道它的一些缺點,但它是有效的,所以我決定分享它。 希望我的熱情並不是太荒謬,因為我知道任何經驗豐富的編碼員都可以解決這個問題並不是很重要。 但是,嘿,我認為分享知識會讓我好一點,無論我吹噓多少,都比一個經驗豐富的編碼員能讓自己保持一切。 只是分享我的意見,因為我無法相信以前沒有人遇到過這個問題,但我確實相信很多人已經擁有它並且沒有費心去分享他們的知識。
我在答案中提出了一個建議的類,用於Android的幾個版本,以及一些有關其用法的建議。 我願意接受討論和貢獻,以使其成為更好的課程。
已知的問題:
如果您使用的是最新的ADT插件,則可以選擇輕松創建支持大多數舊版Android以及所有新版本的首選項。
右鍵單擊您的項目 - >其他 - > Android Activity
然后選擇SettingsActivity
創建的Activity將負責處理高和低API版本,因為它使用if語句來選擇顯示首選項的適當方法。
編輯
提出了一個很好的觀點:無論API版本如何,Phone-Sized設備都使用舊的PreferenceActivity
方法。
讓API 11+設備使用Fragments
的最快方法是刪除!isXLargeTablet(context);
來自isSimplePreferences()
private static boolean isSimplePreferences(Context context) {
return ALWAYS_SIMPLE_PREFS
|| Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB;
}
但是,現在用戶有更多導航要做。
這是因為onBuildHeaders()
。
要擺脫這種情況,我們需要創建自己的PreferenceFragment來添加每個xml資源。
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class AllPreferencesFragment extends PreferenceFragment{
@Override
public void onCreate (Bundle savedInstanceState){
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_general);
// Add 'notifications' preferences, and a corresponding header.
PreferenceCategory fakeHeader = new PreferenceCategory(getActivity());
fakeHeader.setTitle(R.string.pref_header_notifications);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_notification);
// Add 'data and sync' preferences, and a corresponding header.
fakeHeader = new PreferenceCategory(getActivity());
fakeHeader.setTitle(R.string.pref_header_data_sync);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_data_sync);
// 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("example_text"));
bindPreferenceSummaryToValue(findPreference("example_list"));
bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"));
bindPreferenceSummaryToValue(findPreference("sync_frequency"));
}
}
如果您可以從啟動設置的Activity
外部確定屏幕大小,則可以指定要通過EXTRA_SHOW_FRAGMENT
啟動的片段
i.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT, "com.example.test.SettingsActivity$AllPreferencesFragment");
或者您可以讓SettingsActivity
確定是否顯示此片段(假設您對isXLargeTablet()
方法感到滿意。
將onBuildHeaders()
更改為:
@Override
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void onBuildHeaders(List<Header> target) {
if (!isSimplePreferences(this) && isXLargeTablet(this)) {
loadHeadersFromResource(R.xml.pref_headers, target);
}
}
添加此方法:
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void setupNewApiPhoneSizePreferences() {
if (!isXLargeTablet(this) && Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB){
getFragmentManager().beginTransaction().replace(android.R.id.content, new AllPreferencesFragment()).commit();
}
}
並在onPostCreate()
添加方法調用。
setupNewApiPhoneSizePreferences();
現在應該使用API 11以后的非棄用調用。
您可以使用此類在2.X到4.X的所有Android版本中顯示首選項屏幕,方法是使用首選項屏幕資源。
如果您願意,可以通過重命名直接使用它,但我建議您按原樣將其添加到項目中,並從中繼承,如果您需要使用多個父偏好設置屏幕,則可以更加清晰。
如果您想直接使用它,只需將prefs值替換為您的首選項屏幕資源ID。
如果你想繼承它,你應該這樣做:
import android.os.Bundle;
public class MyPreferencesActivity extends CompatiblePreferenceActivity
{
@Override
protected void onCreate(final Bundle savedInstanceState)
{
setPrefs(R.xml.mypreferencesactivity);
super.onCreate(savedInstanceState);
}
}
在調用super.onCreate(Bundle)之前總是調用setPrefs(int)
如果由於某種原因,您只想利用故障修復並自己創建首選項,您可以將故障修復代碼復制到您自己的首選項活動中,或者從類中繼承並捕獲PrefsNotSet異常如下:
import android.os.Bundle;
public class MyPreferencesActivity extends CompatiblePreferenceActivity
{
@Override
protected void onCreate(final Bundle savedInstanceState)
{
try{
super.onCreate(savedInstanceState);
}catch(PrefsNotSetException e){};
}
}
最后,班級:
import android.annotation.TargetApi;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
public class CompatiblePreferenceActivity extends PreferenceActivity
{
private int prefs=0;
//Get/Set
public void setPrefs(int prefs)
{
this.prefs=prefs;
}
//Exception
protected static class PrefsNotSetException extends RuntimeException
{
private static final long serialVersionUID = 1L;
PrefsNotSetException()
{
super("\"prefs\" should be set to a valid preference resource ID.");
}
}
//Creation
@Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (prefs==0)
throw new PrefsNotSetException();
else
try {
getClass().getMethod("getFragmentManager");
AddResourceApi11AndGreater();
}
catch (NoSuchMethodException e) { //Api < 11
AddResourceApiLessThan11();
}
}
@SuppressWarnings("deprecation")
protected void AddResourceApiLessThan11()
{
addPreferencesFromResource(prefs);
}
@TargetApi(11)
protected void AddResourceApi11AndGreater()
{
PF.prefs=prefs;
getFragmentManager().beginTransaction().replace(
android.R.id.content, new PF()).commit();
}
@TargetApi(11)
public static class PF extends PreferenceFragment
{
private static int prefs;
@Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(prefs);
}
}
//Sub-screen background glitch fix
@SuppressWarnings("deprecation")
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
Preference preference)
{
super.onPreferenceTreeClick(preferenceScreen, preference);
if (preference!=null)
if (preference instanceof PreferenceScreen)
if (((PreferenceScreen)preference).getDialog()!=null)
((PreferenceScreen)preference).getDialog().
getWindow().getDecorView().
setBackgroundDrawable(this.getWindow().
getDecorView().getBackground().getConstantState().
newDrawable());
return false;
}
}
好吧,使用自動生成的SettingsActivity很快就開始了。 一個人必須向上和向下滾動樣板代碼 - 而且它充滿了黃色警告而且我討厭黃色(盡管不能完全避免使用過的警告 - 請參閱在PreferenceActivity中使用什么而不是“addPreferencesFromResource”?如何使交叉API PreferenceActivity
也被觸及 - 並且有意將PreferenceFragment從兼容性包中排除?討論)。 而且你也可以輕松獲得一個NPE - 你知道onPostCreate()
實際上是onPostStart()
- 所以findPreference()
在onStart()
返回null
。
現在有涉及反思,但反思的解決方案是要避免的(像地獄它是) -因為我們不感興趣,前2個版本的Android反射能夠避免的(見正在檢查SDK_INT不夠,或者需要使用較新的Android延遲加載API?為什么? )。 還有一些解決方案涉及在運行時選擇一個類 - 但是有兩個類很糟糕而且不是OOP(對於那些和其他解決方案,請參閱相關問題的答案: PreferenceActivity Android 4.0及更早版本 )。
所以我想出了一個抽象的基類,這是正確的Java和OO做事方式(除非你需要Eclair,下面你需要反射和/或延遲加載類以避免VerifyErrors
),我移動了自動生成的樣板代碼:
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import java.util.List;
/**
* A {@link PreferenceActivity} that presents a set of application settings. On
* handset devices, settings are presented as a single list. On tablets,
* settings are split by category, with category headers shown to the left of
* the list of settings.
* <p>
* See <a href="http://developer.android.com/design/patterns/settings.html">
* Android Design: Settings</a> for design guidelines and the <a
* href="http://developer.android.com/guide/topics/ui/settings.html">Settings
* API Guide</a> for more information on developing a Settings UI.
*
* Defines two abstract methods that need be implemented by implementators.
*/
public abstract class BaseSettings extends PreferenceActivity {
/**
* 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;
/**
* Helper method to determine if the device has an extra-large screen. For
* example, 10" tablets are extra-large.
*/
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
private static boolean isXLargeTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout &
Configuration.SCREENLAYOUT_SIZE_MASK)
>= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
/** {@inheritDoc} */
@Override
public final boolean onIsMultiPane() { // never used by us
return isXLargeTablet(this) && !isSimplePreferences(this);
}
/**
* 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 final boolean isSimplePreferences(Context context) {
return ALWAYS_SIMPLE_PREFS
|| Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB
|| !isXLargeTablet(context);
}
@Override
protected final void onCreate(Bundle savedInstanceState) {
// disallow onCreate(), see comment in onPostCreate()
super.onCreate(savedInstanceState);
}
@Override
protected final void onStart() {
// disallow onStart(), see comment in onPostCreate()
super.onStart();
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
// onPostCreate() probably is needed because onBuildHeaders() is called
// after onCreate() ? This piece of err code should be called
// onPostStart() btw - so yeah
super.onPostCreate(savedInstanceState);
setupSimplePreferencesScreen();
// findPreference will return null if setupSimplePreferencesScreen
// hasn't run, so I disallow onCreate() and onStart()
}
/**
* 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;
}
buildSimplePreferences();
}
/** {@inheritDoc} */
/*
* Subclasses of PreferenceActivity should implement onBuildHeaders(List) to
* populate the header list with the desired items. Doing this implicitly
* switches the class into its new "headers + fragments" mode rather than
* the old style of just showing a single preferences list (from
* http://developer
* .android.com/reference/android/preference/PreferenceActivity.html) -> IE
* this is called automatically - reads the R.xml.pref_headers and creates
* the 2 panes view - it was driving me mad - @inheritDoc my - It does not
* crash in Froyo cause isSimplePreferences is always true for
* Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB - @Override has
* nothing to do with runtime and of course on Froyo this is never called by
* the system
*/
@Override
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public final void onBuildHeaders(List<Header> target) {
if (!isSimplePreferences(this)) {
loadHeadersFromResource(getHeadersXmlID(), target);
}
}
// =========================================================================
// Abstract API
// =========================================================================
/**
* Must return an id for the headers xml file. There you define the headers
* and the corresponding PreferenceFragment for each header which you must
* of course implement. This is used in the super implementation of
* {@link #onBuildHeaders(List)}
*
* @return an id from the R file for the xml containing the headers
*/
abstract int getHeadersXmlID();
/**
* Builds a pre Honeycomb preference screen. An implementation would use the
* (deprecated)
*{@link android.preference.PreferenceActivity#addPreferencesFromResource(int)}
*/
abstract void buildSimplePreferences();
}
一個示例實現:
public final class SettingsActivity extends BaseSettings implements
OnSharedPreferenceChangeListener {
private static final int PREF_HEADERS_XML = R.xml.pref_headers;
private static CharSequence master_enable;
private OnPreferenceChangeListener listener;
private static Preference master_pref;
private static final String TAG = SettingsActivity.class.getSimpleName();
private SharedPreferences sp;
/** Used as canvas for the simple preferences screen */
private static final int EMPTY_PREF_RESOURCE = R.xml.pref_empty;
private static int PREF_RESOURCE_SETTINGS = R.xml.pref_data_sync;
// abstract overrides
@Override
int getHeadersXmlID() {
return PREF_HEADERS_XML;
}
@Override
void buildSimplePreferences() {
// In the simplified UI, fragments are not used at all and we instead
// use the older PreferenceActivity APIs.
// THIS is a blank preferences layout - which I need so
// getPreferenceScreen() does not return null - so I can add a header -
// alternatively you can very well comment everything out apart from
// addPreferencesFromResource(R.xml.pref_data_sync);
addPreferencesFromResource(EMPTY_PREF_RESOURCE);
// Add 'data and sync' preferences, and a corresponding header.
PreferenceCategory fakeHeader = new PreferenceCategory(this);
fakeHeader.setTitle(R.string.pref_header_data_sync);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(PREF_RESOURCE_SETTINGS);
}
// here is the work done
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
master_enable = getResources().getText(
R.string.enable_monitoring_master_pref_key);
listener = new ToggleMonitoringListener();
// DefaultSharedPreferences - register listener lest Monitor aborts
sp = PreferenceManager.getDefaultSharedPreferences(this);
sp.registerOnSharedPreferenceChangeListener(this);
master_pref = findPreference(master_enable.toString());
}
@Override
protected void onResume() {
super.onResume();
master_pref.setOnPreferenceChangeListener(listener); // no way to
// unregister, see: https://stackoverflow.com/a/20493608/281545 This
// listener reacts to *manual* updates - so no need to be active
// outside onResume()/onPause()
}
@Override
protected void onDestroy() {
// may not be called (as onDestroy() is killable), but no leak,
// see: https://stackoverflow.com/a/20493608/281545
sp.unregisterOnSharedPreferenceChangeListener(this);
super.onDestroy();
}
/**
* Toggles monitoring and sets the preference summary.Triggered on *manual*
* update of the *single* preference it is registered with, but before this
* preference is updated and saved.
*/
private static class ToggleMonitoringListener implements
OnPreferenceChangeListener {
ToggleMonitoringListener() {}
@Override
public boolean
onPreferenceChange(Preference preference, Object newValue) {
if (newValue instanceof Boolean) {
final boolean enable = (Boolean) newValue;
Monitor.enableMonitoring(preference.getContext(), enable);
final CheckBoxPreference p = (CheckBoxPreference) preference;
preference.setSummary((enable) ? p.getSummaryOn() : p
.getSummaryOff());
return true;
}
return false;
}
}
/**
* This fragment is used when the activity is showing a two-pane
* settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public final static class DataSyncPreferenceFragment extends
PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.w(TAG, "onCreate");
addPreferencesFromResource(PREF_RESOURCE_SETTINGS);
master_pref = findPreference(master_enable.toString());
}
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
if (master_enable == null || master_pref == null) return;
if (master_enable.toString().equals(key)) {
refreshMasterPreference();
}
}
/**
* @param key
*/
private void refreshMasterPreference() {
final Boolean isMonitoringEnabled = AccessPreferences.get(this,
master_enable.toString(), false);
Log.w(TAG, "Stored value: " + isMonitoringEnabled);
final CheckBoxPreference p = (CheckBoxPreference) master_pref;
final boolean needsRefresh = p.isChecked() != isMonitoringEnabled;
if (needsRefresh) {
p.setChecked(isMonitoringEnabled);
p.setSummary((isMonitoringEnabled) ? p.getSummaryOn() : p
.getSummaryOff());
}
}
}
所以主要的想法是你為帶頭的首選項提供一個xml:
public final void onBuildHeaders(List<Header> target) {
if (!isSimplePreferences(this)) {
loadHeadersFromResource(getHeadersXmlID(), target);
}
}
哪里:
@Override
int getHeadersXmlID() {
return PREF_HEADERS_XML;
}
和PREF_HEADERS_XML
:
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- These settings headers are only used on tablets. -->
<header
android:fragment=".activities.SettingsActivity$DataSyncPreferenceFragment"
android:title="@string/pref_header_data_sync" />
</preference-headers>
並在buildSimplePreferences()
設置簡單首選項
我有興趣將它變成一個更通用的API - 可能包括sBindPreferenceSummaryToValueListener
- 所以歡迎這些想法。
啊,是的,sBindPreferenceSummaryToValueListener絨毛:
// FLUFF AHEAD:
// the fluff that follows is for binding preference summary to value -
// essentially wrappers around OnPreferenceChangeListener - just so
// you get an idea of the mess this autogenerated piece of, code, was
// formatter:off
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
*/
/* private static Preference.OnPreferenceChangeListener
sBindPreferenceSummaryToValueListener =
new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference,
Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value
// in the preference's 'entries' list.
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
// Set the summary to reflect the new value.
preference.setSummary(index >= 0
? listPreference.getEntries()[index] : null);
} else if (preference instanceof RingtonePreference) {
// For ringtone preferences, look up the correct display
// value using RingtoneManager.
if (TextUtils.isEmpty(stringValue)) {
// Empty values correspond to 'silent' (no ringtone).
// preference.setSummary(R.string.pref_ringtone_silent);
} else {
Ringtone ringtone = RingtoneManager.getRingtone(
preference.getContext(), Uri.parse(stringValue));
if (ringtone == null) {
// Clear the summary if there was a lookup error.
preference.setSummary(null);
} else {
// Set the summary to reflect the new ringtone
// display name.
String name = ringtone
.getTitle(preference.getContext());
preference.setSummary(name);
}
}
} else if (preference instanceof CheckBoxPreference) {
boolean b = (Boolean) value;
Log.w(TAG, "::::value " + b);
final CheckBoxPreference p =(CheckBoxPreference)preference;
preference.setSummary((b) ? p.getSummaryOn() : p
.getSummaryOff());
Log.w(TAG, p.getKey() + " :: " + p.isChecked());
} else {
// For all other preferences, set the summary to the value's
// simple string representation.
preference.setSummary(stringValue);
}
return true;
}
}; */
/**
* Binds a preference's summary to its value. More specifically, when the
* preference's value is changed, its summary (line of text below the
* preference title) is updated to reflect the value. The summary is also
* immediately updated upon calling this method. The exact display format is
* dependent on the type of preference.
*
* @see #sBindPreferenceSummaryToValueListener
*/
/* private static void bindPreferenceSummaryToValue(Preference preference) {
// Set the listener to watch for value changes.
preference
.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
// Trigger the listener immediately with the preference's
// current value.
sBindPreferenceSummaryToValueListener.onPreferenceChange(
preference,
PreferenceManager.getDefaultSharedPreferences(
preference.getContext()).getString(preference.getKey(), ""));
} */
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.