Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 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 | |
Dmitri Plotnikov | 18ffaa2 | 2010-12-03 14:28:00 -0800 | [diff] [blame] | 17 | package com.android.contacts.editor; |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 18 | |
| 19 | import com.android.contacts.ContactsUtils; |
| 20 | import com.android.contacts.R; |
Dmitri Plotnikov | 4597c92 | 2010-11-15 13:03:06 -0800 | [diff] [blame] | 21 | import com.android.contacts.model.AccountType.EditField; |
Daisuke Miyakawa | 405671a | 2011-03-29 09:34:07 -0700 | [diff] [blame] | 22 | import com.android.contacts.model.DataKind; |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 23 | import com.android.contacts.model.EntityDelta; |
| 24 | import com.android.contacts.model.EntityDelta.ValuesDelta; |
Dave Santoro | da5bf1c | 2011-05-03 10:30:34 -0700 | [diff] [blame] | 25 | import com.android.contacts.util.NameConverter; |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 26 | |
| 27 | import android.content.Context; |
| 28 | import android.content.Entity; |
| 29 | import android.graphics.Rect; |
Dave Santoro | da5bf1c | 2011-05-03 10:30:34 -0700 | [diff] [blame] | 30 | import android.graphics.Typeface; |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 31 | import android.os.Parcel; |
| 32 | import android.os.Parcelable; |
Katherine Kuan | a2d4a96 | 2011-05-06 15:20:21 -0700 | [diff] [blame] | 33 | import android.provider.ContactsContract.CommonDataKinds.StructuredName; |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 34 | import android.telephony.PhoneNumberFormattingTextWatcher; |
| 35 | import android.text.Editable; |
| 36 | import android.text.InputType; |
Dave Santoro | da5bf1c | 2011-05-03 10:30:34 -0700 | [diff] [blame] | 37 | import android.text.Spannable; |
Katherine Kuan | 1b22073 | 2011-04-28 18:45:39 -0700 | [diff] [blame] | 38 | import android.text.TextUtils; |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 39 | import android.text.TextWatcher; |
Dave Santoro | da5bf1c | 2011-05-03 10:30:34 -0700 | [diff] [blame] | 40 | import android.text.style.StyleSpan; |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 41 | import android.util.AttributeSet; |
| 42 | import android.view.Gravity; |
| 43 | import android.view.View; |
Katherine Kuan | 63ffb90 | 2011-04-26 19:53:40 -0700 | [diff] [blame] | 44 | import android.view.ViewGroup; |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 45 | import android.widget.EditText; |
Katherine Kuan | 12a9363 | 2011-05-05 13:38:01 -0700 | [diff] [blame] | 46 | import android.widget.ImageView; |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 47 | import android.widget.LinearLayout; |
Dave Santoro | da5bf1c | 2011-05-03 10:30:34 -0700 | [diff] [blame] | 48 | |
| 49 | import java.util.Map; |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 50 | |
| 51 | /** |
Katherine Kuan | 63ffb90 | 2011-04-26 19:53:40 -0700 | [diff] [blame] | 52 | * Simple editor that handles labels and any {@link EditField} defined for the |
| 53 | * entry. Uses {@link ValuesDelta} to read any existing {@link Entity} values, |
| 54 | * and to correctly write any changes values. |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 55 | */ |
| 56 | public class TextFieldsEditorView extends LabeledEditorView { |
| 57 | private EditText[] mFieldEditTexts = null; |
Katherine Kuan | 63ffb90 | 2011-04-26 19:53:40 -0700 | [diff] [blame] | 58 | private ViewGroup mFields = null; |
Katherine Kuan | 12a9363 | 2011-05-05 13:38:01 -0700 | [diff] [blame] | 59 | private View mExpansionViewContainer; |
| 60 | private ImageView mExpansionView; |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 61 | private boolean mHideOptional = true; |
| 62 | private boolean mHasShortAndLongForms; |
Katherine Kuan | 1ebbd5b | 2011-08-05 14:39:34 -0700 | [diff] [blame^] | 63 | private int mMinFieldHeight; |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 64 | |
| 65 | public TextFieldsEditorView(Context context) { |
| 66 | super(context); |
| 67 | } |
| 68 | |
| 69 | public TextFieldsEditorView(Context context, AttributeSet attrs) { |
| 70 | super(context, attrs); |
| 71 | } |
| 72 | |
| 73 | public TextFieldsEditorView(Context context, AttributeSet attrs, int defStyle) { |
| 74 | super(context, attrs, defStyle); |
| 75 | } |
| 76 | |
Katherine Kuan | 63ffb90 | 2011-04-26 19:53:40 -0700 | [diff] [blame] | 77 | /** {@inheritDoc} */ |
| 78 | @Override |
| 79 | protected void onFinishInflate() { |
| 80 | super.onFinishInflate(); |
| 81 | |
| 82 | setDrawingCacheEnabled(true); |
| 83 | setAlwaysDrawnWithCacheEnabled(true); |
| 84 | |
Katherine Kuan | 1ebbd5b | 2011-08-05 14:39:34 -0700 | [diff] [blame^] | 85 | mMinFieldHeight = mContext.getResources().getDimensionPixelSize( |
| 86 | R.dimen.editor_min_line_item_height); |
Katherine Kuan | 63ffb90 | 2011-04-26 19:53:40 -0700 | [diff] [blame] | 87 | mFields = (ViewGroup) findViewById(R.id.editors); |
Katherine Kuan | 12a9363 | 2011-05-05 13:38:01 -0700 | [diff] [blame] | 88 | mExpansionView = (ImageView) findViewById(R.id.expansion_view); |
| 89 | mExpansionViewContainer = findViewById(R.id.expansion_view_container); |
| 90 | mExpansionViewContainer.setOnClickListener(new OnClickListener() { |
Katherine Kuan | 63ffb90 | 2011-04-26 19:53:40 -0700 | [diff] [blame] | 91 | @Override |
| 92 | public void onClick(View v) { |
| 93 | // Save focus |
| 94 | final View focusedChild = getFocusedChild(); |
| 95 | final int focusedViewId = focusedChild == null ? -1 : focusedChild.getId(); |
| 96 | |
| 97 | // Reconfigure GUI |
| 98 | mHideOptional = !mHideOptional; |
| 99 | onOptionalFieldVisibilityChange(); |
| 100 | rebuildValues(); |
| 101 | |
| 102 | // Restore focus |
| 103 | View newFocusView = findViewById(focusedViewId); |
| 104 | if (newFocusView == null || newFocusView.getVisibility() == GONE) { |
| 105 | // find first visible child |
| 106 | newFocusView = TextFieldsEditorView.this; |
| 107 | } |
| 108 | newFocusView.requestFocus(); |
| 109 | } |
| 110 | }); |
| 111 | } |
| 112 | |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 113 | @Override |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 114 | public void setEnabled(boolean enabled) { |
| 115 | super.setEnabled(enabled); |
| 116 | |
| 117 | if (mFieldEditTexts != null) { |
| 118 | for (int index = 0; index < mFieldEditTexts.length; index++) { |
Dmitri Plotnikov | 02bb125 | 2010-12-06 09:39:05 -0800 | [diff] [blame] | 119 | mFieldEditTexts[index].setEnabled(!isReadOnly() && enabled); |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 120 | } |
| 121 | } |
Katherine Kuan | 12a9363 | 2011-05-05 13:38:01 -0700 | [diff] [blame] | 122 | mExpansionView.setEnabled(!isReadOnly() && enabled); |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 123 | } |
| 124 | |
| 125 | /** |
| 126 | * Creates or removes the type/label button. Doesn't do anything if already correctly configured |
| 127 | */ |
Katherine Kuan | 12a9363 | 2011-05-05 13:38:01 -0700 | [diff] [blame] | 128 | private void setupExpansionView(boolean shouldExist, boolean collapsed) { |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 129 | if (shouldExist) { |
Katherine Kuan | 12a9363 | 2011-05-05 13:38:01 -0700 | [diff] [blame] | 130 | mExpansionViewContainer.setVisibility(View.VISIBLE); |
| 131 | mExpansionView.setImageResource(collapsed |
Daniel Lehmann | 915ffc5 | 2010-11-10 11:33:44 -0800 | [diff] [blame] | 132 | ? R.drawable.ic_menu_expander_minimized_holo_light |
| 133 | : R.drawable.ic_menu_expander_maximized_holo_light); |
Katherine Kuan | 63ffb90 | 2011-04-26 19:53:40 -0700 | [diff] [blame] | 134 | } else { |
Katherine Kuan | 12a9363 | 2011-05-05 13:38:01 -0700 | [diff] [blame] | 135 | mExpansionViewContainer.setVisibility(View.GONE); |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 136 | } |
| 137 | } |
| 138 | |
| 139 | @Override |
| 140 | protected void requestFocusForFirstEditField() { |
| 141 | if (mFieldEditTexts != null && mFieldEditTexts.length != 0) { |
| 142 | EditText firstField = null; |
| 143 | boolean anyFieldHasFocus = false; |
| 144 | for (EditText editText : mFieldEditTexts) { |
| 145 | if (firstField == null && editText.getVisibility() == View.VISIBLE) { |
| 146 | firstField = editText; |
| 147 | } |
| 148 | if (editText.hasFocus()) { |
| 149 | anyFieldHasFocus = true; |
| 150 | break; |
| 151 | } |
| 152 | } |
| 153 | if (!anyFieldHasFocus && firstField != null) { |
| 154 | firstField.requestFocus(); |
| 155 | } |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | @Override |
| 160 | public void setValues(DataKind kind, ValuesDelta entry, EntityDelta state, boolean readOnly, |
| 161 | ViewIdGenerator vig) { |
| 162 | super.setValues(kind, entry, state, readOnly, vig); |
| 163 | // Remove edit texts that we currently have |
| 164 | if (mFieldEditTexts != null) { |
| 165 | for (EditText fieldEditText : mFieldEditTexts) { |
Katherine Kuan | 63ffb90 | 2011-04-26 19:53:40 -0700 | [diff] [blame] | 166 | mFields.removeView(fieldEditText); |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 167 | } |
| 168 | } |
| 169 | boolean hidePossible = false; |
| 170 | |
| 171 | int fieldCount = kind.fieldList.size(); |
| 172 | mFieldEditTexts = new EditText[fieldCount]; |
| 173 | for (int index = 0; index < fieldCount; index++) { |
| 174 | final EditField field = kind.fieldList.get(index); |
| 175 | final EditText fieldView = new EditText(mContext); |
| 176 | fieldView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, |
Katherine Kuan | 1ebbd5b | 2011-08-05 14:39:34 -0700 | [diff] [blame^] | 177 | field.isMultiLine() ? LayoutParams.WRAP_CONTENT : mMinFieldHeight)); |
Katherine Kuan | a2d4a96 | 2011-05-06 15:20:21 -0700 | [diff] [blame] | 178 | fieldView.setTextAppearance(getContext(), kind.textAppearanceResourceId); |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 179 | fieldView.setGravity(Gravity.TOP); |
| 180 | mFieldEditTexts[index] = fieldView; |
| 181 | fieldView.setId(vig.getId(state, kind, entry, index)); |
| 182 | if (field.titleRes > 0) { |
| 183 | fieldView.setHint(field.titleRes); |
| 184 | } |
| 185 | int inputType = field.inputType; |
| 186 | fieldView.setInputType(inputType); |
Dave Santoro | da5bf1c | 2011-05-03 10:30:34 -0700 | [diff] [blame] | 187 | if (field.isFullName) { |
| 188 | fieldView.addTextChangedListener(new NameFormattingTextWatcher()); |
| 189 | } |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 190 | if (inputType == InputType.TYPE_CLASS_PHONE) { |
| 191 | fieldView.addTextChangedListener(new PhoneNumberFormattingTextWatcher( |
| 192 | ContactsUtils.getCurrentCountryIso(mContext))); |
| 193 | } |
| 194 | fieldView.setMinLines(field.minLines); |
| 195 | |
| 196 | // Read current value from state |
| 197 | final String column = field.column; |
| 198 | final String value = entry.getAsString(column); |
| 199 | fieldView.setText(value); |
| 200 | |
Katherine Kuan | 5e330ed | 2011-07-15 15:06:06 -0700 | [diff] [blame] | 201 | // Show the delete button if we have a non-null value |
| 202 | setDeleteButtonVisible(value != null); |
| 203 | |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 204 | // Prepare listener for writing changes |
| 205 | fieldView.addTextChangedListener(new TextWatcher() { |
| 206 | @Override |
| 207 | public void afterTextChanged(Editable s) { |
| 208 | // Trigger event for newly changed value |
| 209 | onFieldChanged(column, s.toString()); |
| 210 | } |
| 211 | |
| 212 | @Override |
| 213 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { |
| 214 | } |
| 215 | |
| 216 | @Override |
| 217 | public void onTextChanged(CharSequence s, int start, int before, int count) { |
| 218 | } |
| 219 | }); |
| 220 | |
Dmitri Plotnikov | 02bb125 | 2010-12-06 09:39:05 -0800 | [diff] [blame] | 221 | fieldView.setEnabled(isEnabled() && !readOnly); |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 222 | |
| 223 | if (field.shortForm) { |
| 224 | hidePossible = true; |
| 225 | mHasShortAndLongForms = true; |
| 226 | fieldView.setVisibility(mHideOptional ? View.VISIBLE : View.GONE); |
| 227 | } else if (field.longForm) { |
| 228 | hidePossible = true; |
| 229 | mHasShortAndLongForms = true; |
| 230 | fieldView.setVisibility(mHideOptional ? View.GONE : View.VISIBLE); |
| 231 | } else { |
| 232 | // Hide field when empty and optional value |
| 233 | final boolean couldHide = (!ContactsUtils.isGraphic(value) && field.optional); |
| 234 | final boolean willHide = (mHideOptional && couldHide); |
| 235 | fieldView.setVisibility(willHide ? View.GONE : View.VISIBLE); |
| 236 | hidePossible = hidePossible || couldHide; |
| 237 | } |
| 238 | |
Katherine Kuan | 63ffb90 | 2011-04-26 19:53:40 -0700 | [diff] [blame] | 239 | mFields.addView(fieldView); |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 240 | } |
| 241 | |
| 242 | // When hiding fields, place expandable |
Katherine Kuan | 12a9363 | 2011-05-05 13:38:01 -0700 | [diff] [blame] | 243 | setupExpansionView(hidePossible, mHideOptional); |
| 244 | mExpansionView.setEnabled(!readOnly && isEnabled()); |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 245 | } |
| 246 | |
Katherine Kuan | 2591436 | 2011-04-29 19:42:01 -0700 | [diff] [blame] | 247 | @Override |
| 248 | public boolean isEmpty() { |
Katherine Kuan | 1b22073 | 2011-04-28 18:45:39 -0700 | [diff] [blame] | 249 | for (int i = 0; i < mFields.getChildCount(); i++) { |
| 250 | EditText editText = (EditText) mFields.getChildAt(i); |
Katherine Kuan | 2591436 | 2011-04-29 19:42:01 -0700 | [diff] [blame] | 251 | if (!TextUtils.isEmpty(editText.getText())) { |
| 252 | return false; |
Katherine Kuan | 1b22073 | 2011-04-28 18:45:39 -0700 | [diff] [blame] | 253 | } |
| 254 | } |
Katherine Kuan | 2591436 | 2011-04-29 19:42:01 -0700 | [diff] [blame] | 255 | return true; |
Katherine Kuan | 1b22073 | 2011-04-28 18:45:39 -0700 | [diff] [blame] | 256 | } |
| 257 | |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 258 | /** |
| 259 | * Returns true if the editor is currently configured to show optional fields. |
| 260 | */ |
| 261 | public boolean areOptionalFieldsVisible() { |
| 262 | return !mHideOptional; |
| 263 | } |
| 264 | |
| 265 | public boolean hasShortAndLongForms() { |
| 266 | return mHasShortAndLongForms; |
| 267 | } |
| 268 | |
| 269 | /** |
| 270 | * Populates the bound rectangle with the bounds of the last editor field inside this view. |
| 271 | */ |
| 272 | public void acquireEditorBounds(Rect bounds) { |
| 273 | if (mFieldEditTexts != null) { |
| 274 | for (int i = mFieldEditTexts.length; --i >= 0;) { |
| 275 | EditText editText = mFieldEditTexts[i]; |
| 276 | if (editText.getVisibility() == View.VISIBLE) { |
| 277 | bounds.set(editText.getLeft(), editText.getTop(), editText.getRight(), |
| 278 | editText.getBottom()); |
| 279 | return; |
| 280 | } |
| 281 | } |
| 282 | } |
| 283 | } |
| 284 | |
| 285 | /** |
| 286 | * Saves the visibility of the child EditTexts, and mHideOptional. |
| 287 | */ |
| 288 | @Override |
| 289 | protected Parcelable onSaveInstanceState() { |
| 290 | Parcelable superState = super.onSaveInstanceState(); |
| 291 | SavedState ss = new SavedState(superState); |
| 292 | |
| 293 | ss.mHideOptional = mHideOptional; |
| 294 | |
Dmitri Plotnikov | 5ec40b0 | 2011-03-01 18:36:16 -0800 | [diff] [blame] | 295 | final int numChildren = mFieldEditTexts == null ? 0 : mFieldEditTexts.length; |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 296 | ss.mVisibilities = new int[numChildren]; |
| 297 | for (int i = 0; i < numChildren; i++) { |
| 298 | ss.mVisibilities[i] = mFieldEditTexts[i].getVisibility(); |
| 299 | } |
| 300 | |
| 301 | return ss; |
| 302 | } |
| 303 | |
| 304 | /** |
| 305 | * Restores the visibility of the child EditTexts, and mHideOptional. |
| 306 | */ |
| 307 | @Override |
| 308 | protected void onRestoreInstanceState(Parcelable state) { |
| 309 | SavedState ss = (SavedState) state; |
| 310 | super.onRestoreInstanceState(ss.getSuperState()); |
| 311 | |
| 312 | mHideOptional = ss.mHideOptional; |
| 313 | |
| 314 | int numChildren = Math.min(mFieldEditTexts.length, ss.mVisibilities.length); |
| 315 | for (int i = 0; i < numChildren; i++) { |
| 316 | mFieldEditTexts[i].setVisibility(ss.mVisibilities[i]); |
| 317 | } |
| 318 | } |
| 319 | |
| 320 | private static class SavedState extends BaseSavedState { |
| 321 | public boolean mHideOptional; |
| 322 | public int[] mVisibilities; |
| 323 | |
| 324 | SavedState(Parcelable superState) { |
| 325 | super(superState); |
| 326 | } |
| 327 | |
| 328 | private SavedState(Parcel in) { |
| 329 | super(in); |
| 330 | mVisibilities = new int[in.readInt()]; |
| 331 | in.readIntArray(mVisibilities); |
| 332 | } |
| 333 | |
| 334 | @Override |
| 335 | public void writeToParcel(Parcel out, int flags) { |
| 336 | super.writeToParcel(out, flags); |
| 337 | out.writeInt(mVisibilities.length); |
| 338 | out.writeIntArray(mVisibilities); |
| 339 | } |
| 340 | |
Daniel Lehmann | cfb525b | 2010-11-02 19:24:54 -0700 | [diff] [blame] | 341 | @SuppressWarnings({"unused", "hiding" }) |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 342 | public static final Parcelable.Creator<SavedState> CREATOR |
| 343 | = new Parcelable.Creator<SavedState>() { |
| 344 | @Override |
| 345 | public SavedState createFromParcel(Parcel in) { |
| 346 | return new SavedState(in); |
| 347 | } |
| 348 | |
| 349 | @Override |
| 350 | public SavedState[] newArray(int size) { |
| 351 | return new SavedState[size]; |
| 352 | } |
| 353 | }; |
| 354 | } |
Dave Santoro | da5bf1c | 2011-05-03 10:30:34 -0700 | [diff] [blame] | 355 | |
| 356 | private class NameFormattingTextWatcher implements TextWatcher { |
| 357 | |
| 358 | |
| 359 | @Override |
| 360 | public void beforeTextChanged(CharSequence s, int start, int count, int after) {} |
| 361 | |
| 362 | @Override |
| 363 | public void onTextChanged(CharSequence s, int start, int before, int count) {} |
| 364 | |
| 365 | @Override |
| 366 | public void afterTextChanged(Editable s) { |
| 367 | String displayName = s.toString(); |
| 368 | Map<String, String> structuredName = NameConverter.displayNameToStructuredName( |
| 369 | getContext(), displayName); |
| 370 | String givenName = structuredName.get(StructuredName.GIVEN_NAME); |
| 371 | if (!TextUtils.isEmpty(givenName)) { |
| 372 | int spanStart = -1; |
| 373 | int spanEnd = -1; |
| 374 | if (displayName.startsWith(givenName + " ")) { |
| 375 | spanStart = 0; |
| 376 | spanEnd = givenName.length(); |
| 377 | } else { |
| 378 | spanStart = displayName.lastIndexOf(" " + givenName); |
| 379 | if (spanStart > -1) { |
| 380 | spanStart++; |
| 381 | spanEnd = spanStart + givenName.length(); |
| 382 | } |
| 383 | } |
| 384 | |
| 385 | // If the requested range is already bolded, don't make any changes. |
| 386 | if (spanStart > -1) { |
| 387 | StyleSpan[] existingSpans = s.getSpans(0, s.length(), StyleSpan.class); |
| 388 | for (StyleSpan span : existingSpans) { |
| 389 | if (span.getStyle() == Typeface.BOLD |
| 390 | && s.getSpanStart(span.getUnderlying()) == spanStart |
| 391 | && s.getSpanEnd(span.getUnderlying()) == spanEnd) { |
| 392 | // Nothing to do - the correct portion is already bolded. |
| 393 | return; |
| 394 | } |
| 395 | } |
| 396 | |
| 397 | // Clear any existing bold style spans. |
| 398 | for (StyleSpan span : existingSpans) { |
| 399 | if (span.getStyle() == Typeface.BOLD) { |
| 400 | s.removeSpan(span); |
| 401 | } |
| 402 | } |
| 403 | |
| 404 | // Set the new bold span. |
| 405 | s.setSpan(new StyleSpan(Typeface.BOLD), spanStart, spanEnd, |
| 406 | Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); |
| 407 | } |
| 408 | } |
| 409 | } |
| 410 | } |
Katherine Kuan | 2293e55 | 2011-07-21 20:25:44 -0700 | [diff] [blame] | 411 | |
| 412 | @Override |
| 413 | public void clearAllFields() { |
| 414 | if (mFieldEditTexts != null) { |
| 415 | for (EditText fieldEditText : mFieldEditTexts) { |
| 416 | // Update UI (which will trigger a state change through the {@link TextWatcher}) |
| 417 | fieldEditText.setText(""); |
| 418 | } |
| 419 | } |
| 420 | } |
Daniel Lehmann | 392ccec | 2010-11-01 20:50:03 -0700 | [diff] [blame] | 421 | } |