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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mobile/android/base/background/preferences/PreferenceFragment.java	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,318 @@
     1.4 +/*
     1.5 + * Copyright (C) 2013 The Android Open Source Project
     1.6 + *
     1.7 + * Licensed under the Apache License, Version 2.0 (the "License");
     1.8 + * you may not use this file except in compliance with the License.
     1.9 + * You may obtain a copy of the License at
    1.10 + *
    1.11 + *      http://www.apache.org/licenses/LICENSE-2.0
    1.12 + *
    1.13 + * Unless required by applicable law or agreed to in writing, software
    1.14 + * distributed under the License is distributed on an "AS IS" BASIS,
    1.15 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    1.16 + * See the License for the specific language governing permissions and
    1.17 + * limitations under the License.
    1.18 + */
    1.19 +
    1.20 +package org.mozilla.gecko.background.preferences;
    1.21 +
    1.22 +import org.mozilla.gecko.R;
    1.23 +
    1.24 +import android.content.Intent;
    1.25 +import android.os.Bundle;
    1.26 +import android.os.Handler;
    1.27 +import android.os.Message;
    1.28 +import android.preference.Preference;
    1.29 +import android.preference.PreferenceGroup;
    1.30 +import android.preference.PreferenceManager;
    1.31 +import android.preference.PreferenceScreen;
    1.32 +import android.support.v4.app.Fragment;
    1.33 +import android.view.KeyEvent;
    1.34 +import android.view.LayoutInflater;
    1.35 +import android.view.View;
    1.36 +import android.view.View.OnKeyListener;
    1.37 +import android.view.ViewGroup;
    1.38 +import android.widget.ListView;
    1.39 +
    1.40 +public abstract class PreferenceFragment extends Fragment implements PreferenceManagerCompat.OnPreferenceTreeClickListener {
    1.41 +  private static final String PREFERENCES_TAG = "android:preferences";
    1.42 +
    1.43 +  private PreferenceManager mPreferenceManager;
    1.44 +  private ListView mList;
    1.45 +  private boolean mHavePrefs;
    1.46 +  private boolean mInitDone;
    1.47 +
    1.48 +  /**
    1.49 +   * The starting request code given out to preference framework.
    1.50 +   */
    1.51 +  private static final int FIRST_REQUEST_CODE = 100;
    1.52 +
    1.53 +  private static final int MSG_BIND_PREFERENCES = 1;
    1.54 +
    1.55 +  // This triggers "This Handler class should be static or leaks might occur".
    1.56 +  // The issue is that the Handler references the Fragment; messages targeting
    1.57 +  // the Handler reference it; and if such messages are long lived, the Fragment
    1.58 +  // cannot be GCed. This is not an issue for us; our messages are short-lived.
    1.59 +  private Handler mHandler = new Handler() {
    1.60 +    @Override
    1.61 +    public void handleMessage(Message msg) {
    1.62 +      switch (msg.what) {
    1.63 +
    1.64 +      case MSG_BIND_PREFERENCES:
    1.65 +        bindPreferences();
    1.66 +        break;
    1.67 +      }
    1.68 +    }
    1.69 +  };
    1.70 +
    1.71 +  final private Runnable mRequestFocus = new Runnable() {
    1.72 +    @Override
    1.73 +    public void run() {
    1.74 +      mList.focusableViewAvailable(mList);
    1.75 +    }
    1.76 +  };
    1.77 +
    1.78 +  /**
    1.79 +   * Interface that PreferenceFragment's containing activity should
    1.80 +   * implement to be able to process preference items that wish to
    1.81 +   * switch to a new fragment.
    1.82 +   */
    1.83 +  public interface OnPreferenceStartFragmentCallback {
    1.84 +    /**
    1.85 +     * Called when the user has clicked on a Preference that has
    1.86 +     * a fragment class name associated with it.  The implementation
    1.87 +     * to should instantiate and switch to an instance of the given
    1.88 +     * fragment.
    1.89 +     */
    1.90 +    boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref);
    1.91 +  }
    1.92 +
    1.93 +  @Override
    1.94 +  public void onCreate(Bundle paramBundle) {
    1.95 +    super.onCreate(paramBundle);
    1.96 +    mPreferenceManager = PreferenceManagerCompat.newInstance(getActivity(), FIRST_REQUEST_CODE);
    1.97 +    PreferenceManagerCompat.setFragment(mPreferenceManager, this);
    1.98 +  }
    1.99 +
   1.100 +  @Override
   1.101 +  public View onCreateView(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup, Bundle paramBundle) {
   1.102 +    return paramLayoutInflater.inflate(R.layout.fxaccount_preference_list_fragment, paramViewGroup,
   1.103 +        false);
   1.104 +  }
   1.105 +
   1.106 +  @Override
   1.107 +  public void onActivityCreated(Bundle savedInstanceState) {
   1.108 +    super.onActivityCreated(savedInstanceState);
   1.109 +
   1.110 +    if (mHavePrefs) {
   1.111 +      bindPreferences();
   1.112 +    }
   1.113 +
   1.114 +    mInitDone = true;
   1.115 +
   1.116 +    if (savedInstanceState != null) {
   1.117 +      Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG);
   1.118 +      if (container != null) {
   1.119 +        final PreferenceScreen preferenceScreen = getPreferenceScreen();
   1.120 +        if (preferenceScreen != null) {
   1.121 +          preferenceScreen.restoreHierarchyState(container);
   1.122 +        }
   1.123 +      }
   1.124 +    }
   1.125 +  }
   1.126 +
   1.127 +  @Override
   1.128 +  public void onStart() {
   1.129 +    super.onStart();
   1.130 +    PreferenceManagerCompat.setOnPreferenceTreeClickListener(mPreferenceManager, this);
   1.131 +  }
   1.132 +
   1.133 +  @Override
   1.134 +  public void onStop() {
   1.135 +    super.onStop();
   1.136 +    PreferenceManagerCompat.dispatchActivityStop(mPreferenceManager);
   1.137 +    PreferenceManagerCompat.setOnPreferenceTreeClickListener(mPreferenceManager, null);
   1.138 +  }
   1.139 +
   1.140 +  @Override
   1.141 +  public void onDestroyView() {
   1.142 +    mList = null;
   1.143 +    mHandler.removeCallbacks(mRequestFocus);
   1.144 +    mHandler.removeMessages(MSG_BIND_PREFERENCES);
   1.145 +    super.onDestroyView();
   1.146 +  }
   1.147 +
   1.148 +  @Override
   1.149 +  public void onDestroy() {
   1.150 +    super.onDestroy();
   1.151 +    PreferenceManagerCompat.dispatchActivityDestroy(mPreferenceManager);
   1.152 +  }
   1.153 +
   1.154 +  @Override
   1.155 +  public void onSaveInstanceState(Bundle outState) {
   1.156 +    super.onSaveInstanceState(outState);
   1.157 +
   1.158 +    final PreferenceScreen preferenceScreen = getPreferenceScreen();
   1.159 +    if (preferenceScreen != null) {
   1.160 +      Bundle container = new Bundle();
   1.161 +      preferenceScreen.saveHierarchyState(container);
   1.162 +      outState.putBundle(PREFERENCES_TAG, container);
   1.163 +    }
   1.164 +  }
   1.165 +
   1.166 +  @Override
   1.167 +  public void onActivityResult(int requestCode, int resultCode, Intent data) {
   1.168 +    super.onActivityResult(requestCode, resultCode, data);
   1.169 +
   1.170 +    PreferenceManagerCompat.dispatchActivityResult(mPreferenceManager, requestCode, resultCode, data);
   1.171 +  }
   1.172 +
   1.173 +  /**
   1.174 +   * Returns the {@link PreferenceManager} used by this fragment.
   1.175 +   * @return The {@link PreferenceManager}.
   1.176 +   */
   1.177 +  public PreferenceManager getPreferenceManager() {
   1.178 +    return mPreferenceManager;
   1.179 +  }
   1.180 +
   1.181 +  /**
   1.182 +   * Sets the root of the preference hierarchy that this fragment is showing.
   1.183 +   *
   1.184 +   * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
   1.185 +   */
   1.186 +  public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
   1.187 +    if (PreferenceManagerCompat.setPreferences(mPreferenceManager, preferenceScreen) && preferenceScreen != null) {
   1.188 +      mHavePrefs = true;
   1.189 +      if (mInitDone) {
   1.190 +        postBindPreferences();
   1.191 +      }
   1.192 +    }
   1.193 +  }
   1.194 +
   1.195 +  /**
   1.196 +   * Gets the root of the preference hierarchy that this fragment is showing.
   1.197 +   *
   1.198 +   * @return The {@link PreferenceScreen} that is the root of the preference
   1.199 +   *         hierarchy.
   1.200 +   */
   1.201 +  public PreferenceScreen getPreferenceScreen() {
   1.202 +    return PreferenceManagerCompat.getPreferenceScreen(mPreferenceManager);
   1.203 +  }
   1.204 +
   1.205 +  /**
   1.206 +   * Adds preferences from activities that match the given {@link Intent}.
   1.207 +   *
   1.208 +   * @param intent The {@link Intent} to query activities.
   1.209 +   */
   1.210 +  public void addPreferencesFromIntent(Intent intent) {
   1.211 +    requirePreferenceManager();
   1.212 +
   1.213 +    setPreferenceScreen(PreferenceManagerCompat.inflateFromIntent(mPreferenceManager, intent, getPreferenceScreen()));
   1.214 +  }
   1.215 +
   1.216 +  /**
   1.217 +   * Inflates the given XML resource and adds the preference hierarchy to the current
   1.218 +   * preference hierarchy.
   1.219 +   *
   1.220 +   * @param preferencesResId The XML resource ID to inflate.
   1.221 +   */
   1.222 +  public void addPreferencesFromResource(int preferencesResId) {
   1.223 +    requirePreferenceManager();
   1.224 +
   1.225 +    setPreferenceScreen(PreferenceManagerCompat.inflateFromResource(mPreferenceManager, getActivity(),
   1.226 +        preferencesResId, getPreferenceScreen()));
   1.227 +  }
   1.228 +
   1.229 +  /**
   1.230 +   * {@inheritDoc}
   1.231 +   */
   1.232 +  @Override
   1.233 +  public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
   1.234 +      Preference preference) {
   1.235 +    //if (preference.getFragment() != null &&
   1.236 +    if (
   1.237 +        getActivity() instanceof OnPreferenceStartFragmentCallback) {
   1.238 +      return ((OnPreferenceStartFragmentCallback)getActivity()).onPreferenceStartFragment(
   1.239 +          this, preference);
   1.240 +    }
   1.241 +    return false;
   1.242 +  }
   1.243 +
   1.244 +  /**
   1.245 +   * Finds a {@link Preference} based on its key.
   1.246 +   *
   1.247 +   * @param key The key of the preference to retrieve.
   1.248 +   * @return The {@link Preference} with the key, or null.
   1.249 +   * @see PreferenceGroup#findPreference(CharSequence)
   1.250 +   */
   1.251 +  public Preference findPreference(CharSequence key) {
   1.252 +    if (mPreferenceManager == null) {
   1.253 +      return null;
   1.254 +    }
   1.255 +    return mPreferenceManager.findPreference(key);
   1.256 +  }
   1.257 +
   1.258 +  private void requirePreferenceManager() {
   1.259 +    if (mPreferenceManager == null) {
   1.260 +      throw new RuntimeException("This should be called after super.onCreate.");
   1.261 +    }
   1.262 +  }
   1.263 +
   1.264 +  private void postBindPreferences() {
   1.265 +    if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return;
   1.266 +    mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
   1.267 +  }
   1.268 +
   1.269 +  private void bindPreferences() {
   1.270 +    final PreferenceScreen preferenceScreen = getPreferenceScreen();
   1.271 +    if (preferenceScreen != null) {
   1.272 +      preferenceScreen.bind(getListView());
   1.273 +    }
   1.274 +  }
   1.275 +
   1.276 +  public ListView getListView() {
   1.277 +    ensureList();
   1.278 +    return mList;
   1.279 +  }
   1.280 +
   1.281 +  private void ensureList() {
   1.282 +    if (mList != null) {
   1.283 +      return;
   1.284 +    }
   1.285 +    View root = getView();
   1.286 +    if (root == null) {
   1.287 +      throw new IllegalStateException("Content view not yet created");
   1.288 +    }
   1.289 +    View rawListView = root.findViewById(android.R.id.list);
   1.290 +    if (!(rawListView instanceof ListView)) {
   1.291 +      throw new RuntimeException(
   1.292 +          "Content has view with id attribute 'android.R.id.list' "
   1.293 +              + "that is not a ListView class");
   1.294 +    }
   1.295 +    mList = (ListView)rawListView;
   1.296 +    if (mList == null) {
   1.297 +      throw new RuntimeException(
   1.298 +          "Your content must have a ListView whose id attribute is " +
   1.299 +          "'android.R.id.list'");
   1.300 +    }
   1.301 +    mList.setOnKeyListener(mListOnKeyListener);
   1.302 +    mHandler.post(mRequestFocus);
   1.303 +  }
   1.304 +
   1.305 +  private OnKeyListener mListOnKeyListener = new OnKeyListener() {
   1.306 +
   1.307 +    @Override
   1.308 +    public boolean onKey(View v, int keyCode, KeyEvent event) {
   1.309 +      Object selectedItem = mList.getSelectedItem();
   1.310 +      if (selectedItem instanceof Preference) {
   1.311 +        @SuppressWarnings("unused")
   1.312 +        View selectedView = mList.getSelectedView();
   1.313 +        //return ((Preference)selectedItem).onKey(
   1.314 +        //        selectedView, keyCode, event);
   1.315 +        return false;
   1.316 +      }
   1.317 +      return false;
   1.318 +    }
   1.319 +
   1.320 +  };
   1.321 +}

mercurial