2 * Copyright (C) 2010 Google Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.i18n.addressinput;
19 import android.app.ProgressDialog;
20 import android.content.Context;
21 import android.os.Handler;
22 import android.telephony.TelephonyManager;
23 import android.util.Log;
24 import android.view.LayoutInflater;
25 import android.view.View;
26 import android.view.ViewGroup;
27 import android.widget.AdapterView;
28 import android.widget.ArrayAdapter;
29 import android.widget.EditText;
30 import android.widget.LinearLayout;
31 import android.widget.LinearLayout.LayoutParams;
32 import android.widget.Spinner;
33 import android.widget.TextView;
35 import com.android.i18n.addressinput.AddressUIComponent.UIComponent;
36 import com.android.i18n.addressinput.LookupKey.KeyType;
37 import com.android.i18n.addressinput.LookupKey.ScriptType;
39 import java.util.ArrayList;
40 import java.text.Collator;
41 import java.util.Collections;
42 import java.util.EnumMap;
43 import java.util.HashMap;
44 import java.util.List;
45 import java.util.Locale;
49 * Address widget that lays out address fields, validate and format addresses according to local
52 public class AddressWidget implements AdapterView.OnItemSelectedListener {
53 private Context mContext;
55 private ViewGroup mRootView;
57 private LayoutInflater mInflater;
59 private CacheData mCacheData;
61 // A map for all address fields except for country.
62 private final EnumMap<AddressField, AddressUIComponent> mInputWidgets =
63 new EnumMap<AddressField, AddressUIComponent>(AddressField.class);
65 private FormController mFormController;
67 private FormatInterpreter mFormatInterpreter;
69 private FormOptions mFormOptions;
71 private StandardAddressVerifier mVerifier;
73 private ProgressDialog mProgressDialog;
75 private String mCurrentRegion;
77 // The current language the widget use in BCP47 format. It differs from the default locale of
78 // the phone in that it contains information on the script to use.
79 private String mWidgetLocale;
81 private ScriptType mScript;
83 // The appropriate label that should be applied to the admin area field of the current country.
84 // Examples include "state", "province", "emirate", etc.
85 private String mAdminLabel;
87 private static final Map<String, Integer> ADMIN_LABELS;
88 private static final Map<String, Integer> ADMIN_ERROR_MESSAGES;
90 private static final FormOptions SHOW_ALL_FIELDS = new FormOptions.Builder().build();
92 // The appropriate label that should be applied to the zip code field of the current country.
93 private enum ZipLabel {
98 private ZipLabel mZipLabel;
101 Map<String, Integer> adminLabelMap = new HashMap<String, Integer>(15);
102 adminLabelMap.put("area", R.string.i18n_area);
103 adminLabelMap.put("county", R.string.i18n_county_label);
104 adminLabelMap.put("department", R.string.i18n_department);
105 adminLabelMap.put("district", R.string.i18n_dependent_locality_label);
106 adminLabelMap.put("do_si", R.string.i18n_do_si);
107 adminLabelMap.put("emirate", R.string.i18n_emirate);
108 adminLabelMap.put("island", R.string.i18n_island);
109 adminLabelMap.put("parish", R.string.i18n_parish);
110 adminLabelMap.put("prefecture", R.string.i18n_prefecture);
111 adminLabelMap.put("province", R.string.i18n_province);
112 adminLabelMap.put("state", R.string.i18n_state_label);
113 ADMIN_LABELS = Collections.unmodifiableMap(adminLabelMap);
115 Map<String, Integer> adminErrorMap = new HashMap<String, Integer>(15);
116 adminErrorMap.put("area", R.string.invalid_area);
117 adminErrorMap.put("county", R.string.invalid_county_label);
118 adminErrorMap.put("department", R.string.invalid_department);
119 adminErrorMap.put("district", R.string.invalid_dependent_locality_label);
120 adminErrorMap.put("do_si", R.string.invalid_do_si);
121 adminErrorMap.put("emirate", R.string.invalid_emirate);
122 adminErrorMap.put("island", R.string.invalid_island);
123 adminErrorMap.put("parish", R.string.invalid_parish);
124 adminErrorMap.put("prefecture", R.string.invalid_prefecture);
125 adminErrorMap.put("province", R.string.invalid_province);
126 adminErrorMap.put("state", R.string.invalid_state_label);
127 ADMIN_ERROR_MESSAGES = Collections.unmodifiableMap(adminErrorMap);
130 // Need handler for callbacks to the UI thread
131 final Handler mHandler = new Handler();
133 final Runnable mUpdateMultipleFields = new Runnable() {
140 private class UpdateRunnable implements Runnable {
141 private AddressField myId;
143 public UpdateRunnable(AddressField id) {
149 updateInputWidget(myId);
153 private static class AddressSpinnerInfo {
154 private Spinner mView;
156 private AddressField mId;
158 private AddressField mParentId;
160 private ArrayAdapter<String> mAdapter;
162 private List<RegionData> mCurrentRegions;
164 public AddressSpinnerInfo(Spinner view, AddressField id, AddressField parentId) {
167 mParentId = parentId;
170 // Initializes the adapter that manages the Spinner.
171 public void initAdapter(Context context, int textViewId, int dropDownId) {
172 mAdapter = new ArrayAdapter<String>(context, textViewId);
173 mAdapter.setDropDownViewResource(dropDownId);
176 public void setSpinnerList(List<RegionData> list, String defaultKey) {
177 mCurrentRegions = list;
179 for (RegionData item : list) {
180 mAdapter.add(item.getDisplayName());
182 mAdapter.sort(Collator.getInstance(Locale.getDefault()));
183 if (defaultKey.length() == 0) {
184 mView.setSelection(0);
186 int position = mAdapter.getPosition(defaultKey);
187 mView.setSelection(position);
191 // Returns the region key of the currently selected region in the Spinner.
192 public String getRegionCode(int position) {
193 if (mAdapter.getCount() <= position) {
196 String value = mAdapter.getItem(position);
197 return getRegionDataKeyForValue(value);
200 // Returns the region key for the region value.
201 public String getRegionDataKeyForValue(String value) {
202 for (RegionData data : mCurrentRegions) {
203 if (data.getDisplayName().endsWith(value)) {
204 return data.getKey();
211 private ArrayList<AddressSpinnerInfo> mSpinners = new ArrayList<AddressSpinnerInfo>();
213 private void createView(ViewGroup rootView, AddressUIComponent field, String defaultKey,
215 @SuppressWarnings("deprecation") // FILL_PARENT renamed MATCH_PARENT in API Level 8.
216 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
217 LayoutParams.WRAP_CONTENT);
218 String fieldText = field.getFieldName();
220 if (fieldText.length() > 0) {
221 TextView textView = (TextView) mInflater.inflate(R.layout.address_textview, rootView,
223 rootView.addView(textView, lp);
224 textView.setText(fieldText);
226 if (field.getUIType().equals(UIComponent.EDIT)) {
227 View view = mInflater.inflate(R.layout.address_edittext, rootView, false);
229 EditText editText = (EditText) view;
230 editText.setEnabled(!readOnly);
231 rootView.addView(editText, lp);
232 } else if (field.getUIType().equals(UIComponent.SPINNER)) {
233 View view = mInflater.inflate(R.layout.address_spinner, rootView, false);
235 Spinner spinner = (Spinner) view;
236 rootView.addView(spinner, lp);
237 AddressSpinnerInfo spinnerInfo =
238 new AddressSpinnerInfo(spinner, field.getId(), field.getParentId());
239 spinnerInfo.initAdapter(mContext, android.R.layout.simple_spinner_item,
240 android.R.layout.simple_spinner_dropdown_item);
241 spinner.setAdapter(spinnerInfo.mAdapter);
242 spinnerInfo.setSpinnerList(field.getCandidatesList(), defaultKey);
244 if (fieldText.length() > 0) {
245 spinner.setPrompt(fieldText);
247 spinner.setOnItemSelectedListener(this);
248 mSpinners.add(spinnerInfo);
253 * Associates each field with its corresponding AddressUIComponent.
255 private void buildFieldWidgets() {
256 AddressData data = new AddressData.Builder().setCountry(mCurrentRegion).build();
257 LookupKey key = new LookupKey.Builder(LookupKey.KeyType.DATA).setAddressData(data).build();
258 AddressVerificationNodeData countryNode =
259 (new ClientData(mCacheData)).getDefaultData(key.toString());
261 // Set up AddressField.ADMIN_AREA
262 AddressUIComponent adminAreaUI = new AddressUIComponent(AddressField.ADMIN_AREA);
263 adminAreaUI.setFieldName(getAdminAreaFieldName(countryNode));
264 mInputWidgets.put(AddressField.ADMIN_AREA, adminAreaUI);
266 // Set up AddressField.LOCALITY
267 AddressUIComponent localityUI = new AddressUIComponent(AddressField.LOCALITY);
268 localityUI.setFieldName(mContext.getString(R.string.i18n_locality_label));
269 mInputWidgets.put(AddressField.LOCALITY, localityUI);
271 // Set up AddressField.DEPENDENT_LOCALITY
272 AddressUIComponent subLocalityUI = new AddressUIComponent(AddressField.DEPENDENT_LOCALITY);
273 subLocalityUI.setFieldName(mContext.getString(R.string.i18n_dependent_locality_label));
274 mInputWidgets.put(AddressField.DEPENDENT_LOCALITY, subLocalityUI);
276 // Set up AddressField.ADDRESS_LINE_1
277 AddressUIComponent addressLine1UI = new AddressUIComponent(AddressField.ADDRESS_LINE_1);
278 addressLine1UI.setFieldName(mContext.getString(R.string.i18n_address_line1_label));
279 mInputWidgets.put(AddressField.ADDRESS_LINE_1, addressLine1UI);
281 // Set up AddressField.ADDRESS_LINE_2
282 AddressUIComponent addressLine2UI = new AddressUIComponent(AddressField.ADDRESS_LINE_2);
283 addressLine2UI.setFieldName("");
284 mInputWidgets.put(AddressField.ADDRESS_LINE_2, addressLine2UI);
286 // Set up AddressField.ORGANIZATION
287 AddressUIComponent organizationUI = new AddressUIComponent(AddressField.ORGANIZATION);
288 organizationUI.setFieldName(mContext.getString(R.string.i18n_organization_label));
289 mInputWidgets.put(AddressField.ORGANIZATION, organizationUI);
291 // Set up AddressField.RECIPIENT
292 AddressUIComponent recipientUI = new AddressUIComponent(AddressField.RECIPIENT);
293 recipientUI.setFieldName(mContext.getString(R.string.i18n_recipient_label));
294 mInputWidgets.put(AddressField.RECIPIENT, recipientUI);
296 // Set up AddressField.POSTAL_CODE
297 AddressUIComponent postalCodeUI = new AddressUIComponent(AddressField.POSTAL_CODE);
298 postalCodeUI.setFieldName(getZipFieldName(countryNode));
299 mInputWidgets.put(AddressField.POSTAL_CODE, postalCodeUI);
301 // Set up AddressField.SORTING_CODE
302 AddressUIComponent sortingCodeUI = new AddressUIComponent(AddressField.SORTING_CODE);
303 sortingCodeUI.setFieldName("CEDEX");
304 mInputWidgets.put(AddressField.SORTING_CODE, sortingCodeUI);
307 private void initializeDropDowns() {
308 AddressUIComponent adminAreaUI = mInputWidgets.get(AddressField.ADMIN_AREA);
309 List<RegionData> adminAreaList = getRegionData(AddressField.COUNTRY);
310 adminAreaUI.initializeCandidatesList(adminAreaList);
312 AddressUIComponent localityUI = mInputWidgets.get(AddressField.LOCALITY);
313 List<RegionData> localityList = getRegionData(AddressField.ADMIN_AREA);
314 localityUI.initializeCandidatesList(localityList);
317 // Zip code is called postal code in some countries. This method returns the appropriate name
318 // for the given countryNode.
319 private String getZipFieldName(AddressVerificationNodeData countryNode) {
321 String zipType = countryNode.get(AddressDataKey.ZIP_NAME_TYPE);
322 if (zipType == null) {
323 mZipLabel = ZipLabel.POSTAL;
324 zipName = mContext.getString(R.string.i18n_postal_code_label);
326 mZipLabel = ZipLabel.ZIP;
327 zipName = mContext.getString(R.string.i18n_zip_code_label);
332 private String getAdminAreaFieldName(AddressVerificationNodeData countryNode) {
333 String adminLabelType = countryNode.get(AddressDataKey.STATE_NAME_TYPE);
334 mAdminLabel = adminLabelType;
335 Integer result = ADMIN_LABELS.get(adminLabelType);
336 if (result == null) {
337 // Fallback to province.
338 result = R.string.i18n_province;
340 return mContext.getString(result);
343 private void buildCountryListBox() {
344 // Set up AddressField.COUNTRY
345 AddressUIComponent countryUI = new AddressUIComponent(AddressField.COUNTRY);
346 countryUI.setFieldName(mContext.getString(R.string.i18n_country_label));
347 ArrayList<RegionData> countries = new ArrayList<RegionData>();
348 for (RegionData regionData : mFormController.getRegionData(new LookupKey.Builder(
349 KeyType.DATA).build())) {
350 String regionKey = regionData.getKey();
351 // ZZ represents an unknown region code.
352 if (!regionKey.equals("ZZ")) {
353 String localCountryName = getLocalCountryName(regionKey);
354 RegionData country = new RegionData.Builder().setKey(regionKey).setName(
355 localCountryName).build();
356 countries.add(country);
359 countryUI.initializeCandidatesList(countries);
360 mInputWidgets.put(AddressField.COUNTRY, countryUI);
363 private String getLocalCountryName(String regionCode) {
364 return (new Locale("", regionCode)).getDisplayCountry(Locale.getDefault());
367 private AddressSpinnerInfo findSpinnerByView(View view) {
368 for (AddressSpinnerInfo spinnerInfo : mSpinners) {
369 if (spinnerInfo.mView == view) {
376 private void updateFields() {
377 removePreviousViews();
379 initializeDropDowns();
380 layoutAddressFields();
383 private void removePreviousViews() {
384 if (mRootView == null) {
387 int childCount = mRootView.getChildCount();
388 if (mFormOptions.isHidden(AddressField.COUNTRY)) {
389 if (childCount > 0) {
390 mRootView.removeAllViews();
392 } else if (childCount > 2) {
393 // Keep the TextView and Spinner for Country and remove everything else.
394 mRootView.removeViews(2, mRootView.getChildCount() - 2);
398 private void layoutAddressFields() {
399 for (AddressField field : mFormatInterpreter.getAddressFieldOrder(mScript,
401 if (!mFormOptions.isHidden(field)) {
402 createView(mRootView, mInputWidgets.get(field), "", mFormOptions.isReadonly(field));
407 private void updateChildNodes(AdapterView<?> parent, int position) {
408 AddressSpinnerInfo spinnerInfo = findSpinnerByView(parent);
409 if (spinnerInfo == null) {
413 // Find all the child spinners, if any, that depend on this one.
414 final AddressField myId = spinnerInfo.mId;
415 if (myId != AddressField.COUNTRY && myId != AddressField.ADMIN_AREA
416 && myId != AddressField.LOCALITY) {
417 // Only a change in the three AddressFields above will trigger a change in other
418 // AddressFields. Therefore, for all other AddressFields, we return immediately.
422 String regionCode = spinnerInfo.getRegionCode(position);
423 if (myId == AddressField.COUNTRY) {
424 updateWidgetOnCountryChange(regionCode);
428 mFormController.requestDataForAddress(getAddressData(), new DataLoadListener() {
430 public void dataLoadingBegin(){
434 public void dataLoadingEnd() {
435 Runnable updateChild = new UpdateRunnable(myId);
436 mHandler.post(updateChild);
441 public void updateWidgetOnCountryChange(String regionCode) {
442 if (mCurrentRegion.equalsIgnoreCase(regionCode)) {
445 mCurrentRegion = regionCode;
446 mFormController.setCurrentCountry(mCurrentRegion);
450 private void updateInputWidget(AddressField myId) {
451 for (AddressSpinnerInfo child : mSpinners) {
452 if (child.mParentId == myId) {
453 List<RegionData> candidates = getRegionData(child.mParentId);
454 child.setSpinnerList(candidates, "");
459 public void renderForm() {
460 setWidgetLocaleAndScript();
461 AddressData data = new AddressData.Builder().setCountry(mCurrentRegion)
462 .setLanguageCode(mWidgetLocale).build();
463 mFormController.requestDataForAddress(data, new DataLoadListener() {
465 public void dataLoadingBegin() {
466 mProgressDialog = ProgressDialog.show(mContext, "",
467 mContext.getString(R.string.address_data_loading));
468 Log.d(this.toString(), "Progress dialog started.");
471 public void dataLoadingEnd() {
472 Log.d(this.toString(), "Data loading completed.");
473 mProgressDialog.dismiss();
474 Log.d(this.toString(), "Progress dialog stopped.");
475 mHandler.post(mUpdateMultipleFields);
480 private void setWidgetLocaleAndScript() {
481 mWidgetLocale = Util.getWidgetCompatibleLanguageCode(Locale.getDefault(), mCurrentRegion);
482 mFormController.setLanguageCode(mWidgetLocale);
483 mScript = Util.isExplicitLatinScript(mWidgetLocale)
488 private List<RegionData> getRegionData(AddressField parentField) {
489 AddressData address = getAddressData();
491 // Removes language code from address if it is default. This address is used to build
492 // lookup key, which neglects default language. For example, instead of "data/US--en/CA",
493 // the right lookup key is "data/US/CA".
494 if (mFormController.isDefaultLanguage(address.getLanguageCode())) {
495 address = new AddressData.Builder(address).setLanguageCode(null).build();
498 LookupKey parentKey = mFormController.getDataKeyFor(address).getKeyForUpperLevelField(
500 List<RegionData> candidates;
501 // Can't build a key with parent field, quit.
502 if (parentKey == null) {
503 Log.w(this.toString(), "Can't build key with parent field " + parentField + ". One of"
504 + " the ancestor fields might be empty");
506 // Removes candidates that exist from previous settings. For example, data/US has a
507 // list of candidates AB, BC, CA, etc, that list should be cleaned up when user updates
508 // the address by changing country to Channel Islands.
509 candidates = new ArrayList<RegionData>(1);
511 candidates = mFormController.getRegionData(parentKey);
517 * Creates an AddressWidget to be attached to rootView for the specific context.
519 public AddressWidget(Context context, ViewGroup rootView, FormOptions formOptions,
520 ClientCacheManager cacheManager) {
522 ((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE))
523 .getSimCountryIso().toUpperCase(Locale.US);
524 if (mCurrentRegion.length() == 0) {
525 mCurrentRegion = "US";
527 init(context, rootView, formOptions, cacheManager);
532 * Creates an AddressWidget to be attached to rootView for the specific context, and fill out
533 * the address form with savedAddress.
535 public AddressWidget(Context context, ViewGroup rootView, FormOptions formOptions,
536 ClientCacheManager cacheManager, AddressData savedAddress) {
537 mCurrentRegion = savedAddress.getPostalCountry();
538 // Postal country must be 2 letter country code. Otherwise default to US.
539 if (mCurrentRegion == null || mCurrentRegion.length() != 2) {
540 mCurrentRegion = "US";
542 init(context, rootView, formOptions, cacheManager);
543 renderFormWithSavedAddress(savedAddress);
546 public void renderFormWithSavedAddress(AddressData savedAddress) {
547 setWidgetLocaleAndScript();
548 removePreviousViews();
550 layoutAddressFields();
551 initializeFieldsWithAddress(savedAddress);
554 private void initializeFieldsWithAddress(AddressData savedAddress) {
555 for (AddressField field : mFormatInterpreter.getAddressFieldOrder(mScript,
557 String value = savedAddress.getFieldValue(field);
561 AddressUIComponent uiComponent = mInputWidgets.get(field);
562 EditText view = (EditText) uiComponent.getView();
569 private void init(Context context, ViewGroup rootView, FormOptions formOptions,
570 ClientCacheManager cacheManager) {
572 mRootView = rootView;
573 mFormOptions = formOptions;
574 mCacheData = new CacheData(cacheManager);
575 mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
577 new FormController(new ClientData(mCacheData),
578 mWidgetLocale, mCurrentRegion);
579 mFormatInterpreter = new FormatInterpreter(mFormOptions);
580 mVerifier = new StandardAddressVerifier(
581 new FieldVerifier(new ClientData(mCacheData)));
582 if (!formOptions.isHidden(AddressField.COUNTRY)) {
583 buildCountryListBox();
584 createView(mRootView, mInputWidgets.get(AddressField.COUNTRY),
585 getLocalCountryName(mCurrentRegion),
586 formOptions.isReadonly(AddressField.COUNTRY));
591 * Sets address data server URL. Input URL cannot be null.
593 * @param url The service URL.
595 public void setUrl(String url) {
596 mCacheData.setUrl(url);
600 * Gets user input address in AddressData format.
602 public AddressData getAddressData() {
603 AddressData.Builder builder = new AddressData.Builder();
604 builder.setCountry(mCurrentRegion);
605 for (AddressField field : mFormatInterpreter.getAddressFieldOrder(mScript,
607 AddressUIComponent addressUIComponent = mInputWidgets.get(field);
608 if (addressUIComponent != null) {
609 String value = addressUIComponent.getValue();
610 if (addressUIComponent.getUIType() == UIComponent.SPINNER) {
611 // For drop-downs, return the key of the region selected instead of the value.
612 View view = getViewForField(field);
613 AddressSpinnerInfo spinnerInfo = findSpinnerByView(view);
614 if (spinnerInfo != null) {
615 value = spinnerInfo.getRegionDataKeyForValue(value);
618 builder.set(field, value);
621 builder.setLanguageCode(mWidgetLocale);
622 return builder.build();
626 * Gets the formatted address.
628 * This method does not validate addresses. Also, it will "normalize" the result strings by
629 * removing redundant spaces and empty lines.
631 * @return the formatted address
633 public List<String> getEnvelopeAddress() {
634 return mFormatInterpreter.getEnvelopeAddress(getAddressData());
638 * Gets the formatted address based on the AddressData passed in.
640 public List<String> getEnvelopeAddress(AddressData address) {
641 return mFormatInterpreter.getEnvelopeAddress(address);
645 * Gets the formatted address based on the AddressData passed in with none of the relevant
648 public static List<String> getFullEnvelopeAddress(AddressData address) {
649 return new FormatInterpreter(SHOW_ALL_FIELDS).getEnvelopeAddress(address);
653 * Get problems found in the address data entered by the user.
655 public AddressProblems getAddressProblems() {
656 AddressProblems problems = new AddressProblems();
657 AddressData addressData = getAddressData();
658 mVerifier.verify(addressData, problems);
663 * Displays an appropriate error message when the AddressField contains an invalid entry.
665 * @return the View object representing the AddressField.
667 public View displayErrorMessageForInvalidEntryIn(AddressField field) {
668 Log.d(this.toString(), "Display error message for the field: " + field.toString());
669 AddressUIComponent addressUIComponent = mInputWidgets.get(field);
670 if (addressUIComponent != null && addressUIComponent.getUIType() == UIComponent.EDIT) {
671 int errorMessageId = getErrorMessageIdForInvalidEntryIn(field);
672 EditText view = (EditText) addressUIComponent.getView();
673 view.setError(mContext.getString(errorMessageId));
679 private int getErrorMessageIdForInvalidEntryIn(AddressField field) {
682 return ADMIN_ERROR_MESSAGES.get(mAdminLabel);
684 return R.string.invalid_locality_label;
685 case DEPENDENT_LOCALITY:
686 return R.string.invalid_dependent_locality_label;
688 return (mZipLabel == ZipLabel.POSTAL
689 ? R.string.invalid_postal_code_label
690 : R.string.invalid_zip_code_label);
692 return R.string.invalid_entry;
697 * Clears all error messages in the UI.
699 public void clearErrorMessage() {
700 for (AddressField field : mFormatInterpreter.getAddressFieldOrder(mScript,
702 AddressUIComponent addressUIComponent = mInputWidgets.get(field);
704 if (addressUIComponent != null && addressUIComponent.getUIType() == UIComponent.EDIT) {
705 EditText view = (EditText) addressUIComponent.getView();
713 public View getViewForField(AddressField field) {
714 AddressUIComponent component = mInputWidgets.get(field);
715 if (component == null) {
718 return component.getView();
722 public void onNothingSelected(AdapterView<?> arg0) {
726 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
727 updateChildNodes(parent, position);