mobile/android/base/background/preferences/PreferenceFragment.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /*
michael@0 2 * Copyright (C) 2013 The Android Open Source Project
michael@0 3 *
michael@0 4 * Licensed under the Apache License, Version 2.0 (the "License");
michael@0 5 * you may not use this file except in compliance with the License.
michael@0 6 * You may obtain a copy of the License at
michael@0 7 *
michael@0 8 * http://www.apache.org/licenses/LICENSE-2.0
michael@0 9 *
michael@0 10 * Unless required by applicable law or agreed to in writing, software
michael@0 11 * distributed under the License is distributed on an "AS IS" BASIS,
michael@0 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
michael@0 13 * See the License for the specific language governing permissions and
michael@0 14 * limitations under the License.
michael@0 15 */
michael@0 16
michael@0 17 package org.mozilla.gecko.background.preferences;
michael@0 18
michael@0 19 import org.mozilla.gecko.R;
michael@0 20
michael@0 21 import android.content.Intent;
michael@0 22 import android.os.Bundle;
michael@0 23 import android.os.Handler;
michael@0 24 import android.os.Message;
michael@0 25 import android.preference.Preference;
michael@0 26 import android.preference.PreferenceGroup;
michael@0 27 import android.preference.PreferenceManager;
michael@0 28 import android.preference.PreferenceScreen;
michael@0 29 import android.support.v4.app.Fragment;
michael@0 30 import android.view.KeyEvent;
michael@0 31 import android.view.LayoutInflater;
michael@0 32 import android.view.View;
michael@0 33 import android.view.View.OnKeyListener;
michael@0 34 import android.view.ViewGroup;
michael@0 35 import android.widget.ListView;
michael@0 36
michael@0 37 public abstract class PreferenceFragment extends Fragment implements PreferenceManagerCompat.OnPreferenceTreeClickListener {
michael@0 38 private static final String PREFERENCES_TAG = "android:preferences";
michael@0 39
michael@0 40 private PreferenceManager mPreferenceManager;
michael@0 41 private ListView mList;
michael@0 42 private boolean mHavePrefs;
michael@0 43 private boolean mInitDone;
michael@0 44
michael@0 45 /**
michael@0 46 * The starting request code given out to preference framework.
michael@0 47 */
michael@0 48 private static final int FIRST_REQUEST_CODE = 100;
michael@0 49
michael@0 50 private static final int MSG_BIND_PREFERENCES = 1;
michael@0 51
michael@0 52 // This triggers "This Handler class should be static or leaks might occur".
michael@0 53 // The issue is that the Handler references the Fragment; messages targeting
michael@0 54 // the Handler reference it; and if such messages are long lived, the Fragment
michael@0 55 // cannot be GCed. This is not an issue for us; our messages are short-lived.
michael@0 56 private Handler mHandler = new Handler() {
michael@0 57 @Override
michael@0 58 public void handleMessage(Message msg) {
michael@0 59 switch (msg.what) {
michael@0 60
michael@0 61 case MSG_BIND_PREFERENCES:
michael@0 62 bindPreferences();
michael@0 63 break;
michael@0 64 }
michael@0 65 }
michael@0 66 };
michael@0 67
michael@0 68 final private Runnable mRequestFocus = new Runnable() {
michael@0 69 @Override
michael@0 70 public void run() {
michael@0 71 mList.focusableViewAvailable(mList);
michael@0 72 }
michael@0 73 };
michael@0 74
michael@0 75 /**
michael@0 76 * Interface that PreferenceFragment's containing activity should
michael@0 77 * implement to be able to process preference items that wish to
michael@0 78 * switch to a new fragment.
michael@0 79 */
michael@0 80 public interface OnPreferenceStartFragmentCallback {
michael@0 81 /**
michael@0 82 * Called when the user has clicked on a Preference that has
michael@0 83 * a fragment class name associated with it. The implementation
michael@0 84 * to should instantiate and switch to an instance of the given
michael@0 85 * fragment.
michael@0 86 */
michael@0 87 boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref);
michael@0 88 }
michael@0 89
michael@0 90 @Override
michael@0 91 public void onCreate(Bundle paramBundle) {
michael@0 92 super.onCreate(paramBundle);
michael@0 93 mPreferenceManager = PreferenceManagerCompat.newInstance(getActivity(), FIRST_REQUEST_CODE);
michael@0 94 PreferenceManagerCompat.setFragment(mPreferenceManager, this);
michael@0 95 }
michael@0 96
michael@0 97 @Override
michael@0 98 public View onCreateView(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup, Bundle paramBundle) {
michael@0 99 return paramLayoutInflater.inflate(R.layout.fxaccount_preference_list_fragment, paramViewGroup,
michael@0 100 false);
michael@0 101 }
michael@0 102
michael@0 103 @Override
michael@0 104 public void onActivityCreated(Bundle savedInstanceState) {
michael@0 105 super.onActivityCreated(savedInstanceState);
michael@0 106
michael@0 107 if (mHavePrefs) {
michael@0 108 bindPreferences();
michael@0 109 }
michael@0 110
michael@0 111 mInitDone = true;
michael@0 112
michael@0 113 if (savedInstanceState != null) {
michael@0 114 Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG);
michael@0 115 if (container != null) {
michael@0 116 final PreferenceScreen preferenceScreen = getPreferenceScreen();
michael@0 117 if (preferenceScreen != null) {
michael@0 118 preferenceScreen.restoreHierarchyState(container);
michael@0 119 }
michael@0 120 }
michael@0 121 }
michael@0 122 }
michael@0 123
michael@0 124 @Override
michael@0 125 public void onStart() {
michael@0 126 super.onStart();
michael@0 127 PreferenceManagerCompat.setOnPreferenceTreeClickListener(mPreferenceManager, this);
michael@0 128 }
michael@0 129
michael@0 130 @Override
michael@0 131 public void onStop() {
michael@0 132 super.onStop();
michael@0 133 PreferenceManagerCompat.dispatchActivityStop(mPreferenceManager);
michael@0 134 PreferenceManagerCompat.setOnPreferenceTreeClickListener(mPreferenceManager, null);
michael@0 135 }
michael@0 136
michael@0 137 @Override
michael@0 138 public void onDestroyView() {
michael@0 139 mList = null;
michael@0 140 mHandler.removeCallbacks(mRequestFocus);
michael@0 141 mHandler.removeMessages(MSG_BIND_PREFERENCES);
michael@0 142 super.onDestroyView();
michael@0 143 }
michael@0 144
michael@0 145 @Override
michael@0 146 public void onDestroy() {
michael@0 147 super.onDestroy();
michael@0 148 PreferenceManagerCompat.dispatchActivityDestroy(mPreferenceManager);
michael@0 149 }
michael@0 150
michael@0 151 @Override
michael@0 152 public void onSaveInstanceState(Bundle outState) {
michael@0 153 super.onSaveInstanceState(outState);
michael@0 154
michael@0 155 final PreferenceScreen preferenceScreen = getPreferenceScreen();
michael@0 156 if (preferenceScreen != null) {
michael@0 157 Bundle container = new Bundle();
michael@0 158 preferenceScreen.saveHierarchyState(container);
michael@0 159 outState.putBundle(PREFERENCES_TAG, container);
michael@0 160 }
michael@0 161 }
michael@0 162
michael@0 163 @Override
michael@0 164 public void onActivityResult(int requestCode, int resultCode, Intent data) {
michael@0 165 super.onActivityResult(requestCode, resultCode, data);
michael@0 166
michael@0 167 PreferenceManagerCompat.dispatchActivityResult(mPreferenceManager, requestCode, resultCode, data);
michael@0 168 }
michael@0 169
michael@0 170 /**
michael@0 171 * Returns the {@link PreferenceManager} used by this fragment.
michael@0 172 * @return The {@link PreferenceManager}.
michael@0 173 */
michael@0 174 public PreferenceManager getPreferenceManager() {
michael@0 175 return mPreferenceManager;
michael@0 176 }
michael@0 177
michael@0 178 /**
michael@0 179 * Sets the root of the preference hierarchy that this fragment is showing.
michael@0 180 *
michael@0 181 * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
michael@0 182 */
michael@0 183 public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
michael@0 184 if (PreferenceManagerCompat.setPreferences(mPreferenceManager, preferenceScreen) && preferenceScreen != null) {
michael@0 185 mHavePrefs = true;
michael@0 186 if (mInitDone) {
michael@0 187 postBindPreferences();
michael@0 188 }
michael@0 189 }
michael@0 190 }
michael@0 191
michael@0 192 /**
michael@0 193 * Gets the root of the preference hierarchy that this fragment is showing.
michael@0 194 *
michael@0 195 * @return The {@link PreferenceScreen} that is the root of the preference
michael@0 196 * hierarchy.
michael@0 197 */
michael@0 198 public PreferenceScreen getPreferenceScreen() {
michael@0 199 return PreferenceManagerCompat.getPreferenceScreen(mPreferenceManager);
michael@0 200 }
michael@0 201
michael@0 202 /**
michael@0 203 * Adds preferences from activities that match the given {@link Intent}.
michael@0 204 *
michael@0 205 * @param intent The {@link Intent} to query activities.
michael@0 206 */
michael@0 207 public void addPreferencesFromIntent(Intent intent) {
michael@0 208 requirePreferenceManager();
michael@0 209
michael@0 210 setPreferenceScreen(PreferenceManagerCompat.inflateFromIntent(mPreferenceManager, intent, getPreferenceScreen()));
michael@0 211 }
michael@0 212
michael@0 213 /**
michael@0 214 * Inflates the given XML resource and adds the preference hierarchy to the current
michael@0 215 * preference hierarchy.
michael@0 216 *
michael@0 217 * @param preferencesResId The XML resource ID to inflate.
michael@0 218 */
michael@0 219 public void addPreferencesFromResource(int preferencesResId) {
michael@0 220 requirePreferenceManager();
michael@0 221
michael@0 222 setPreferenceScreen(PreferenceManagerCompat.inflateFromResource(mPreferenceManager, getActivity(),
michael@0 223 preferencesResId, getPreferenceScreen()));
michael@0 224 }
michael@0 225
michael@0 226 /**
michael@0 227 * {@inheritDoc}
michael@0 228 */
michael@0 229 @Override
michael@0 230 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
michael@0 231 Preference preference) {
michael@0 232 //if (preference.getFragment() != null &&
michael@0 233 if (
michael@0 234 getActivity() instanceof OnPreferenceStartFragmentCallback) {
michael@0 235 return ((OnPreferenceStartFragmentCallback)getActivity()).onPreferenceStartFragment(
michael@0 236 this, preference);
michael@0 237 }
michael@0 238 return false;
michael@0 239 }
michael@0 240
michael@0 241 /**
michael@0 242 * Finds a {@link Preference} based on its key.
michael@0 243 *
michael@0 244 * @param key The key of the preference to retrieve.
michael@0 245 * @return The {@link Preference} with the key, or null.
michael@0 246 * @see PreferenceGroup#findPreference(CharSequence)
michael@0 247 */
michael@0 248 public Preference findPreference(CharSequence key) {
michael@0 249 if (mPreferenceManager == null) {
michael@0 250 return null;
michael@0 251 }
michael@0 252 return mPreferenceManager.findPreference(key);
michael@0 253 }
michael@0 254
michael@0 255 private void requirePreferenceManager() {
michael@0 256 if (mPreferenceManager == null) {
michael@0 257 throw new RuntimeException("This should be called after super.onCreate.");
michael@0 258 }
michael@0 259 }
michael@0 260
michael@0 261 private void postBindPreferences() {
michael@0 262 if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return;
michael@0 263 mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
michael@0 264 }
michael@0 265
michael@0 266 private void bindPreferences() {
michael@0 267 final PreferenceScreen preferenceScreen = getPreferenceScreen();
michael@0 268 if (preferenceScreen != null) {
michael@0 269 preferenceScreen.bind(getListView());
michael@0 270 }
michael@0 271 }
michael@0 272
michael@0 273 public ListView getListView() {
michael@0 274 ensureList();
michael@0 275 return mList;
michael@0 276 }
michael@0 277
michael@0 278 private void ensureList() {
michael@0 279 if (mList != null) {
michael@0 280 return;
michael@0 281 }
michael@0 282 View root = getView();
michael@0 283 if (root == null) {
michael@0 284 throw new IllegalStateException("Content view not yet created");
michael@0 285 }
michael@0 286 View rawListView = root.findViewById(android.R.id.list);
michael@0 287 if (!(rawListView instanceof ListView)) {
michael@0 288 throw new RuntimeException(
michael@0 289 "Content has view with id attribute 'android.R.id.list' "
michael@0 290 + "that is not a ListView class");
michael@0 291 }
michael@0 292 mList = (ListView)rawListView;
michael@0 293 if (mList == null) {
michael@0 294 throw new RuntimeException(
michael@0 295 "Your content must have a ListView whose id attribute is " +
michael@0 296 "'android.R.id.list'");
michael@0 297 }
michael@0 298 mList.setOnKeyListener(mListOnKeyListener);
michael@0 299 mHandler.post(mRequestFocus);
michael@0 300 }
michael@0 301
michael@0 302 private OnKeyListener mListOnKeyListener = new OnKeyListener() {
michael@0 303
michael@0 304 @Override
michael@0 305 public boolean onKey(View v, int keyCode, KeyEvent event) {
michael@0 306 Object selectedItem = mList.getSelectedItem();
michael@0 307 if (selectedItem instanceof Preference) {
michael@0 308 @SuppressWarnings("unused")
michael@0 309 View selectedView = mList.getSelectedView();
michael@0 310 //return ((Preference)selectedItem).onKey(
michael@0 311 // selectedView, keyCode, event);
michael@0 312 return false;
michael@0 313 }
michael@0 314 return false;
michael@0 315 }
michael@0 316
michael@0 317 };
michael@0 318 }

mercurial