简体   繁体   English

如何在Android中的“设置”页面中添加工具栏/操作栏?

[英]How do you add a toolbar/action bar to a Settings page in Android?

I'm creating an app that has a settings activity. 我正在创建一个具有设置活动的应用。 The settings activity extends from AppCompatPreferenceActivity which I have imported myself. 设置活动从我自己导入的AppCompatPreferenceActivity扩展而来。 I want a toolbar at the top of the activity for the user to go back. 我希望活动顶部有一个工具栏供用户返回。

I have tried to change the setContentView to an activity with a toolbar but it comes up with the error No view found for id 0x10203a1 (android:id/prefs) for fragment GeneralPreferenceFragment{1fac983 #0 id=0x10203a1} 我试图将setContentView更改为带有工具栏的活动但是它出现错误No view found for id 0x10203a1 (android:id/prefs) for fragment GeneralPreferenceFragment{1fac983 #0 id=0x10203a1}

Here is my current code for settings activity (most of the code is simply from the basic settings activity you get as a template in Android Studio.) 以下是我当前的设置活动代码(大部分代码都来自您在Android Studio中作为模板获得的基本设置活动。)

public class PreferencesActivity extends AppCompatPreferenceActivity implements PreferenceFragment.OnPreferenceStartFragmentCallback{

    /**
     * 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 {
                // For all other preferences, set the summary to the value's
                // simple string representation.
                preference.setSummary(stringValue);
            }
            return true;
        }
    };

    /**
     * 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;
    }

    /**
     * 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(), ""));
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getDelegate().installViewFactory();
        getDelegate().onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setupActionBar();
    }

    private void setupActionBar() {
        ViewGroup rootView = (ViewGroup)findViewById(R.id.action_bar_root); //id from appcompat

        if (rootView != null) {

            Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
            toolbar.setTitleTextColor(Color.WHITE);
            setSupportActionBar(toolbar);
        }

        android.support.v7.app.ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            // Show the Up button in the action bar.
            Log.v(getApplication().getClass().getSimpleName(), "The action bar isn't null");
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setTitle("idk");
//            actionBar.setTitleColor(R.color.white);
            actionBar.setHomeAsUpIndicator(R.drawable.ic_arrow);
        }
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public boolean onIsMultiPane() {
        return isXLargeTablet(this);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public void onBuildHeaders(List<Header> target) {
        loadHeadersFromResource(R.xml.pref_headers, target);
    }

    /**
     * This method stops fragment injection in malicious applications.
     * Make sure to deny any unknown fragments here.
     */
    protected boolean isValidFragment(String fragmentName) {
        return GeneralPreferenceFragment.class.getName().equals(fragmentName)
                || DataSyncPreferenceFragment.class.getName().equals(fragmentName)
                || NotificationPreferenceFragment.class.getName().equals(fragmentName);
    }

    /**
     * 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);
            setHasOptionsMenu(true);

            // 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"));
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            int id = item.getItemId();
            if (id == android.R.id.home) {
                startActivity(new Intent(getActivity(), SettingsActivity.class));
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
    }

    /**
     * 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);
            setHasOptionsMenu(true);

            // 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("notifications_new_message_ringtone"));
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            int id = item.getItemId();
            if (id == android.R.id.home) {
                startActivity(new Intent(getActivity(), SettingsActivity.class));
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
    }

    /**
     * This fragment shows data and sync preferences only. It is used when the
     * activity is showing a two-pane settings UI.
     */
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public static class DataSyncPreferenceFragment extends PreferenceFragment {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.pref_data_sync);
            setHasOptionsMenu(true);

            // 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("sync_frequency"));
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            int id = item.getItemId();
            if (id == android.R.id.home) {
                startActivity(new Intent(getActivity(), SettingsActivity.class));
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
    }


}

here is code of my activity_settings.xml 这是我的activity_settings.xml代码

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/content_frame"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:minHeight="?attr/actionBarSize"
        android:background="?attr/colorPrimary" />

    <LinearLayout
        android:id="@+id/root_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

    </LinearLayout>
</LinearLayout>

The root view is where my content will go and the there on top. 根视图是我的内容将在哪里和顶部。

after a lot of experimenting and trying things out. 经过大量的实验和尝试。 I think that I have worked out how to create a toolbar for a settings page. 我想我已经研究了如何为设置页面创建工具栏。 It was actually much easier than expected and the main way I did it was through different themes. 它实际上比预期容易得多,我做的主要方式是通过不同的主题。 Using this method, saves you the hassle of getting errors such as No view found for android:id/prefs or No list view found (android.R.id.list) 使用此方法,可以省去获取错误的麻烦,例如No view found for android:id/prefsNo list view found (android.R.id.list)

Declaring the themes in styles.xml styles.xml中声明主题

You need to have one theme which is your regular app theme. 您需要有一个主题,这是您的常规应用主题。 It should already be created and customised by you, and one other theme with the Toolbar added to it. 它应该已经由您创建和自定义,并且添加了工具栏的另一个主题。 In my case I wanted to use my own custom toolbar for the other activities but for the SettingsActivity, I wanted a basic toolbar. 在我的情况下,我想将自己的自定义工具栏用于其他活动,但对于SettingsActivity,我想要一个基本的工具栏。

<resources>


    <!-- Base application theme. -->

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <!-- Customised App Theme with the Toolbar-->
    <style name="AppTheme_Toolbar" parent="Theme.AppCompat.Light.DarkActionBar" xmlns:tools="http://schemas.android.com/tools">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>

Suffice to say, the only difference between the two themes were that the one without the Toolbar already there was Theme.AppCompat.Light.NoActionBar and the other was Theme.AppCompat.Light.DarkActionBar 可以说,两个主题之间的唯一区别是没有工具栏的那个已经存在Theme.AppCompat.Light.NoActionBar而另一个是Theme.AppCompat.Light.DarkActionBar

Change the themes of your activity 更改活动的主题

There are two ways to do this. 有两种方法可以做到这一点。 First, is to go to your SettingsActivity.class and in the onCreate method, add this line of code setTheme(R.style.AppTheme_Toolbar); 首先,是去你的SettingsActivity.class并在onCreate方法中添加这行代码setTheme(R.style.AppTheme_Toolbar); Otherwise, go to your AndroidManifest.xml : 否则,请转到AndroidManifest.xml

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity
        android:name=".SettingsActivity"
        android:label="@string/app_name"
        android:theme="@style/AppTheme_Toolbar">
    </activity>

Here my app's theme itself is @style/AppTheme . 这里我的应用程序主题本身是@style/AppTheme But my settings activity page's theme is set to @style/AppTheme_Toolbar 但我的设置活动页面的主题设置为@style/AppTheme_Toolbar

Hope this helps! 希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM