如何在Android上创建首选项活动和首选项片段?

Wan*_*igh 40 android android-preferences android-xml android-fragments android-activity

当我关注一个旧教程(Créezdesapplications pour Android - > openclassroom)时,我addPreferencesFromResource(int id)从PreferenceActivity类中坚持使用这个弃用的方法.

所以我的问题是:

在Android中创建首选项的新方法是什么?

Wan*_*igh 101

我发现这篇文章(在PreferenceActivity中使用什么而不是"addPreferencesFromResource"?),这有助于我理解你必须通过a PreferenceFragment才能做到这一点.

在下面的解释中,我your.package.用来表明你必须放入包名.每个人都有自己的包装,所以请用你的包装代替.

让我们开始 :


1.偏好片段

  • 创建PreferenceFragment类

    MyPreferenceFragment

    public class MyPreferenceFragment extends PreferenceFragment
    {
        @Override
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.fragment_preference);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)


  • 然后是关联的xml资源

    fragment_preference.xml(在项目的res/xml文件夹中)

    <?xml version="1.0" encoding="utf-8"?>
    
    <PreferenceScreen
        xmlns:android="http://schemas.android.com/apk/res/android">
    
        <PreferenceCategory 
            android:title="FOO">
    
            <CheckBoxPreference
                android:key="checkBoxPref"
                android:title="check it out"
                android:summary="click this little box"/>
    
        </PreferenceCategory>
    
    </PreferenceScreen>
    
    Run Code Online (Sandbox Code Playgroud)

    这就是全部Fragment.



2.偏好活动

  • 创建PreferenceActivity类

    MyPreferenceActivity

    public class MyPreferenceActivity extends PreferenceActivity
    {
        @Override
        public void onBuildHeaders(List<Header> target)
        {
            loadHeadersFromResource(R.xml.headers_preference, target);
        }
    
        @Override
        protected boolean isValidFragment(String fragmentName)
        {
            return MyPreferenceFragment.class.getName().equals(fragmentName);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    不要忘记覆盖isValidFragment(String fragmentName)方法,因为您的应用程序将面对您的打孔!;)更严重的是我不知道为什么你需要这样做但是需要它.如果有人对此有解释,我很乐意阅读:)

    编辑:


    感谢kirtan403我现在知道为什么需要它:它必须设置因为(android框架片段注入).


    正如您所看到的,onBuildHeaders(List<Header> target)我们加载了另一个包含首选项标头的xml文件.简而言之,标题是首选项的左侧部分,而片段是正确的部分(对于平板电脑).对于手机,您将首先拥有标题,当您点击某个项目时,相应的片段将被放在标题列表的顶部.

    阅读本文(带有片段的Android中的多窗格开发 - 教程)图像自己解释.


  • 然后是关联的xml资源

    headers_preference.xml(在项目的res/xml文件夹中)

    <?xml version="1.0" encoding="utf-8"?>
    
    <preference-headers
        xmlns:android="http://schemas.android.com/apk/res/android">
    
        <header 
            android:fragment="your.package.MyPreferenceFragment"
            android:title="Goto: Preference fragment"
            android:summary="An example of some preferences." />
    
    </preference-headers>
    
    Run Code Online (Sandbox Code Playgroud)

    您可能已经在标题部分注意到了:

    android:fragment="your.package.MyPreferenceFragment"

    这将作为您要显示的片段的链接.在平板电脑上,它将加载在右侧部分和手机上,它将加载到当前视图的顶部.



3. Android Manifest

现在您应该做的是将您的活动添加到AndroidManifest.xml文件中.

在该application部分内添加以下行:

<activity
    android:name="your.package.MyPreferenceActivity"
    android:label="Preferences">
</activity>
Run Code Online (Sandbox Code Playgroud)

你可能会告诉我:

"哦,亲爱的,你忘了把android:launchMode ="singleTask"放在你的行动中"

但请不要这样做,因为你永远不会在手机上加载你的片段.这个错误是由一个伟人解决的!这是他博客的链接(小屏幕/手机上的Android标题首选项).



4.从菜单中启动首选项

最后你需要添加显示此偏好的功能!! 要做到这一点,你需要3件事:

  • 菜单

    menu.xml(在项目的文件夹res/menu中)

    <?xml version="1.0" encoding="utf-8"?>
    
    <menu 
        xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item 
            android:id="@+id/preferences"
            android:title="Preferences" />
    
    </menu>
    
    Run Code Online (Sandbox Code Playgroud)


  • 在此方法下的主活动(而不是PreferenceActivity)中加载此菜单 onCreateOptionsMenu(Menu menu)

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return true;
    }
    
    Run Code Online (Sandbox Code Playgroud)


  • MyPreferenceActivity单击该按钮时启动活动.

    为此,您需要覆盖onOptionsItemSelected(MenuItem item)Main活动中的方法.

    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        switch(item.getItemId())
        {
            case R.id.preferences:
            {
                Intent intent = new Intent();
                intent.setClassName(this, "your.package.MyPreferenceActivity");
                startActivity(intent);
                return true;
            }
        }
    
        return super.onOptionsItemSelected(item);
    }
    
    Run Code Online (Sandbox Code Playgroud)



Et voila les amis!

我还没有测试过这段代码.我把它从我自己的代码中修改了,所以我可能没有很好地复制粘贴的东西.如果你遇到错误告诉我,我会试着找出问题并解决这个问题.

我希望这篇文章可以帮助那些人:D

干杯!

  • @WannaGetHigh你提到了isValidFragment()的用法,为什么使用它.你可以阅读更多相关信息[这里](https://securityintelligence.com/new-vulnerability-android-framework-fragment-injection/).由于漏洞,此方法是在Android 4.4 Kitkat中引入的. (3认同)

Gen*_* Bo 19

我喜欢这篇文章的解决方案:http://alvinalexander.com/android/android-tutorial-preferencescreen-preferenceactivity-preferencefragment

..因为对于那些只需要非常基本且快速运行的人来说,它似乎是最紧凑的.它只有一个.java文件和两个小的xml文件.

活动配置提醒

将3个文件添加到项目后,不要忘记

A)将Prefs活动添加到清单文件
B)添加一些方法来启动Prefs活动..例如,按钮或菜单项

将以下文件添加到项目中.使用它们列出的顺序来避免编译错误.

  1. 添加/res/values/array.xml

    <resources>
        <string-array name="listArray">
            <item>Ace</item>
            <item>Club</item>
        </string-array>
    
        <string-array name="listValues">
            <item>Ace</item>
            <item>Club</item>
        </string-array>
    </resources>
    
    Run Code Online (Sandbox Code Playgroud)
  2. 添加/res/xml/preferences.xml

    <?xml version="1.0" encoding="utf-8"?>
    <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
        <EditTextPreference android:title="Your Name"
                            android:key="username"
                            android:summary="Please provide your username"></EditTextPreference>
        <CheckBoxPreference android:title="Application Updates"
                            android:defaultValue="false"
                            android:summary="This option if selected will allow the application to check for latest versions."
                            android:key="applicationUpdates" />
        <ListPreference     android:title="Download Details"
                            android:summary="Select the kind of data that you would like to download"
                            android:key="downloadType"
                            android:defaultValue="Ace"
                            android:entries="@array/listArray"
                            android:entryValues="@array/listValues" />
    </PreferenceScreen>
    
    Run Code Online (Sandbox Code Playgroud)
  3. 添加活动代码

    public class AppPreferenceActivity extends PreferenceActivity
    {
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            getFragmentManager().beginTransaction().replace(android.R.id.content, new MyPreferenceFragment()).commit();
    
            checkValues();
        }
    
        public static class MyPreferenceFragment extends PreferenceFragment
        {
            @Override
            public void onCreate(final Bundle savedInstanceState)
            {
                super.onCreate(savedInstanceState);
                addPreferencesFromResource(R.xml.preferences);
            }
        }
    
        private void checkValues()
        {
            SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
            String strUserName = sharedPrefs.getString("username", "NA");
            boolean bAppUpdates = sharedPrefs.getBoolean("applicationUpdates",false);
            String downloadType = sharedPrefs.getString("downloadType","1");
    
            String msg = "Cur Values: ";
            msg += "\n userName = " + strUserName;
            msg += "\n bAppUpdates = " + bAppUpdates;
            msg += "\n downloadType = " + downloadType;
    
            Toaster.shortDebug(msg);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)