TextFieldsEditorView.java revision e598332967106e3db63b73c701f21902d169efef
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 com.android.contacts.ContactsUtils; 20392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.R; 21392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.model.AccountType.EditField; 22392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.model.DataKind; 23392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.model.EntityDelta; 24392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.model.EntityDelta.ValuesDelta; 251b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuanimport com.android.contacts.util.NameConverter; 26392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport com.android.contacts.util.PhoneNumberFormatter; 27392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 2826918da1650c1ff7b6f92deb978ab976525c811aJosh Gargusimport android.content.Context; 29392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.content.Entity; 30392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.graphics.Rect; 3163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuanimport android.graphics.Typeface; 320af02581eecabbe234e54364bdbbd65090518d7cKatherine Kuanimport android.os.Parcel; 3326918da1650c1ff7b6f92deb978ab976525c811aJosh Gargusimport android.os.Parcelable; 34392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 3512a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuanimport android.telephony.PhoneNumberFormattingTextWatcher; 36392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.text.Editable; 37da5bf1cf60beef3de5e651a569fa544293683926Dave Santoroimport android.text.InputType; 38e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport android.text.Spannable; 39e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport android.text.TextUtils; 40851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport android.text.TextWatcher; 41851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport android.text.style.StyleSpan; 42851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport android.util.AttributeSet; 43851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport android.view.Gravity; 44e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport android.view.View; 45e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport android.view.ViewGroup; 46392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport android.widget.EditText; 4763ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuanimport android.widget.ImageView; 48851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport android.widget.LinearLayout; 4963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan 50392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmannimport java.util.Map; 51392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 5226918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus/** 5326918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus * Simple editor that handles labels and any {@link EditField} defined for the 54392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * entry. Uses {@link ValuesDelta} to read any existing {@link Entity} values, 5563ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan * and to correctly write any changes values. 5612a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan */ 5712a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuanpublic class TextFieldsEditorView extends LabeledEditorView { 58392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private EditText[] mFieldEditTexts = null; 59392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private ViewGroup mFields = null; 601ebbd5bbe71814123b80df702b474bcd7196cbb7Katherine Kuan private View mExpansionViewContainer; 61392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private ImageView mExpansionView; 62392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private boolean mHideOptional = true; 63392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private boolean mHasShortAndLongForms; 64392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private int mMinFieldHeight; 65392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 66392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public TextFieldsEditorView(Context context) { 67392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super(context); 68392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 69392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 70392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public TextFieldsEditorView(Context context, AttributeSet attrs) { 71392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super(context, attrs); 72392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 73392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 7463ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan public TextFieldsEditorView(Context context, AttributeSet attrs, int defStyle) { 7591d8e892d549bbeba721cb434163a83bc99330a9Dmitri Plotnikov super(context, attrs, defStyle); 7663ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan } 7763ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan 7863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan /** {@inheritDoc} */ 7963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan @Override 8063ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan protected void onFinishInflate() { 8163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan super.onFinishInflate(); 821ebbd5bbe71814123b80df702b474bcd7196cbb7Katherine Kuan 831ebbd5bbe71814123b80df702b474bcd7196cbb7Katherine Kuan setDrawingCacheEnabled(true); 8463ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan setAlwaysDrawnWithCacheEnabled(true); 8512a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan 8612a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan mMinFieldHeight = mContext.getResources().getDimensionPixelSize( 8712a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan R.dimen.editor_min_line_item_height); 8863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mFields = (ViewGroup) findViewById(R.id.editors); 8963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mExpansionView = (ImageView) findViewById(R.id.expansion_view); 9063ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mExpansionViewContainer = findViewById(R.id.expansion_view_container); 9163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mExpansionViewContainer.setOnClickListener(new OnClickListener() { 9263ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan @Override 9363ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan public void onClick(View v) { 9463ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan // Save focus 9563ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan final View focusedChild = getFocusedChild(); 9663ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan final int focusedViewId = focusedChild == null ? -1 : focusedChild.getId(); 9763ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan 9863ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan // Reconfigure GUI 9963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan mHideOptional = !mHideOptional; 10063ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan onOptionalFieldVisibilityChange(); 10163ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan rebuildValues(); 10263ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan 10363ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan // Restore focus 104392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann View newFocusView = findViewById(focusedViewId); 10563ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan if (newFocusView == null || newFocusView.getVisibility() == GONE) { 106392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // find first visible child 10763ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan newFocusView = TextFieldsEditorView.this; 108392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 109392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann newFocusView.requestFocus(); 110392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 11126918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus }); 11226918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus } 11326918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus 11426918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus @Override 11526918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus public void setEnabled(boolean enabled) { 11626918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus super.setEnabled(enabled); 11726918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus 11826918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus if (mFieldEditTexts != null) { 11926918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus for (int index = 0; index < mFieldEditTexts.length; index++) { 12026918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus mFieldEditTexts[index].setEnabled(!isReadOnly() && enabled); 12126918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus } 12226918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus } 12326918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus mExpansionView.setEnabled(!isReadOnly() && enabled); 12426918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus } 12526918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus 12626918da1650c1ff7b6f92deb978ab976525c811aJosh Gargus /** 127392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Creates or removes the type/label button. Doesn't do anything if already correctly configured 128392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 129392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private void setupExpansionView(boolean shouldExist, boolean collapsed) { 130392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (shouldExist) { 131392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mExpansionViewContainer.setVisibility(View.VISIBLE); 13202bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mExpansionView.setImageResource(collapsed 133392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann ? R.drawable.ic_menu_expander_minimized_holo_light 134392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann : R.drawable.ic_menu_expander_maximized_holo_light); 13512a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan } else { 136392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mExpansionViewContainer.setVisibility(View.GONE); 137392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 138392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 139392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 140392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 14112a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan protected void requestFocusForFirstEditField() { 142392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (mFieldEditTexts != null && mFieldEditTexts.length != 0) { 14312a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan EditText firstField = null; 14412a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan boolean anyFieldHasFocus = false; 145915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann for (EditText editText : mFieldEditTexts) { 146915ffc5ae1d10a7ed06d5541fe81da023fa3228fDaniel Lehmann if (firstField == null && editText.getVisibility() == View.VISIBLE) { 14763ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan firstField = editText; 14812a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan } 149392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (editText.hasFocus()) { 150392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann anyFieldHasFocus = true; 151392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann break; 152392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 153392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 154392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (!anyFieldHasFocus && firstField != null) { 155392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann firstField.requestFocus(); 156392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 157392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 158392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 159392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 160392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 161392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void setValues(DataKind kind, ValuesDelta entry, EntityDelta state, boolean readOnly, 162392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann ViewIdGenerator vig) { 163392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super.setValues(kind, entry, state, readOnly, vig); 164392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // Remove edit texts that we currently have 165392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (mFieldEditTexts != null) { 166392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann for (EditText fieldEditText : mFieldEditTexts) { 167392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mFields.removeView(fieldEditText); 168392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 169392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 170392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann boolean hidePossible = false; 171392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 172392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann int fieldCount = kind.fieldList.size(); 173851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu mFieldEditTexts = new EditText[fieldCount]; 174392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann for (int index = 0; index < fieldCount; index++) { 175392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann final EditField field = kind.fieldList.get(index); 176392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann final EditText fieldView = new EditText(mContext); 177392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 178392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann field.isMultiLine() ? LayoutParams.WRAP_CONTENT : mMinFieldHeight)); 17963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan fieldView.setTextAppearance(getContext(), kind.textAppearanceResourceId); 180392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.setGravity(Gravity.TOP); 181392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mFieldEditTexts[index] = fieldView; 182392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.setId(vig.getId(state, kind, entry, index)); 183392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (field.titleRes > 0) { 184392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.setHint(field.titleRes); 185392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 186392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann int inputType = field.inputType; 187392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.setInputType(inputType); 188392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (inputType == InputType.TYPE_CLASS_PHONE) { 189392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann PhoneNumberFormatter.setPhoneNumberFormattingTextWatcher(mContext, fieldView); 1901ebbd5bbe71814123b80df702b474bcd7196cbb7Katherine Kuan } 1919db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan fieldView.setMinLines(field.minLines); 1929db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan 1939db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan // Read current value from state 1949db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan final String column = field.column; 1959db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan final String value = entry.getAsString(column); 1969db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan fieldView.setText(value); 1979db59fe67d9f2624120c718499a74eab7fea3c03Katherine Kuan 19850a27b70581b0191995969c63edd1f6a3db3d1b7Makoto Onuki // Show the delete button if we have a non-null value 199392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann setDeleteButtonVisible(value != null); 200392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 201392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // Prepare listener for writing changes 202392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.addTextChangedListener(new TextWatcher() { 203392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 204392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void afterTextChanged(Editable s) { 205392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // Trigger event for newly changed value 206392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann onFieldChanged(column, s.toString()); 207392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 208e598332967106e3db63b73c701f21902d169efefMakoto Onuki 209392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 210392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void beforeTextChanged(CharSequence s, int start, int count, int after) { 2110af02581eecabbe234e54364bdbbd65090518d7cKatherine Kuan } 2120af02581eecabbe234e54364bdbbd65090518d7cKatherine Kuan 2130af02581eecabbe234e54364bdbbd65090518d7cKatherine Kuan @Override 2140af02581eecabbe234e54364bdbbd65090518d7cKatherine Kuan public void onTextChanged(CharSequence s, int start, int before, int count) { 2150af02581eecabbe234e54364bdbbd65090518d7cKatherine Kuan } 216392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann }); 217392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 218392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.setEnabled(isEnabled() && !readOnly); 219392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 220392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (field.shortForm) { 2215e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan hidePossible = true; 2225e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan mHasShortAndLongForms = true; 2235e330ed98f1c2711b4cd3b375a1c0f76bedaf3e1Katherine Kuan fieldView.setVisibility(mHideOptional ? View.VISIBLE : View.GONE); 224392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } else if (field.longForm) { 225392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann hidePossible = true; 226392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mHasShortAndLongForms = true; 227392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.setVisibility(mHideOptional ? View.GONE : View.VISIBLE); 228392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } else { 229392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // Hide field when empty and optional value 230392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann final boolean couldHide = (!ContactsUtils.isGraphic(value) && field.optional); 231392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann final boolean willHide = (mHideOptional && couldHide); 232392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldView.setVisibility(willHide ? View.GONE : View.VISIBLE); 233392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann hidePossible = hidePossible || couldHide; 234392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 235392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 236392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mFields.addView(fieldView); 237392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 238392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 239392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // When hiding fields, place expandable 240392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann setupExpansionView(hidePossible, mHideOptional); 24102bb1252aa990813fa9e86ad75c458acc15e6801Dmitri Plotnikov mExpansionView.setEnabled(!readOnly && isEnabled()); 242392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 243392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 244392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 245392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public boolean isEmpty() { 246392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann for (int i = 0; i < mFields.getChildCount(); i++) { 247392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann EditText editText = (EditText) mFields.getChildAt(i); 248392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (!TextUtils.isEmpty(editText.getText())) { 249392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return false; 250392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 251392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 252392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return true; 253392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 254392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 255392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 256392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Returns true if the editor is currently configured to show optional fields. 257392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 258392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public boolean areOptionalFieldsVisible() { 25963ffb90935d8aec295e4a8f62af6c77dafe1899fKatherine Kuan return !mHideOptional; 260392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 261392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 262392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public boolean hasShortAndLongForms() { 26312a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan return mHasShortAndLongForms; 26412a93637e406ba7f3da4db8d53cd035c2c1d6e6eKatherine Kuan } 265392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 266392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 2672591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan * Populates the bound rectangle with the bounds of the last editor field inside this view. 2682591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan */ 2691b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan public void acquireEditorBounds(Rect bounds) { 2701b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan if (mFieldEditTexts != null) { 2712591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan for (int i = mFieldEditTexts.length; --i >= 0;) { 2722591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan EditText editText = mFieldEditTexts[i]; 2731b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan if (editText.getVisibility() == View.VISIBLE) { 2741b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan bounds.set(editText.getLeft(), editText.getTop(), editText.getRight(), 2752591436971bad3050c85929c8e0c5a8d48111f88Katherine Kuan editText.getBottom()); 2761b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan return; 2771b22073590c1801c3e6c7bde2f4636632a049f6cKatherine Kuan } 278392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 279392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 280392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 281392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 282392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 283392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Saves the visibility of the child EditTexts, and mHideOptional. 284392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 285392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 286392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected Parcelable onSaveInstanceState() { 287392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann Parcelable superState = super.onSaveInstanceState(); 288392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann SavedState ss = new SavedState(superState); 289392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 290392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann ss.mHideOptional = mHideOptional; 291392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 292392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann final int numChildren = mFieldEditTexts == null ? 0 : mFieldEditTexts.length; 293392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann ss.mVisibilities = new int[numChildren]; 294392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann for (int i = 0; i < numChildren; i++) { 295392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann ss.mVisibilities[i] = mFieldEditTexts[i].getVisibility(); 296392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 297392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 298392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return ss; 299392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 300392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 301392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann /** 302392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * Restores the visibility of the child EditTexts, and mHideOptional. 303392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann */ 304392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 305392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann protected void onRestoreInstanceState(Parcelable state) { 306392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann SavedState ss = (SavedState) state; 307392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super.onRestoreInstanceState(ss.getSuperState()); 308392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 309392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mHideOptional = ss.mHideOptional; 310392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 311392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann int numChildren = Math.min(mFieldEditTexts.length, ss.mVisibilities.length); 312392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann for (int i = 0; i < numChildren; i++) { 313392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mFieldEditTexts[i].setVisibility(ss.mVisibilities[i]); 314392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 3155ec40b04041818bc042c0671cb1a43b54f650e25Dmitri Plotnikov } 316392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 317392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private static class SavedState extends BaseSavedState { 318392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public boolean mHideOptional; 319392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public int[] mVisibilities; 320392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 321392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann SavedState(Parcelable superState) { 322392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super(superState); 323392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 324392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 325392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann private SavedState(Parcel in) { 326392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super(in); 327392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann mVisibilities = new int[in.readInt()]; 328392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann in.readIntArray(mVisibilities); 329392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 330392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 331392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 332392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void writeToParcel(Parcel out, int flags) { 333392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann super.writeToParcel(out, flags); 334392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann out.writeInt(mVisibilities.length); 335392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann out.writeIntArray(mVisibilities); 336392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 337392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 338392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @SuppressWarnings({"unused", "hiding" }) 339392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public static final Parcelable.Creator<SavedState> CREATOR 340392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann = new Parcelable.Creator<SavedState>() { 341392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 342392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public SavedState createFromParcel(Parcel in) { 343392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return new SavedState(in); 344392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 345392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 346392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 347392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public SavedState[] newArray(int size) { 348392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann return new SavedState[size]; 349392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 350392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann }; 351392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 352392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann 353392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann @Override 354392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann public void clearAllFields() { 355392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann if (mFieldEditTexts != null) { 356392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann for (EditText fieldEditText : mFieldEditTexts) { 357392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann // Update UI (which will trigger a state change through the {@link TextWatcher}) 358392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann fieldEditText.setText(""); 359392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 360392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann } 361cfb525b3f18d71d6cc5d4ef36d704b3ba9e9a6f3Daniel Lehmann } 362392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann} 363392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann