• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1package ${packageName};
2
3import android.annotation.TargetApi;
4import android.content.Context;
5import android.content.res.Configuration;
6import android.media.Ringtone;
7import android.media.RingtoneManager;
8import android.net.Uri;
9import android.os.Build;
10import android.os.Bundle;
11import android.preference.ListPreference;
12import android.preference.Preference;
13import android.preference.PreferenceActivity;
14import android.preference.PreferenceCategory;
15import android.preference.PreferenceFragment;
16import android.preference.PreferenceManager;
17import android.preference.RingtonePreference;
18import android.text.TextUtils;
19<#if parentActivityClass != "">
20import android.view.MenuItem;
21import android.support.v4.app.NavUtils;
22</#if>
23
24import java.util.List;
25
26/**
27 * A {@link PreferenceActivity} that presents a set of application settings. On
28 * handset devices, settings are presented as a single list. On tablets,
29 * settings are split by category, with category headers shown to the left of
30 * the list of settings.
31 * <p>
32 * See <a href="http://developer.android.com/design/patterns/settings.html">
33 * Android Design: Settings</a> for design guidelines and the <a
34 * href="http://developer.android.com/guide/topics/ui/settings.html">Settings
35 * API Guide</a> for more information on developing a Settings UI.
36 */
37public class ${activityClass} extends PreferenceActivity {
38    /**
39     * Determines whether to always show the simplified settings UI, where
40     * settings are presented in a single list. When false, settings are shown
41     * as a master/detail two-pane view on tablets. When true, a single pane is
42     * shown on tablets.
43     */
44    private static final boolean ALWAYS_SIMPLE_PREFS = false;
45
46    <#if parentActivityClass != "">
47    @Override
48    protected void onCreate(Bundle savedInstanceState) {
49        super.onCreate(savedInstanceState);
50        setupActionBar();
51    }
52
53    /**
54     * Set up the {@link android.app.ActionBar}, if the API is available.
55     */
56    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
57    private void setupActionBar() {
58        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
59            // Show the Up button in the action bar.
60            getActionBar().setDisplayHomeAsUpEnabled(true);
61        }
62    }
63
64    @Override
65    public boolean onOptionsItemSelected(MenuItem item) {
66        switch (item.getItemId()) {
67            case android.R.id.home:
68                // This ID represents the Home or Up button. In the case of this
69                // activity, the Up button is shown. Use NavUtils to allow users
70                // to navigate up one level in the application structure. For
71                // more details, see the Navigation pattern on Android Design:
72                //
73                // http://developer.android.com/design/patterns/navigation.html#up-vs-back
74                //
75                // TODO: If Settings has multiple levels, Up should navigate up
76                // that hierarchy.
77                NavUtils.navigateUpFromSameTask(this);
78                return true;
79        }
80        return super.onOptionsItemSelected(item);
81    }
82    </#if>
83
84    @Override
85    protected void onPostCreate(Bundle savedInstanceState) {
86        super.onPostCreate(savedInstanceState);
87
88        setupSimplePreferencesScreen();
89    }
90
91    /**
92     * Shows the simplified settings UI if the device configuration if the
93     * device configuration dictates that a simplified, single-pane UI should be
94     * shown.
95     */
96    private void setupSimplePreferencesScreen() {
97        if (!isSimplePreferences(this)) {
98            return;
99        }
100
101        // In the simplified UI, fragments are not used at all and we instead
102        // use the older PreferenceActivity APIs.
103
104        // Add 'general' preferences.
105        addPreferencesFromResource(R.xml.pref_general);
106
107        // Add 'notifications' preferences, and a corresponding header.
108        PreferenceCategory fakeHeader = new PreferenceCategory(this);
109        fakeHeader.setTitle(R.string.pref_header_notifications);
110        getPreferenceScreen().addPreference(fakeHeader);
111        addPreferencesFromResource(R.xml.pref_notification);
112
113        // Add 'data and sync' preferences, and a corresponding header.
114        fakeHeader = new PreferenceCategory(this);
115        fakeHeader.setTitle(R.string.pref_header_data_sync);
116        getPreferenceScreen().addPreference(fakeHeader);
117        addPreferencesFromResource(R.xml.pref_data_sync);
118
119        // Bind the summaries of EditText/List/Dialog/Ringtone preferences to
120        // their values. When their values change, their summaries are updated
121        // to reflect the new value, per the Android Design guidelines.
122        bindPreferenceSummaryToValue(findPreference("example_text"));
123        bindPreferenceSummaryToValue(findPreference("example_list"));
124        bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"));
125        bindPreferenceSummaryToValue(findPreference("sync_frequency"));
126    }
127
128    /** {@inheritDoc} */
129    @Override
130    public boolean onIsMultiPane() {
131        return isXLargeTablet(this) && !isSimplePreferences(this);
132    }
133
134    /**
135     * Helper method to determine if the device has an extra-large screen. For
136     * example, 10" tablets are extra-large.
137     */
138    private static boolean isXLargeTablet(Context context) {
139        return (context.getResources().getConfiguration().screenLayout
140        & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
141    }
142
143    /**
144     * Determines whether the simplified settings UI should be shown. This is
145     * true if this is forced via {@link #ALWAYS_SIMPLE_PREFS}, or the device
146     * doesn't have newer APIs like {@link PreferenceFragment}, or the device
147     * doesn't have an extra-large screen. In these cases, a single-pane
148     * "simplified" settings UI should be shown.
149     */
150    private static boolean isSimplePreferences(Context context) {
151        return ALWAYS_SIMPLE_PREFS
152                || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB
153                || !isXLargeTablet(context);
154    }
155
156    /** {@inheritDoc} */
157    @Override
158    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
159    public void onBuildHeaders(List<Header> target) {
160        if (!isSimplePreferences(this)) {
161            loadHeadersFromResource(R.xml.pref_headers, target);
162        }
163    }
164
165    /**
166     * A preference value change listener that updates the preference's summary
167     * to reflect its new value.
168     */
169    private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
170        @Override
171        public boolean onPreferenceChange(Preference preference, Object value) {
172            String stringValue = value.toString();
173
174            if (preference instanceof ListPreference) {
175                // For list preferences, look up the correct display value in
176                // the preference's 'entries' list.
177                ListPreference listPreference = (ListPreference) preference;
178                int index = listPreference.findIndexOfValue(stringValue);
179
180                // Set the summary to reflect the new value.
181                preference.setSummary(
182                        index >= 0
183                                ? listPreference.getEntries()[index]
184                                : null);
185
186            } else if (preference instanceof RingtonePreference) {
187                // For ringtone preferences, look up the correct display value
188                // using RingtoneManager.
189                if (TextUtils.isEmpty(stringValue)) {
190                    // Empty values correspond to 'silent' (no ringtone).
191                    preference.setSummary(R.string.pref_ringtone_silent);
192
193                } else {
194                    Ringtone ringtone = RingtoneManager.getRingtone(
195                            preference.getContext(), Uri.parse(stringValue));
196
197                    if (ringtone == null) {
198                        // Clear the summary if there was a lookup error.
199                        preference.setSummary(null);
200                    } else {
201                        // Set the summary to reflect the new ringtone display
202                        // name.
203                        String name = ringtone.getTitle(preference.getContext());
204                        preference.setSummary(name);
205                    }
206                }
207
208            } else {
209                // For all other preferences, set the summary to the value's
210                // simple string representation.
211                preference.setSummary(stringValue);
212            }
213            return true;
214        }
215    };
216
217    /**
218     * Binds a preference's summary to its value. More specifically, when the
219     * preference's value is changed, its summary (line of text below the
220     * preference title) is updated to reflect the value. The summary is also
221     * immediately updated upon calling this method. The exact display format is
222     * dependent on the type of preference.
223     *
224     * @see #sBindPreferenceSummaryToValueListener
225     */
226    private static void bindPreferenceSummaryToValue(Preference preference) {
227        // Set the listener to watch for value changes.
228        preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
229
230        // Trigger the listener immediately with the preference's
231        // current value.
232        sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
233                PreferenceManager
234                        .getDefaultSharedPreferences(preference.getContext())
235                        .getString(preference.getKey(), ""));
236    }
237
238    /**
239     * This fragment shows general preferences only. It is used when the
240     * activity is showing a two-pane settings UI.
241     */
242    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
243    public static class GeneralPreferenceFragment extends PreferenceFragment {
244        @Override
245        public void onCreate(Bundle savedInstanceState) {
246            super.onCreate(savedInstanceState);
247            addPreferencesFromResource(R.xml.pref_general);
248
249            // Bind the summaries of EditText/List/Dialog/Ringtone preferences
250            // to their values. When their values change, their summaries are
251            // updated to reflect the new value, per the Android Design
252            // guidelines.
253            bindPreferenceSummaryToValue(findPreference("example_text"));
254            bindPreferenceSummaryToValue(findPreference("example_list"));
255        }
256    }
257
258    /**
259     * This fragment shows notification preferences only. It is used when the
260     * activity is showing a two-pane settings UI.
261     */
262    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
263    public static class NotificationPreferenceFragment extends PreferenceFragment {
264        @Override
265        public void onCreate(Bundle savedInstanceState) {
266            super.onCreate(savedInstanceState);
267            addPreferencesFromResource(R.xml.pref_notification);
268
269            // Bind the summaries of EditText/List/Dialog/Ringtone preferences
270            // to their values. When their values change, their summaries are
271            // updated to reflect the new value, per the Android Design
272            // guidelines.
273            bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"));
274        }
275    }
276
277    /**
278     * This fragment shows data and sync preferences only. It is used when the
279     * activity is showing a two-pane settings UI.
280     */
281    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
282    public static class DataSyncPreferenceFragment extends PreferenceFragment {
283        @Override
284        public void onCreate(Bundle savedInstanceState) {
285            super.onCreate(savedInstanceState);
286            addPreferencesFromResource(R.xml.pref_data_sync);
287
288            // Bind the summaries of EditText/List/Dialog/Ringtone preferences
289            // to their values. When their values change, their summaries are
290            // updated to reflect the new value, per the Android Design
291            // guidelines.
292            bindPreferenceSummaryToValue(findPreference("sync_frequency"));
293        }
294    }
295}
296