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 17 package com.android.example.spinner; 18 19 import com.android.example.spinner.R; 20 21 import android.app.Activity; 22 import android.content.Context; 23 import android.content.SharedPreferences; 24 import android.os.Bundle; 25 import android.view.View; 26 import android.widget.AdapterView; 27 import android.widget.ArrayAdapter; 28 import android.widget.Spinner; 29 import android.widget.TextView; 30 import android.widget.Toast; 31 import android.widget.AdapterView.OnItemSelectedListener; 32 33 /** 34 * Displays an Android spinner widget backed by data in an array. The 35 * array is loaded from the strings.xml resources file. 36 */ 37 public class SpinnerActivity extends Activity { 38 39 /** 40 * Fields to contain the current position and display contents of the spinner 41 */ 42 protected int mPos; 43 protected String mSelection; 44 45 /** 46 * ArrayAdapter connects the spinner widget to array-based data. 47 */ 48 protected ArrayAdapter<CharSequence> mAdapter; 49 50 /** 51 * The initial position of the spinner when it is first installed. 52 */ 53 public static final int DEFAULT_POSITION = 2; 54 55 /** 56 * The name of a properties file that stores the position and 57 * selection when the activity is not loaded. 58 */ 59 public static final String PREFERENCES_FILE = "SpinnerPrefs"; 60 61 /** 62 * These values are used to read and write the properties file. 63 * PROPERTY_DELIMITER delimits the key and value in a Java properties file. 64 * The "marker" strings are used to write the properties into the file 65 */ 66 public static final String PROPERTY_DELIMITER = "="; 67 68 /** 69 * The key or label for "position" in the preferences file 70 */ 71 public static final String POSITION_KEY = "Position"; 72 73 /** 74 * The key or label for "selection" in the preferences file 75 */ 76 public static final String SELECTION_KEY = "Selection"; 77 78 public static final String POSITION_MARKER = 79 POSITION_KEY + PROPERTY_DELIMITER; 80 81 public static final String SELECTION_MARKER = 82 SELECTION_KEY + PROPERTY_DELIMITER; 83 84 /** 85 * Initializes the application and the activity. 86 * 1) Sets the view 87 * 2) Reads the spinner's backing data from the string resources file 88 * 3) Instantiates a callback listener for handling selection from the 89 * spinner 90 * Notice that this method includes code that can be uncommented to force 91 * tests to fail. 92 * 93 * This method overrides the default onCreate() method for an Activity. 94 * 95 * @see android.app.Activity#onCreate(android.os.Bundle) 96 */ 97 @Override 98 public void onCreate(Bundle savedInstanceState) { 99 100 /** 101 * derived classes that use onCreate() overrides must always call the super constructor 102 */ 103 super.onCreate(savedInstanceState); 104 105 setContentView(R.layout.main); 106 107 Spinner spinner = (Spinner) findViewById(R.id.Spinner01); 108 109 /* 110 * Create a backing mLocalAdapter for the Spinner from a list of the 111 * planets. The list is defined by XML in the strings.xml file. 112 */ 113 114 this.mAdapter = ArrayAdapter.createFromResource(this, R.array.Planets, 115 android.R.layout.simple_spinner_dropdown_item); 116 117 /* 118 * Attach the mLocalAdapter to the spinner. 119 */ 120 121 spinner.setAdapter(this.mAdapter); 122 123 /* 124 * Create a listener that is triggered when Android detects the 125 * user has selected an item in the Spinner. 126 */ 127 128 OnItemSelectedListener spinnerListener = new myOnItemSelectedListener(this,this.mAdapter); 129 130 /* 131 * Attach the listener to the Spinner. 132 */ 133 134 spinner.setOnItemSelectedListener(spinnerListener); 135 136 137 /* 138 * To demonstrate a failure in the preConditions test, 139 * uncomment the following line. 140 * The test will fail because the selection listener for the 141 * Spinner is not set. 142 */ 143 // spinner.setOnItemSelectedListener(null); 144 145 } 146 147 148 /** 149 * A callback listener that implements the 150 * {@link android.widget.AdapterView.OnItemSelectedListener} interface 151 * For views based on adapters, this interface defines the methods available 152 * when the user selects an item from the View. 153 * 154 */ 155 public class myOnItemSelectedListener implements OnItemSelectedListener { 156 157 /* 158 * provide local instances of the mLocalAdapter and the mLocalContext 159 */ 160 161 ArrayAdapter<CharSequence> mLocalAdapter; 162 Activity mLocalContext; 163 164 /** 165 * Constructor 166 * @param c - The activity that displays the Spinner. 167 * @param ad - The Adapter view that 168 * controls the Spinner. 169 * Instantiate a new listener object. 170 */ 171 public myOnItemSelectedListener(Activity c, ArrayAdapter<CharSequence> ad) { 172 173 this.mLocalContext = c; 174 this.mLocalAdapter = ad; 175 176 } 177 178 /** 179 * When the user selects an item in the spinner, this method is invoked by the callback 180 * chain. Android calls the item selected listener for the spinner, which invokes the 181 * onItemSelected method. 182 * 183 * @see android.widget.AdapterView.OnItemSelectedListener#onItemSelected( 184 * android.widget.AdapterView, android.view.View, int, long) 185 * @param parent - the AdapterView for this listener 186 * @param v - the View for this listener 187 * @param pos - the 0-based position of the selection in the mLocalAdapter 188 * @param row - the 0-based row number of the selection in the View 189 */ 190 public void onItemSelected(AdapterView<?> parent, View v, int pos, long row) { 191 192 SpinnerActivity.this.mPos = pos; 193 SpinnerActivity.this.mSelection = parent.getItemAtPosition(pos).toString(); 194 /* 195 * Set the value of the text field in the UI 196 */ 197 TextView resultText = (TextView)findViewById(R.id.SpinnerResult); 198 resultText.setText(SpinnerActivity.this.mSelection); 199 } 200 201 /** 202 * The definition of OnItemSelectedListener requires an override 203 * of onNothingSelected(), even though this implementation does not use it. 204 * @param parent - The View for this Listener 205 */ 206 public void onNothingSelected(AdapterView<?> parent) { 207 208 // do nothing 209 210 } 211 } 212 213 /** 214 * Restores the current state of the spinner (which item is selected, and the value 215 * of that item). 216 * Since onResume() is always called when an Activity is starting, even if it is re-displaying 217 * after being hidden, it is the best place to restore state. 218 * 219 * Attempts to read the state from a preferences file. If this read fails, 220 * assume it was just installed, so do an initialization. Regardless, change the 221 * state of the spinner to be the previous position. 222 * 223 * @see android.app.Activity#onResume() 224 */ 225 @Override 226 public void onResume() { 227 228 /* 229 * an override to onResume() must call the super constructor first. 230 */ 231 232 super.onResume(); 233 234 /* 235 * Try to read the preferences file. If not found, set the state to the desired initial 236 * values. 237 */ 238 239 if (!readInstanceState(this)) setInitialState(); 240 241 /* 242 * Set the spinner to the current state. 243 */ 244 245 Spinner restoreSpinner = (Spinner)findViewById(R.id.Spinner01); 246 restoreSpinner.setSelection(getSpinnerPosition()); 247 248 } 249 250 /** 251 * Store the current state of the spinner (which item is selected, and the value of that item). 252 * Since onPause() is always called when an Activity is about to be hidden, even if it is about 253 * to be destroyed, it is the best place to save state. 254 * 255 * Attempt to write the state to the preferences file. If this fails, notify the user. 256 * 257 * @see android.app.Activity#onPause() 258 */ 259 @Override 260 public void onPause() { 261 262 /* 263 * an override to onPause() must call the super constructor first. 264 */ 265 266 super.onPause(); 267 268 /* 269 * Save the state to the preferences file. If it fails, display a Toast, noting the failure. 270 */ 271 272 if (!writeInstanceState(this)) { 273 Toast.makeText(this, 274 "Failed to write state!", Toast.LENGTH_LONG).show(); 275 } 276 } 277 278 /** 279 * Sets the initial state of the spinner when the application is first run. 280 */ 281 public void setInitialState() { 282 283 this.mPos = DEFAULT_POSITION; 284 285 } 286 287 /** 288 * Read the previous state of the spinner from the preferences file 289 * @param c - The Activity's Context 290 */ 291 public boolean readInstanceState(Context c) { 292 293 /* 294 * The preferences are stored in a SharedPreferences file. The abstract implementation of 295 * SharedPreferences is a "file" containing a hashmap. All instances of an application 296 * share the same instance of this file, which means that all instances of an application 297 * share the same preference settings. 298 */ 299 300 /* 301 * Get the SharedPreferences object for this application 302 */ 303 304 SharedPreferences p = c.getSharedPreferences(PREFERENCES_FILE, MODE_WORLD_READABLE); 305 /* 306 * Get the position and value of the spinner from the file, or a default value if the 307 * key-value pair does not exist. 308 */ 309 this.mPos = p.getInt(POSITION_KEY, SpinnerActivity.DEFAULT_POSITION); 310 this.mSelection = p.getString(SELECTION_KEY, ""); 311 312 /* 313 * SharedPreferences doesn't fail if the code tries to get a non-existent key. The 314 * most straightforward way to indicate success is to return the results of a test that 315 * SharedPreferences contained the position key. 316 */ 317 318 return (p.contains(POSITION_KEY)); 319 320 } 321 322 /** 323 * Write the application's current state to a properties repository. 324 * @param c - The Activity's Context 325 * 326 */ 327 public boolean writeInstanceState(Context c) { 328 329 /* 330 * Get the SharedPreferences object for this application 331 */ 332 333 SharedPreferences p = 334 c.getSharedPreferences(SpinnerActivity.PREFERENCES_FILE, MODE_WORLD_READABLE); 335 336 /* 337 * Get the editor for this object. The editor interface abstracts the implementation of 338 * updating the SharedPreferences object. 339 */ 340 341 SharedPreferences.Editor e = p.edit(); 342 343 /* 344 * Write the keys and values to the Editor 345 */ 346 347 e.putInt(POSITION_KEY, this.mPos); 348 e.putString(SELECTION_KEY, this.mSelection); 349 350 /* 351 * Commit the changes. Return the result of the commit. The commit fails if Android 352 * failed to commit the changes to persistent storage. 353 */ 354 355 return (e.commit()); 356 357 } 358 359 public int getSpinnerPosition() { 360 return this.mPos; 361 } 362 363 public void setSpinnerPosition(int pos) { 364 this.mPos = pos; 365 } 366 367 public String getSpinnerSelection() { 368 return this.mSelection; 369 } 370 371 public void setSpinnerSelection(String selection) { 372 this.mSelection = selection; 373 } 374 } 375