diff options
author | Steve Kondik <shade@chemlab.org> | 2013-02-12 22:31:24 -0800 |
---|---|---|
committer | Steve Kondik <shade@chemlab.org> | 2013-02-12 22:31:24 -0800 |
commit | aff1242e5451db7edf4fc165895b656dea722593 (patch) | |
tree | 38e7a79da20cf168bc915745e26ce95f226627e3 /chips | |
parent | 8adb8f081f31911059a96bd426de01a4d3128e1a (diff) | |
parent | a918fec5a1dc028e9b04a71d0e37ee1bab6caa61 (diff) | |
download | android_frameworks_ex-mr1.1-staging.tar.gz android_frameworks_ex-mr1.1-staging.tar.bz2 android_frameworks_ex-mr1.1-staging.zip |
Merge tag 'android-4.2.2_r1' of https://android.googlesource.com/platform/frameworks/ex into 1.1cm-10.1.3-RC2cm-10.1.3-RC1cm-10.1.3cm-10.1.2cm-10.1.1cm-10.1.0-RC5cm-10.1.0-RC4cm-10.1.0-RC3cm-10.1.0-RC2cm-10.1.0-RC1cm-10.1.0cm-10.1-M3cm-10.1-M2mr1.1-stagingcm-10.1
Android 4.2.2 release 1
Diffstat (limited to 'chips')
-rw-r--r-- | chips/src/com/android/ex/chips/BaseRecipientAdapter.java | 15 | ||||
-rw-r--r-- | chips/src/com/android/ex/chips/RecipientEditTextView.java | 107 |
2 files changed, 98 insertions, 24 deletions
diff --git a/chips/src/com/android/ex/chips/BaseRecipientAdapter.java b/chips/src/com/android/ex/chips/BaseRecipientAdapter.java index c0cfa19..c981728 100644 --- a/chips/src/com/android/ex/chips/BaseRecipientAdapter.java +++ b/chips/src/com/android/ex/chips/BaseRecipientAdapter.java @@ -499,6 +499,8 @@ public abstract class BaseRecipientAdapter extends BaseAdapter implements Filter private final DelayedMessageHandler mDelayedMessageHandler = new DelayedMessageHandler(); + private EntriesUpdatedObserver mEntriesUpdatedObserver; + /** * Constructor for email queries. */ @@ -706,9 +708,14 @@ public abstract class BaseRecipientAdapter extends BaseAdapter implements Filter return entries; } + public void registerUpdateObserver(EntriesUpdatedObserver observer) { + mEntriesUpdatedObserver = observer; + } + /** Resets {@link #mEntries} and notify the event to its parent ListView. */ private void updateEntries(List<RecipientEntry> newEntries) { mEntries = newEntries; + mEntriesUpdatedObserver.onChanged(newEntries); notifyDataSetChanged(); } @@ -967,4 +974,12 @@ public abstract class BaseRecipientAdapter extends BaseAdapter implements Filter protected int getPhotoId() { return android.R.id.icon; } + + /** + * Interface called before the BaseRecipientAdapter updates recipient + * results in the popup window. + */ + protected interface EntriesUpdatedObserver { + public void onChanged(List<RecipientEntry> entries); + } } diff --git a/chips/src/com/android/ex/chips/RecipientEditTextView.java b/chips/src/com/android/ex/chips/RecipientEditTextView.java index 011b1e9..93ca4e8 100644 --- a/chips/src/com/android/ex/chips/RecipientEditTextView.java +++ b/chips/src/com/android/ex/chips/RecipientEditTextView.java @@ -54,6 +54,7 @@ import android.text.util.Rfc822Token; import android.text.util.Rfc822Tokenizer; import android.util.AttributeSet; import android.util.Log; +import android.util.TypedValue; import android.util.Patterns; import android.view.ActionMode; import android.view.ActionMode.Callback; @@ -72,6 +73,7 @@ import android.view.inputmethod.InputConnection; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.Button; +import android.widget.Filterable; import android.widget.ListAdapter; import android.widget.ListPopupWindow; import android.widget.ListView; @@ -86,8 +88,10 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * RecipientEditTextView is an auto complete text view for use with applications @@ -194,6 +198,15 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements private boolean mDragEnabled = false; + // This pattern comes from android.util.Patterns. It has been tweaked to handle a "1" before + // parens, so numbers such as "1 (425) 222-2342" match. + private static final Pattern PHONE_PATTERN + = Pattern.compile( // sdd = space, dot, or dash + "(\\+[0-9]+[\\- \\.]*)?" // +<digits><sdd>* + + "(1?[ ]*\\([0-9]+\\)[\\- \\.]*)?" // 1(<digits>)<sdd>* + + "([0-9][0-9\\- \\.][0-9\\- \\.]+[0-9])"); // <digit><digit|sdd>+<digit> + + private final Runnable mAddTextWatcher = new Runnable() { @Override public void run() { @@ -226,6 +239,10 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements private int mMaxLines; + private static int sExcessTopPadding = -1; + + private int mActionBarHeight; + public RecipientEditTextView(Context context, AttributeSet attrs) { super(context, attrs); setChipDimensions(context, attrs); @@ -389,6 +406,44 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements } } + private int getExcessTopPadding() { + if (sExcessTopPadding == -1) { + sExcessTopPadding = (int) (mChipHeight + mLineSpacingExtra); + } + return sExcessTopPadding; + } + + public <T extends ListAdapter & Filterable> void setAdapter(T adapter) { + super.setAdapter(adapter); + ((BaseRecipientAdapter) adapter) + .registerUpdateObserver(new BaseRecipientAdapter.EntriesUpdatedObserver() { + @Override + public void onChanged(List<RecipientEntry> entries) { + // Scroll the chips field to the top of the screen so + // that the user can see as many results as possible. + if (entries != null && entries.size() > 0) { + scrollBottomIntoView(); + } + } + }); + } + + private void scrollBottomIntoView() { + if (mScrollView != null && mShouldShrink) { + int[] location = new int[2]; + getLocationOnScreen(location); + int height = getHeight(); + int currentPos = location[1] + height; + // Desired position shows at least 1 line of chips below the action + // bar. We add excess padding to make sure this is always below other + // content. + int desiredPos = (int) mChipHeight + mActionBarHeight + getExcessTopPadding(); + if (currentPos > desiredPos) { + mScrollView.scrollBy(0, currentPos - desiredPos); + } + } + } + @Override public void performValidation() { // Do nothing. Chips handles its own validation. @@ -427,7 +482,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements int whatEnd = mTokenizer.findTokenEnd(text, start); // This token was already tokenized, so skip past the ending token. if (whatEnd < text.length() && text.charAt(whatEnd) == ',') { - whatEnd++; + whatEnd = movePastTerminators(whatEnd); } // In the middle of chip; treat this as an edit // and commit the whole token. @@ -701,6 +756,11 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements mInvalidChipBackground = r.getDrawable(R.drawable.chip_background_invalid); } mLineSpacingExtra = context.getResources().getDimension(R.dimen.line_spacing_extra); + TypedValue tv = new TypedValue(); + if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) { + mActionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, getResources() + .getDisplayMetrics()); + } a.recycle(); } @@ -897,8 +957,6 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements RecipientEntry entry = createTokenizedEntry(token); if (entry != null) { String destText = createAddressText(entry); - // Always leave a blank space at the end of a chip. - int textLength = destText.length() - 1; SpannableString chipText = new SpannableString(destText); int end = getSelectionEnd(); int start = mTokenizer != null ? mTokenizer.findTokenStart(getText(), end) : 0; @@ -913,12 +971,11 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements TextUtils.isEmpty(entry.getDisplayName()) || TextUtils.equals(entry.getDisplayName(), entry.getDestination())); - chipText.setSpan(chip, 0, textLength, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } } catch (NullPointerException e) { Log.e(TAG, e.getMessage(), e); } - editable.replace(tokenStart, tokenEnd, chipText); + editable.setSpan(chip, tokenStart, tokenEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // Add this chip to the list of entries "to replace" if (chip != null) { if (mTemporaryRecipients == null) { @@ -938,7 +995,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements return false; } - Matcher match = Patterns.PHONE.matcher(number); + Matcher match = PHONE_PATTERN.matcher(number); return match.matches(); } @@ -1117,6 +1174,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements int whatEnd = mTokenizer.findTokenEnd(getText(), start); // In the middle of chip; treat this as an edit // and commit the whole token. + whatEnd = movePastTerminators(whatEnd); if (whatEnd != getSelectionEnd()) { handleEdit(start, whatEnd); return true; @@ -1294,7 +1352,8 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements */ @Override protected void performFiltering(CharSequence text, int keyCode) { - if (enoughToFilter() && !isCompletedToken(text)) { + boolean isCompletedToken = isCompletedToken(text); + if (enoughToFilter() && !isCompletedToken) { int end = getSelectionEnd(); int start = mTokenizer.findTokenStart(text, end); // If this is a RecipientChip, don't filter @@ -1304,6 +1363,8 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements if (chips != null && chips.length > 0) { return; } + } else if (isCompletedToken) { + return; } super.performFiltering(text, keyCode); } @@ -1384,7 +1445,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements private void scrollLineIntoView(int line) { if (mScrollView != null) { - mScrollView.scrollBy(0, calculateOffsetFromBottom(line)); + mScrollView.smoothScrollBy(0, calculateOffsetFromBottom(line)); } } @@ -1880,11 +1941,17 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements if (shouldShowEditableText(currentChip)) { CharSequence text = currentChip.getValue(); Editable editable = getText(); - removeChip(currentChip); - editable.append(text); + Spannable spannable = getSpannable(); + int spanStart = spannable.getSpanStart(currentChip); + int spanEnd = spannable.getSpanEnd(currentChip); + spannable.removeSpan(currentChip); + editable.delete(spanStart, spanEnd); setCursorVisible(true); setSelection(editable.length()); - return new RecipientChip(null, RecipientEntry.constructFakeEntry((String) text), -1); + editable.append(text); + return constructChipSpan( + RecipientEntry.constructFakeEntry((String) text), + getSelectionStart(), true, false); } else if (currentChip.getContactId() == RecipientEntry.GENERATED_CONTACT) { int start = getChipStart(currentChip); int end = getChipEnd(currentChip); @@ -2176,7 +2243,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements public void onTextChanged(CharSequence s, int start, int before, int count) { // This is a delete; check to see if the insertion point is on a space // following a chip. - if (before > count) { + if (before - count == 1) { // If the item deleted is a space, and the thing before the // space is a chip, delete the entire span. int selStart = getSelectionStart(); @@ -2195,8 +2262,6 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements editable.delete(tokenStart, tokenEnd); getSpannable().removeSpan(repl[0]); } - } else if (count > before) { - scrollBottomIntoView(); } } @@ -2206,12 +2271,6 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements } } - private void scrollBottomIntoView() { - if (mScrollView != null) { - mScrollView.scrollBy(0, (int)(getLineCount() * mChipHeight)); - } - } - /** * Handles pasting a {@link ClipData} to this {@link RecipientEditTextView}. */ @@ -2391,11 +2450,11 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements end = oldText.getSpanEnd(chip); oldText.removeSpan(chip); RecipientChip replacement = replacements.get(i); - // Trim any whitespace, as we will already have - // it added if these are replacement chips. + // Make sure we always have just 1 space at the + // end to separate this chip from the next chip. SpannableString displayText = new SpannableString( - createAddressText(replacement.getEntry()).trim()); - displayText.setSpan(replacement, 0, displayText.length(), + createAddressText(replacement.getEntry()).trim() + " "); + displayText.setSpan(replacement, 0, displayText.length()-1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // Replace the old text we found with with the new display text, // which now may also contain the display name of the recipient. |