SettingsPreferenceFragment.java revision f58090d5224fa03e8f4d8a980306952686a152f0
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.settings;
18
19import android.app.Activity;
20import android.app.Dialog;
21import android.app.DialogFragment;
22import android.content.ContentResolver;
23import android.content.Intent;
24import android.content.pm.PackageManager;
25import android.content.res.Resources;
26import android.os.Bundle;
27import android.preference.PreferenceActivity;
28import android.preference.PreferenceFragment;
29import android.text.TextUtils;
30import android.util.Log;
31import android.view.View;
32import android.view.View.OnClickListener;
33import android.widget.Button;
34
35/**
36 * Letting the class, assumed to be Fragment, create a Dialog on it. Should be useful
37 * you want to utilize some capability in {@link SettingsPreferenceFragment} but don't want
38 * the class inherit the class itself (See {@link ProxySelector} for example).
39 */
40interface DialogCreatable {
41    public Dialog onCreateDialog(int dialogId);
42}
43
44/**
45 * Base class for Settings fragments, with some helper functions and dialog management.
46 */
47public class SettingsPreferenceFragment extends PreferenceFragment
48        implements DialogCreatable {
49
50    private static final String TAG = "SettingsPreferenceFragment";
51
52    // Originally from PreferenceActivity.
53    private static final String EXTRA_PREFS_SHOW_BUTTON_BAR = "extra_prefs_show_button_bar";
54    private static final String EXTRA_PREFS_SHOW_SKIP = "extra_prefs_show_skip";
55    private static final String EXTRA_PREFS_SET_NEXT_TEXT = "extra_prefs_set_next_text";
56    private static final String EXTRA_PREFS_SET_BACK_TEXT = "extra_prefs_set_back_text";
57
58    private SettingsDialogFragment mDialogFragment;
59
60    private OnStateListener mOnStateListener;
61
62    private Button mNextButton;
63
64    private boolean mReportedCreation;
65
66    interface OnStateListener {
67
68        void onCreated(SettingsPreferenceFragment fragment);
69
70        void onDestroyed(SettingsPreferenceFragment fragment);
71    }
72
73    public void setOnStateListener(OnStateListener listener) {
74        mOnStateListener = listener;
75    }
76
77    @Override
78    public void onActivityCreated(Bundle savedInstanceState) {
79        super.onActivityCreated(savedInstanceState);
80        if (mOnStateListener != null && !mReportedCreation) {
81            mOnStateListener.onCreated(this);
82            // So that we don't report it on the way back to this fragment
83            mReportedCreation = true;
84        }
85
86        setupButtonBar();
87    }
88
89    @Override
90    public void onDestroy() {
91        super.onDestroy();
92        if (mOnStateListener != null) {
93            mOnStateListener.onDestroyed(this);
94        }
95    }
96
97    // Some helpers for functions used by the settings fragments when they were activities
98
99    /**
100     * Returns the ContentResolver from the owning Activity.
101     */
102    protected ContentResolver getContentResolver() {
103        return getActivity().getContentResolver();
104    }
105
106    /**
107     * Returns the specified system service from the owning Activity.
108     */
109    protected Object getSystemService(final String name) {
110        return getActivity().getSystemService(name);
111    }
112
113    /**
114     * Returns the Resources from the owning Activity.
115     */
116    protected Resources getResources() {
117        return getActivity().getResources();
118    }
119
120    /**
121     * Returns the PackageManager from the owning Activity.
122     */
123    protected PackageManager getPackageManager() {
124        return getActivity().getPackageManager();
125    }
126
127    // Dialog management
128
129    protected void showDialog(int dialogId) {
130        if (mDialogFragment != null) {
131            Log.e(TAG, "Old dialog fragment not null!");
132        }
133        mDialogFragment = new SettingsDialogFragment(this, dialogId);
134        mDialogFragment.show(getActivity().getFragmentManager(), Integer.toString(dialogId));
135    }
136
137    @Override
138    public Dialog onCreateDialog(int dialogId) {
139        return null;
140    }
141
142    protected void removeDialog(int dialogId) {
143        if (mDialogFragment != null && mDialogFragment.getDialogId() == dialogId
144                && mDialogFragment.isVisible()) {
145            mDialogFragment.dismiss();
146        }
147        mDialogFragment = null;
148    }
149
150    static class SettingsDialogFragment extends DialogFragment {
151        private int mDialogId;
152
153        private DialogCreatable mFragment;
154
155        SettingsDialogFragment(DialogCreatable fragment, int dialogId) {
156            mDialogId = dialogId;
157            mFragment = fragment;
158        }
159
160        @Override
161        public Dialog onCreateDialog(Bundle savedInstanceState) {
162            return mFragment.onCreateDialog(mDialogId);
163        }
164
165        public int getDialogId() {
166            return mDialogId;
167        }
168    }
169
170    protected boolean hasNextButton() {
171        return mNextButton != null;
172    }
173
174    protected Button getNextButton() {
175        return mNextButton;
176    }
177
178    /**
179     * Sets up Button Bar possibly required in the Fragment. Probably available only in
180     * phones.
181     *
182     * Previously {@link PreferenceActivity} had the capability as hidden functionality.
183     */
184    private void setupButtonBar() {
185        // Originally from PreferenceActivity, which has had button bar inside its layout.
186        final Activity activity = getActivity();
187        final Intent intent = activity.getIntent();
188        final View buttonBar = activity.findViewById(com.android.internal.R.id.button_bar);
189        if (!intent.getBooleanExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false) || buttonBar == null) {
190            return;
191        }
192
193        buttonBar.setVisibility(View.VISIBLE);
194        View tmpView = activity.findViewById(com.android.internal.R.id.back_button);
195        if (tmpView != null) {
196            // TODO: Assume this is pressed only in single pane, finishing current Activity.
197            try {
198                final Button backButton = (Button)tmpView;
199                backButton.setOnClickListener(new OnClickListener() {
200                    public void onClick(View v) {
201                        activity.setResult(Activity.RESULT_CANCELED);
202                        activity.finish();
203                    }
204                });
205                if (intent.hasExtra(EXTRA_PREFS_SET_BACK_TEXT)) {
206                    String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_BACK_TEXT);
207                    if (TextUtils.isEmpty(buttonText)) {
208                        backButton.setVisibility(View.GONE);
209                    }
210                    else {
211                        backButton.setText(buttonText);
212                    }
213                }
214            } catch (ClassCastException e) {
215                Log.w(TAG, "The view originally for back_button is used not as Button. " +
216                        "Ignored.");
217            }
218        }
219
220        tmpView = activity.findViewById(com.android.internal.R.id.skip_button);
221        if (tmpView != null) {
222            try {
223                final Button skipButton = (Button)tmpView;
224                skipButton.setOnClickListener(new OnClickListener() {
225                    public void onClick(View v) {
226                        activity.setResult(Activity.RESULT_OK);
227                        activity.finish();
228                    }
229                });
230                if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_SKIP, false)) {
231                    skipButton.setVisibility(View.VISIBLE);
232                }
233            } catch (ClassCastException e) {
234                Log.w(TAG, "The view originally for skip_button is used not as Button. " +
235                        "Ignored.");
236            }
237        }
238
239        tmpView = activity.findViewById(com.android.internal.R.id.next_button);
240        if (tmpView != null) {
241            try {
242                mNextButton = (Button)tmpView;
243                mNextButton.setOnClickListener(new OnClickListener() {
244                    public void onClick(View v) {
245                        activity.setResult(Activity.RESULT_OK);
246                        activity.finish();
247                    }
248                });
249                // set our various button parameters
250                if (intent.hasExtra(EXTRA_PREFS_SET_NEXT_TEXT)) {
251                    String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_NEXT_TEXT);
252                    if (TextUtils.isEmpty(buttonText)) {
253                        mNextButton.setVisibility(View.GONE);
254                    }
255                    else {
256                        mNextButton.setText(buttonText);
257                    }
258                }
259            } catch (ClassCastException e) {
260                Log.w(TAG, "The view originally for next_button is used not as Button. " +
261                        "Ignored.");
262                mNextButton = null;
263            }
264        }
265    }
266}
267