Отображение значения EditTextPreference в сводке

Я изучаю, как развиваться в Android и хочу сделать настройку,

Моя активность настройки

public class Main extends Activity  {


    protected SettingsFragment settingsFragment;


    @SuppressLint("NewApi")
    @TargetApi(11)
    public class SettingsFragment extends PreferenceFragment implements
            SharedPreferences.OnSharedPreferenceChangeListener {


        @Override
        public void onCreate(Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.preferences);
            setSummaries();


        }


        @Override
        public void onResume() {
            final SharedPreferences sh = getPreferenceManager().getSharedPreferences() ;
            super.onResume();
            sh.registerOnSharedPreferenceChangeListener(this);

        }

        @Override
        public void onPause() {
            final SharedPreferences sh = getPreferenceManager().getSharedPreferences() ;
            super.onPause();
            sh.unregisterOnSharedPreferenceChangeListener(this);
        }

        @SuppressLint("NewApi")
        public void setSummaries(){

           final SharedPreferences sh = getPreferenceManager().getSharedPreferences() ;


            //Pref1
            Preference stylePref = findPreference("editTextPref");
            stylePref.setSummary(sh.getString("editTextPref", ""));

            //here the other preferences..
        }


        @Override
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
            if (key.equals("editTextPref")) {
                Preference pref = settingsFragment.findPreference(key);
                // Set summary to be the user-description for the selected value
                pref.setSummary(sharedPreferences.getString(key, ""));

            }
            //here the others preferences
        }
    }//End fragment

    @SuppressLint("NewApi")
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        settingsFragment = new SettingsFragment();
        getFragmentManager().beginTransaction()
                .replace(android.R.id.content, settingsFragment)
                .commit();


    }


}

и мой res/preferences.xml файл

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory
        android:title="BTA"
        xmlns:android="http://schemas.android.com/apk/res/android">


        <EditTextPreference
            android:key="editTextPref"
            android:title="Numero de telephone"
            android:summary="This allows you to enter a string"
            android:defaultValue="*"/>

    </PreferenceCategory>

</PreferenceScreen>

Итак, теперь у меня есть активность для активности настройки. Но я хочу показать значение EditTextPref в android:summary. Я нашел много тем, но все функции были устаревшими.

EDIT: благодаря @Ace_McIntosh, я редактировал свой код для людей, которые этого хотят, теперь он работает.

Ответ 1

Просто используйте setSummary method на желаемом объекте Preference. Назовите его, возобновив фрагмент настроек для каждой записи, которую вы хотите обновить (т.е. Все записи EditTextPreference в вашем случае) и зарегистрируйте OnSharedPreferenceChangeListener на конкретном объекте SharedPreferences (чтобы вы могли обновить сводку в если он изменен) - и передайте ему желаемое значение EditTextPreference (которое вы можете получить с помощью метода getText()).

Реализуйте его в своем MyPreferenceFragment, как это (я не гарантирую, что он будет работать с самого начала, он служит цели, чтобы просто дать вам идею):

public class MyPreferenceFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
    SharedPreferences sharedPreferences;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // load the preferences from your XML resource (which I assume you already do anyway)
        addPreferencesFromResource(R.xml.preferences);
    }

    @Override
    public void onResume() {
        super.onResume();

        sharedPreferences = getPreferenceManager().getSharedPreferences();

        // we want to watch the preference values' changes
        sharedPreferences.registerOnSharedPreferenceChangeListener(this);

        Map<String, ?> preferencesMap = sharedPreferences.getAll();
        // iterate through the preference entries and update their summary if they are an instance of EditTextPreference
        for (Map.Entry<String, ?> preferenceEntry : preferencesMap.entrySet()) {
            if (preferenceEntry instanceof EditTextPreference) {
                updateSummary((EditTextPreference) preferenceEntry);
            }
        }
    }

    @Override
    public void onPause() {
        sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
        super.onPause();
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
                                          String key) {
        Map<String, ?> preferencesMap = sharedPreferences.getAll();

        // get the preference that has been changed
        Object changedPreference = preferencesMap.get(key);
        // and if it an instance of EditTextPreference class, update its summary
        if (preferencesMap.get(key) instanceof EditTextPreference) {
            updateSummary((EditTextPreference) changedPreference);
        }
    }

    private void updateSummary(EditTextPreference preference) {
        // set the EditTextPreference summary value to its current text
        preference.setSummary(preference.getText());
    }
}

Ответ 2

Просто переопределите getSummary для EditTextPreference, и вы получите EditTextPreference, значение которого отображается в виде сводки.

public class EditSummaryPreference extends EditTextPreference {
    ...// omit constructor

    @Override
    public CharSequence getSummary() {
        return getText();
    }
}

Ответ 3

Самый простой способ - создать собственный класс EditTextPreference (изменен для компиляции):

package your.package;

import android.content.Context;
import android.util.AttributeSet;

public class EditTextPreference extends android.preference.EditTextPreference{
        public EditTextPreference(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }

        public EditTextPreference(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        public EditTextPreference(Context context) {
            super(context);
        }

        @Override
        public CharSequence getSummary() {
            if ( super.getSummary() == null ) { return null; }
            String summary = super.getSummary().toString();
            return String.format(summary, getText());
        }
    }

И используйте это в своем xml:

<your.package.EditTextPreference
                android:key="pref_alpha"
                android:summary="Actual value: %s"
                android:title="Title"
                android:defaultValue="default"
                />

Ответ 4

(В Kotlin) Я бы предпочел сделать что-то более простое и просто создать класс, который расширяет EditTextPreference:

import android.content.Context
import android.support.v7.preference.EditTextPreference
import android.util.AttributeSet

/**
 * This class was created by Anthony M Cannon on 17/04/2018.
 */
class SummarisedEditTextPreference @JvmOverloads constructor(context: Context,
    attrs: AttributeSet? = null) : EditTextPreference(context, attrs) {

    private var mOnChangeListener: OnPreferenceChangeListener? = null

    init {
        super.setOnPreferenceChangeListener { preference, newValue ->
            summary = newValue as String
            mOnChangeListener?.onPreferenceChange(preference, newValue) ?: true
        }
    }

    /**
    * Called when this Preference has been attached to a Preference hierarchy.
    * Make sure to call the super implementation.
    *
    * @param preferenceManager The PreferenceManager of the hierarchy.
    */
    override fun onAttachedToHierarchy(preferenceManager: PreferenceManager) {
        super.onAttachedToHierarchy(preferenceManager)
        summary = sharedPreferences.getString(key, null)
    }


    /**
     * Sets the callback to be invoked when this Preference is changed by the
     * user (but before the internal state has been updated).
     *
     * @param onPreferenceChangeListener The callback to be invoked.
     */
    override fun setOnPreferenceChangeListener(
        onPreferenceChangeListener: OnPreferenceChangeListener) {
        mOnChangeListener = onPreferenceChangeListener
    }
}

Затем вы можете использовать это так:

< <Имя пакета> .SummarisedEditTextPreference/>

Ответ 5

Там некоторые ошибки в примере выше, поэтому я решил опубликовать рабочее решение (также поддерживает ListPreference и MultiSelectListPreference)

public class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {

private SharedPreferences sharedPreferences;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.settings);
}

@Override
public void onResume() {
    super.onResume();

    sharedPreferences = getPreferenceManager().getSharedPreferences();
    sharedPreferences.registerOnSharedPreferenceChangeListener(this);

    PreferenceScreen preferenceScreen = getPreferenceScreen();
    for(int i = 0; i < preferenceScreen.getPreferenceCount(); i++) {
        setSummary(getPreferenceScreen().getPreference(i));
    }
}

@Override
public void onPause() {
    sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
    super.onPause();
}

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    Preference pref = getPreferenceScreen().findPreference(key);
    setSummary(pref);
}

private void setSummary(Preference pref) {
    if (pref instanceof EditTextPreference) {
        updateSummary((EditTextPreference) pref);
    } else if (pref instanceof ListPreference) {
        updateSummary((ListPreference) pref);
    } else if (pref instanceof MultiSelectListPreference) {
        updateSummary((MultiSelectListPreference) pref);
    }
}

private void updateSummary(MultiSelectListPreference pref) {
    pref.setSummary(Arrays.toString(pref.getValues().toArray()));
}

private void updateSummary(ListPreference pref) {
    pref.setSummary(pref.getValue());
}

private void updateSummary(EditTextPreference preference) {
    preference.setSummary(preference.getText());
}
}

Ответ 6

Ответ @serv-inc работал у меня. Как-то другие ответы работали только при изменении значения.

Но прежде чем это сработало, мне пришлось внести изменения, как показано ниже:

@Override
public CharSequence getSummary() {
    return getText();
}

Показывает значение, когда оно отображается, когда изменяется значение, а также после возобновления.

Ответ 7

Построение Uppon Ответ Бретта Черрингтона, реализация в Котлине. Была ошибка, а именно то, что PreferenceCategories не поддерживались, что исправлено с помощью дополнительного рекурсивного цикла в setSummary

class SettingsFragment : PreferenceFragment(), SharedPreferences.OnSharedPreferenceChangeListener {

    private lateinit var sharedPreferences: SharedPreferences

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        addPreferencesFromResource(R.xml.preferences)
    }

    override fun onResume() {
        super.onResume()

        sharedPreferences = preferenceManager.sharedPreferences
        sharedPreferences.registerOnSharedPreferenceChangeListener(this)

        val preferenceScreen = preferenceScreen
        for (i in 0 until preferenceScreen.preferenceCount) {
            setSummary(getPreferenceScreen().getPreference(i))
        }
    }

    override fun onPause() {
        sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
        super.onPause()
    }

    override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
        val pref = preferenceScreen.findPreference(key)
        pref?.let { setSummary(it) }
    }

    private fun setSummary(pref: Preference) {
        if (pref is EditTextPreference) {
            updateSummary(pref)
        } else if (pref is ListPreference) {
            updateSummary(pref)
        } else if (pref is MultiSelectListPreference) {
            updateSummary(pref)
        } else if (pref is PreferenceCategory){
            // needs to loop through child preferences
            for (i in 0 until pref.preferenceCount) {
                setSummary(pref.getPreference(i))
            }
        }
    }

    private fun updateSummary(pref: MultiSelectListPreference) {
        pref.setSummary(Arrays.toString(pref.values.toTypedArray()))
    }

    private fun updateSummary(pref: ListPreference) {
        pref.summary = pref.value
    }

    private fun updateSummary(preference: EditTextPreference) {
        preference.summary = preference.text
    }
}

Ответ 8

В библиотеке androidx EditTextPreference имеет атрибут app: useSimpleSummaryProvider. Используя атрибут, вам не нужно расширять какой-либо класс или прослушивать какие-либо изменения в SharedPreferences. Вы можете проверить пример кода по адресу https://github.com/googlesamples/android-preferences/blob/master/app/src/main/res/xml/dialogs.xml.

Ответ 9

В дополнение к @Eke Koseoglu ответ.

Если вы используете библиотеку настроек AndroidX, вы можете установить summaryProvider из кода Kotlin ниже.

val editTextPreference = EditTextPreference(context)
editTextPreference.summaryProvider = EditTextPreference.SimpleSummaryProvider.getInstance()

Согласно документации EditTextPreference.SimpleSummaryProvider;

Если значение не было установлено, отображаемая сводка будет "Не установлена", в противном случае отображаемая сводка будет значением, установленным для этого предпочтения.