1392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann/* 2392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Copyright (C) 2010 The Android Open Source Project 3392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * 4392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Licensed under the Apache License, Version 2.0 (the "License"); 5392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * you may not use this file except in compliance with the License. 6392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * You may obtain a copy of the License at 7392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * 8392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * http://www.apache.org/licenses/LICENSE-2.0 9392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * 10392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Unless required by applicable law or agreed to in writing, software 11392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * distributed under the License is distributed on an "AS IS" BASIS, 12392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * See the License for the specific language governing permissions and 14392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * limitations under the License. 15392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 16392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 1718ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovpackage com.android.contacts.editor; 18392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 19392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.content.Context; 20392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.graphics.Rect; 21392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.os.Parcel; 22392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.os.Parcelable; 23392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.text.Editable; 24392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.text.InputType; 251b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuanimport android.text.TextUtils; 26392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.text.TextWatcher; 27392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.util.AttributeSet; 2826918da1650c1ff7b6f92deb978ab976525c811aJosh Gargusimport android.util.Log; 29392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.view.Gravity; 30392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.view.View; 3163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuanimport android.view.ViewGroup; 320af02581eecabbe234e54364bdbbd65090518d7cKatherine Kuanimport android.view.inputmethod.EditorInfo; 3326918da1650c1ff7b6f92deb978ab976525c811aJosh Gargusimport android.view.inputmethod.InputMethodManager; 34392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.widget.EditText; 3512a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuanimport android.widget.ImageView; 36392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.widget.LinearLayout; 37da5bf1cf60beef3de5e651a569fa544293683926Dave Santoro 38e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R; 39cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.RawContactDelta; 40cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.ContactsUtils; 41738ff8623dc77dd91a1b9023861e924ba5e4c27eChiao Chengimport com.android.contacts.common.model.ValuesDelta; 42428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.account.AccountType.EditField; 43428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.dataitem.DataKind; 44720ac2f99fc6cb4b92852a1a54ccd8c7c796c7d2Chiao Chengimport com.android.contacts.common.util.PhoneNumberFormatter; 45e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng 46392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann/** 4763ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan * Simple editor that handles labels and any {@link EditField} defined for the 48851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu * entry. Uses {@link ValuesDelta} to read any existing {@link RawContact} values, 4963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan * and to correctly write any changes values. 50392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 51392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannpublic class TextFieldsEditorView extends LabeledEditorView { 5226918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus private static final String TAG = TextFieldsEditorView.class.getSimpleName(); 5326918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus 54392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private EditText[] mFieldEditTexts = null; 5563ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan private ViewGroup mFields = null; 5612a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan private View mExpansionViewContainer; 5712a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan private ImageView mExpansionView; 58392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private boolean mHideOptional = true; 59392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private boolean mHasShortAndLongForms; 601ebbd5bbe71814123b80df702b474bcd7196cbb7Katherine Kuan private int mMinFieldHeight; 615cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell private int mEditTextTopPadding; 625cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell private int mEditTextBottomPadding; 63ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee private int mPreviousViewHeight; 64392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 65392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public TextFieldsEditorView(Context context) { 66392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super(context); 67392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 68392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 69392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public TextFieldsEditorView(Context context, AttributeSet attrs) { 70392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super(context, attrs); 71392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 72392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 73392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public TextFieldsEditorView(Context context, AttributeSet attrs, int defStyle) { 74392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super(context, attrs, defStyle); 75392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 76392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 7763ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan /** {@inheritDoc} */ 7891d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov @Override 7963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan protected void onFinishInflate() { 8063ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan super.onFinishInflate(); 8163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan 8263ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan setDrawingCacheEnabled(true); 8363ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan setAlwaysDrawnWithCacheEnabled(true); 8463ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan 851ebbd5bbe71814123b80df702b474bcd7196cbb7Katherine Kuan mMinFieldHeight = mContext.getResources().getDimensionPixelSize( 861ebbd5bbe71814123b80df702b474bcd7196cbb7Katherine Kuan R.dimen.editor_min_line_item_height); 875cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell mEditTextBottomPadding = mContext.getResources().getDimensionPixelSize( 885cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell R.dimen.editor_text_field_bottom_padding); 895cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell mEditTextTopPadding = mContext.getResources().getDimensionPixelSize( 905cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell R.dimen.editor_text_field_top_padding); 9163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mFields = (ViewGroup) findViewById(R.id.editors); 9212a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan mExpansionView = (ImageView) findViewById(R.id.expansion_view); 9312a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan mExpansionViewContainer = findViewById(R.id.expansion_view_container); 9412a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan mExpansionViewContainer.setOnClickListener(new OnClickListener() { 9563ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan @Override 9663ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan public void onClick(View v) { 97ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee mPreviousViewHeight = mFields.getHeight(); 98ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee 9963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan // Save focus 10063ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan final View focusedChild = getFocusedChild(); 10163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan final int focusedViewId = focusedChild == null ? -1 : focusedChild.getId(); 10263ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan 10363ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan // Reconfigure GUI 10463ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mHideOptional = !mHideOptional; 10563ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan onOptionalFieldVisibilityChange(); 10663ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan rebuildValues(); 10763ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan 10863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan // Restore focus 10963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan View newFocusView = findViewById(focusedViewId); 11063ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan if (newFocusView == null || newFocusView.getVisibility() == GONE) { 11163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan // find first visible child 11263ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan newFocusView = TextFieldsEditorView.this; 113392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 11463ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan newFocusView.requestFocus(); 115ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee 116ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee EditorAnimator.getInstance().slideAndFadeIn(mFields, mPreviousViewHeight); 117392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 11863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan }); 119392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 120392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 121392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 12226918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus public void editNewlyAddedField() { 12326918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus // Some editors may have multiple fields (eg: first-name/last-name), but since the user 12426918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus // has not selected a particular one, it is reasonable to simply pick the first. 12526918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus final View editor = mFields.getChildAt(0); 12626918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus 12726918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus // Show the soft-keyboard. 12826918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus InputMethodManager imm = 12926918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus (InputMethodManager)getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 13026918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus if (imm != null) { 13126918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus if (!imm.showSoftInput(editor, InputMethodManager.SHOW_IMPLICIT)) { 13226918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus Log.w(TAG, "Failed to show soft input method."); 13326918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus } 13426918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus } 13526918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus } 13626918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus 13726918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus @Override 138392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void setEnabled(boolean enabled) { 139392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super.setEnabled(enabled); 140392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 141392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (mFieldEditTexts != null) { 142392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann for (int index = 0; index < mFieldEditTexts.length; index++) { 14302bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mFieldEditTexts[index].setEnabled(!isReadOnly() && enabled); 144392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 145392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 14612a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan mExpansionView.setEnabled(!isReadOnly() && enabled); 147392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 148392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 149392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 150392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Creates or removes the type/label button. Doesn't do anything if already correctly configured 151392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 15212a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan private void setupExpansionView(boolean shouldExist, boolean collapsed) { 153392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (shouldExist) { 15412a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan mExpansionViewContainer.setVisibility(View.VISIBLE); 15512a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan mExpansionView.setImageResource(collapsed 156915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann ? R.drawable.ic_menu_expander_minimized_holo_light 157915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann : R.drawable.ic_menu_expander_maximized_holo_light); 15863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan } else { 15912a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan mExpansionViewContainer.setVisibility(View.GONE); 160392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 161392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 162392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 163392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 164392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected void requestFocusForFirstEditField() { 165392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (mFieldEditTexts != null && mFieldEditTexts.length != 0) { 166392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann EditText firstField = null; 167392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann boolean anyFieldHasFocus = false; 168392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann for (EditText editText : mFieldEditTexts) { 169392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (firstField == null && editText.getVisibility() == View.VISIBLE) { 170392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann firstField = editText; 171392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 172392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (editText.hasFocus()) { 173392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann anyFieldHasFocus = true; 174392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann break; 175392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 176392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 177392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (!anyFieldHasFocus && firstField != null) { 178392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann firstField.requestFocus(); 179392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 180392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 181392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 182392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 18344cfc56d1701629070384364416c1311b780535dChiao Cheng public void setValue(int field, String value) { 18444cfc56d1701629070384364416c1311b780535dChiao Cheng mFieldEditTexts[field].setText(value); 18544cfc56d1701629070384364416c1311b780535dChiao Cheng } 18644cfc56d1701629070384364416c1311b780535dChiao Cheng 187392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 188851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public void setValues(DataKind kind, ValuesDelta entry, RawContactDelta state, boolean readOnly, 189392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann ViewIdGenerator vig) { 190392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super.setValues(kind, entry, state, readOnly, vig); 191392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // Remove edit texts that we currently have 192392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (mFieldEditTexts != null) { 193392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann for (EditText fieldEditText : mFieldEditTexts) { 19463ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mFields.removeView(fieldEditText); 195392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 196392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 197392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann boolean hidePossible = false; 198392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 199392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann int fieldCount = kind.fieldList.size(); 200392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mFieldEditTexts = new EditText[fieldCount]; 201392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann for (int index = 0; index < fieldCount; index++) { 202392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann final EditField field = kind.fieldList.get(index); 203392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann final EditText fieldView = new EditText(mContext); 204392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 2055cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell LayoutParams.WRAP_CONTENT)); 2069db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan // Set either a minimum line requirement or a minimum height (because {@link TextView} 2079db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan // only takes one or the other at a single time). 2089db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan if (field.minLines != 0) { 2099db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan fieldView.setMinLines(field.minLines); 2109db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan } else { 2119db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan fieldView.setMinHeight(mMinFieldHeight); 2129db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan } 21350a27b70581b0191995969c63edd1f6a3db3d1b7Makoto Onuki fieldView.setTextAppearance(getContext(), android.R.style.TextAppearance_Medium); 2145cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell fieldView.setPadding(fieldView.getPaddingLeft(), mEditTextTopPadding, 2155cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell fieldView.getPaddingRight(), mEditTextBottomPadding); 2165cc21eb9fd21c50ada1d94665560099025f9853dBrian Attwell fieldView.setHintTextColor(R.color.secondary_text_color); 217392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.setGravity(Gravity.TOP); 218392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mFieldEditTexts[index] = fieldView; 219392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.setId(vig.getId(state, kind, entry, index)); 220392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (field.titleRes > 0) { 221392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.setHint(field.titleRes); 222392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 223392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann int inputType = field.inputType; 224392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.setInputType(inputType); 225392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (inputType == InputType.TYPE_CLASS_PHONE) { 226e598332967106e3db63b73c701f21902d169efefMakoto Onuki PhoneNumberFormatter.setPhoneNumberFormattingTextWatcher(mContext, fieldView); 227cbfb11288368bca3a6e350ae880d53ffb4907b78Yorke Lee fieldView.setTextDirection(View.TEXT_DIRECTION_LTR); 228392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 229392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 2300af02581eecabbe234e54364bdbbd65090518d7cKatherine Kuan // Show the "next" button in IME to navigate between text fields 2310af02581eecabbe234e54364bdbbd65090518d7cKatherine Kuan // TODO: Still need to properly navigate to/from sections without text fields, 2320af02581eecabbe234e54364bdbbd65090518d7cKatherine Kuan // See Bug: 5713510 2330af02581eecabbe234e54364bdbbd65090518d7cKatherine Kuan fieldView.setImeOptions(EditorInfo.IME_ACTION_NEXT); 2340af02581eecabbe234e54364bdbbd65090518d7cKatherine Kuan 235392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // Read current value from state 236392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann final String column = field.column; 237392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann final String value = entry.getAsString(column); 238392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.setText(value); 239392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 2405e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan // Show the delete button if we have a non-null value 2415e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan setDeleteButtonVisible(value != null); 2425e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan 243392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // Prepare listener for writing changes 244392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.addTextChangedListener(new TextWatcher() { 245392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 246392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void afterTextChanged(Editable s) { 247392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // Trigger event for newly changed value 248392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann onFieldChanged(column, s.toString()); 249392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 250392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 251392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 252392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void beforeTextChanged(CharSequence s, int start, int count, int after) { 253392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 254392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 255392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 256392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void onTextChanged(CharSequence s, int start, int before, int count) { 257392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 258392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann }); 259392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 26002bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov fieldView.setEnabled(isEnabled() && !readOnly); 261392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 262392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (field.shortForm) { 263392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann hidePossible = true; 264392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mHasShortAndLongForms = true; 265392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.setVisibility(mHideOptional ? View.VISIBLE : View.GONE); 266392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } else if (field.longForm) { 267392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann hidePossible = true; 268392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mHasShortAndLongForms = true; 269392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.setVisibility(mHideOptional ? View.GONE : View.VISIBLE); 270392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } else { 271392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // Hide field when empty and optional value 272392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann final boolean couldHide = (!ContactsUtils.isGraphic(value) && field.optional); 273392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann final boolean willHide = (mHideOptional && couldHide); 274392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.setVisibility(willHide ? View.GONE : View.VISIBLE); 275392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann hidePossible = hidePossible || couldHide; 276392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 277392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 27863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mFields.addView(fieldView); 279392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 280392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 281392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // When hiding fields, place expandable 28212a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan setupExpansionView(hidePossible, mHideOptional); 28312a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan mExpansionView.setEnabled(!readOnly && isEnabled()); 284392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 285392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 2862591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan @Override 2872591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan public boolean isEmpty() { 2881b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan for (int i = 0; i < mFields.getChildCount(); i++) { 2891b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan EditText editText = (EditText) mFields.getChildAt(i); 2902591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan if (!TextUtils.isEmpty(editText.getText())) { 2912591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan return false; 2921b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan } 2931b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan } 2942591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan return true; 2951b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan } 2961b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan 297392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 298392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Returns true if the editor is currently configured to show optional fields. 299392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 300392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public boolean areOptionalFieldsVisible() { 301392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return !mHideOptional; 302392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 303392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 304392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public boolean hasShortAndLongForms() { 305392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return mHasShortAndLongForms; 306392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 307392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 308392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 309392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Populates the bound rectangle with the bounds of the last editor field inside this view. 310392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 311392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void acquireEditorBounds(Rect bounds) { 312392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (mFieldEditTexts != null) { 313392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann for (int i = mFieldEditTexts.length; --i >= 0;) { 314392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann EditText editText = mFieldEditTexts[i]; 315392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (editText.getVisibility() == View.VISIBLE) { 316392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann bounds.set(editText.getLeft(), editText.getTop(), editText.getRight(), 317392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann editText.getBottom()); 318392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return; 319392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 320392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 321392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 322392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 323392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 324392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 325392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Saves the visibility of the child EditTexts, and mHideOptional. 326392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 327392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 328392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected Parcelable onSaveInstanceState() { 329392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann Parcelable superState = super.onSaveInstanceState(); 330392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann SavedState ss = new SavedState(superState); 331392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 332392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann ss.mHideOptional = mHideOptional; 333392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 3345ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov final int numChildren = mFieldEditTexts == null ? 0 : mFieldEditTexts.length; 335392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann ss.mVisibilities = new int[numChildren]; 336392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann for (int i = 0; i < numChildren; i++) { 337392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann ss.mVisibilities[i] = mFieldEditTexts[i].getVisibility(); 338392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 339392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 340392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return ss; 341392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 342392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 343392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 344392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Restores the visibility of the child EditTexts, and mHideOptional. 345392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 346392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 347392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected void onRestoreInstanceState(Parcelable state) { 348392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann SavedState ss = (SavedState) state; 349392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super.onRestoreInstanceState(ss.getSuperState()); 350392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 351392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mHideOptional = ss.mHideOptional; 352392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 353392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann int numChildren = Math.min(mFieldEditTexts.length, ss.mVisibilities.length); 354392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann for (int i = 0; i < numChildren; i++) { 355392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mFieldEditTexts[i].setVisibility(ss.mVisibilities[i]); 356392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 357392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 358392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 359392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private static class SavedState extends BaseSavedState { 360392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public boolean mHideOptional; 361392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public int[] mVisibilities; 362392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 363392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann SavedState(Parcelable superState) { 364392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super(superState); 365392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 366392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 367392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private SavedState(Parcel in) { 368392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super(in); 369392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mVisibilities = new int[in.readInt()]; 370392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann in.readIntArray(mVisibilities); 371392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 372392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 373392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 374392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void writeToParcel(Parcel out, int flags) { 375392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super.writeToParcel(out, flags); 376392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann out.writeInt(mVisibilities.length); 377392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann out.writeIntArray(mVisibilities); 378392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 379392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 380cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann @SuppressWarnings({"unused", "hiding" }) 381392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public static final Parcelable.Creator<SavedState> CREATOR 382392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann = new Parcelable.Creator<SavedState>() { 383392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 384392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public SavedState createFromParcel(Parcel in) { 385392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return new SavedState(in); 386392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 387392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 388392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 389392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public SavedState[] newArray(int size) { 390392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return new SavedState[size]; 391392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 392392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann }; 393392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 394da5bf1cf60beef3de5e651a569fa544293683926Dave Santoro 3952293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan @Override 3962293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan public void clearAllFields() { 3972293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan if (mFieldEditTexts != null) { 3982293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan for (EditText fieldEditText : mFieldEditTexts) { 3992293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan // Update UI (which will trigger a state change through the {@link TextWatcher}) 4002293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan fieldEditText.setText(""); 4012293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan } 4022293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan } 4032293e55d550fbc9974d1185960715e59acb14a85Katherine Kuan } 404392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann} 405