偏好设置

第一步,创建一个空的Activity,准备用它来放Fragment

public class SettingActivity extends AppCompatActivity {

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

    }

}

第二步,在主窗体中加上一个菜单,来启用这个空窗体

第三步,在manifest中,设置SettingActivity的父窗体为主窗体

第四步,设置主窗体的launchMode="singleTop"

第五步,在空SettingActivity的onCreate加入下面的代码,使其中标题栏的左侧,出现一个返回按钮

        ActionBar actionBar = this.getSupportActionBar();

        // Set the action bar back button to look like an up button

        if (actionBar != null) {

            actionBar.setDisplayHomeAsUpEnabled(true);

        }

第六步:响应该返回按钮,使其向上返回。

    public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();

        if (id == android.R.id.home) {

            NavUtils.navigateUpFromSameTask(this);

        }

        return super.onOptionsItemSelected(item);

}

第七步:使用支持库7,注意小版本要和其它的小版本一致

implementation 'com.android.support:preference-v7:27.1.1'

然后同步

第八步:同步后,增加一个类,并按Ctrl+I,实现其抽象方法。

public class SettingFragment extends PreferenceFragmentCompat {

    @Override

    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {

    }

}

第九步:创建资源文件

       9.1 在res目录下,创建一个xml目录

       9.2 在xml目录下创建一个文件,fragment_setting.xml

<?xml version="1.0" encoding="utf-8"?>

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

</PreferenceScreen>

       9.3 在其中增加一个复选框的设置项,设置其5个属性

    <CheckBoxPreference

        android:defaultValue="true"

        android:key="show_bass"

        android:summaryOff="隐藏"

        android:summaryOn="显示"

        android:title="是否显示BASS"

        ></CheckBoxPreference>

十:将资源文件(fragment_setting.xml)和类(SettingFragment)结合起来

    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {

        addPreferencesFromResource(R.xml.fragment_setting);

}

十一:将Fragment加入到空窗体

把activity_setting.xml的内容,换成一个fragment,,并设置它的name为SettingFragment (注意:是类的名字,而不是资源文件的名字)

<?xml version="1.0" encoding="utf-8"?>

<fragment xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/activity_setting"

    android:name="com.code369.test1.SettingFragment"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    >

</fragment>

十二:增加一个主题,在文件Res/values/styles.xml中,如果不增加这个主题,应用会崩溃。

<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>

至此,已经把设定的界面都实现了。接下来,要在主窗体中读取设定值,并让设定值起到作用。

一:在主窗体中,写一个函数,专门用来读取设定

private void ReadSharedPreferences() {

SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);   

boolean bValue = sharedPreferences.getBoolean("show_bass", true);

}

二:在主窗体实现OnSharedPreferenceChangeListener接口

public class VisualizerActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener

三:重载该接口的一个方法onSharedPreferenceChanged,让设定值生效

    @Override

    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {

if (key.equals(“show_bass”)){           

boolean bValue = sharedPreferences.getBoolean("show_bass", true);

        }

}

四:注册这个监听器(在读取设定那个函数)

private void ReadSharedPreferences() {

SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);   

boolean bValue = sharedPreferences.getBoolean("show_bass", true);

sharedPreferences.registerOnSharedPreferenceChangeListener(this);

}

此函数一般在onCreate要进行调用

五:注销这个接收器

    protected void onDestroy() {

        super.onDestroy();

        PreferenceManager.getDefaultSharedPreferences(this)

.unregisterOnSharedPreferenceChangeListener(this);

}

列表偏好

一:在xml文件中增加列表偏好的定义

    <ListPreference

        android:defaultValue="@string/pref_color_red_value"

        android:entries="@array/pref_color_option_labels"

        android:entryValues="@array/pref_color_option_values"

        android:key="@string/pref_color_key"

        android:title="@string/pref_color_label" />

二: 在res/values下面新建一个arrays.xml,定义列表的值和显示内容

<?xml version="1.0" encoding="utf-8"?>

<resources>
    <!-- Label ordering must match values -->
    <array name="pref_color_option_labels">
        <item>@string/pref_color_label_red</item>
        <item>@string/pref_color_label_blue</item>
        <item>@string/pref_color_label_green</item>
    </array>
    <array name="pref_color_option_values">
        <item>@string/pref_color_red_value</item>
        <item>@string/pref_color_blue_value</item>
        <item>@string/pref_color_green_value</item>
    </array>
</resources>

三:读取列表偏好的值

private void loadColorFromPreferences(SharedPreferences sharedPreferences) {

mVisualizerView.setColor(sharedPreferences.getString

(“color“, ”red”));              

}

四:偏好设置摘要(设置Fragment以编程方式更新摘要)

4.1 在SettingsFragment类中,实现接口(和主窗体一样,当设定改变时,更改摘要)nSharedPreferenceChangeListener

4.2 写一个函数,用来更改一个设定的摘要

private void setPreferenceSummary(Preference preference, String value) {

    if (preference instanceof ListPreference) {

        ListPreference listPreference = (ListPreference) preference;

        int prefIndex = listPreference.findIndexOfValue(value);

        if (prefIndex >= 0) {

            listPreference.setSummary

(listPreference.getEntries()[prefIndex]);

        }

    }

}

4.3 在onCreatePreferences函数中,依次对每个设定项的摘要进行设定

SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();

PreferenceScreen prefScreen = getPreferenceScreen();

int count = prefScreen.getPreferenceCount();

 

for (int i = 0; i < count; i++) {

    Preference p = prefScreen.getPreference(i);

    if (!(p instanceof CheckBoxPreference)) {

        String value = sharedPreferences.getString(p.getKey(), "");

        setPreferenceSummary(p, value);

    }

}

 

4.4 重载接口的函数,在里面对改变的设定项,设置摘要

public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {

    Preference preference = findPreference(key);

    if (null != preference) {

        if (!(preference instanceof CheckBoxPreference)) {

            String value = sharedPreferences.getString(preference.getKey(), "");

            setPreferenceSummary(preference, value);

        }

    }

}

4.5 注册和销毁监听器

public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    getPreferenceScreen().getSharedPreferences()

            .registerOnSharedPreferenceChangeListener(this);

}

public void onDestroy() {

    super.onDestroy();

    getPreferenceScreen().getSharedPreferences()

            .unregisterOnSharedPreferenceChangeListener(this);

}

文本偏好

一:在xml文件中增加该设定项

<EditTextPreference

    android:defaultValue="@string/pref_size_default"

    android:key="@string/pref_size_key"

android:title="@string/pref_size_label" />

 

二:在主窗体中,应该有一个专门读取所有设定的函数,在里面加上读取本参数的代码。

loadSizeFromSharedPreferences(sharedPreferences);

 

private void loadSizeFromSharedPreferences(SharedPreferences sharedPreferences) {

    float minSize = Float.parseFloat(sharedPreferences.getString(“size”), “1.0” ));

    。。。

}

三: 在onSharedPreferenceChanged事件中,对该项设定的改变也做出处理。

if (key.equals(getString(R.string.pref_size_key))) {

float minSize = Float.parseFloat(sharedPreferences.getString(“size”), “1.0” ));

。。。

}

四: 修改setPreferenceSummary函数,让它支持文本类型的偏好。

if (preference instanceof EditTextPreference) {

preference.setSummary(value);

这时会有一个问题,就是输入的内容不是数值时,数据类型转换会引发程序崩溃。

检查偏好设置是否合法

一:在类SettingsFragment中,实现接口Preference.OnPreferenceChangeListener

二: 在onCreatePreferences,把该事件附件到该设定项上

        Preference preference = findPreference(getString(R.string.pref_size_key));

        preference.setOnPreferenceChangeListener(this);

三:实现该接口函数,注意返回值,如果值不合法,返回false

public boolean onPreferenceChange(Preference preference, Object newValue) {

Toast error = Toast.makeText(getContext(), "Please select a number between 0.1 and 3", Toast.LENGTH_SHORT);

 

String sizeKey = getString(R.string.pref_size_key);

if (preference.getKey().equals(sizeKey)) {

    String stringSize = (String) newValue;

    try {

        float size = Float.parseFloat(stringSize);

        if (size > 3 || size <= 0) {

            error.show();

            return false;

        }

    } catch (NumberFormatException nfe) {

        error.show();

        return false;

    }

}

return true;

}

 

原文地址:https://www.cnblogs.com/CipherLab/p/14434118.html