Example usage for android.text Spannable getSpanEnd

List of usage examples for android.text Spannable getSpanEnd

Introduction

In this page you can find the example usage for android.text Spannable getSpanEnd.

Prototype

public int getSpanEnd(Object tag);

Source Link

Document

Return the end of the range of text to which the specified markup object is attached, or -1 if the object is not attached.

Usage

From source file:im.zico.fancy.common.widget.HackyMovementMethod.java

@Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
    if (mGray == null) {
        mGray = new BackgroundColorSpan(
                ContextCompat.getColor(widget.getContext(), R.color.alpha_spannable_pressed));
    }/*from  ww w .  ja va2  s. co m*/

    mIsLinkHit = false;

    int action = event.getAction();

    if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        x -= widget.getTotalPaddingLeft();
        y -= widget.getTotalPaddingTop();
        x += widget.getScrollX();
        y += widget.getScrollY();

        int line = widget.getLayout().getLineForVertical(y);
        int offset = widget.getLayout().getOffsetForHorizontal(line, x);

        ClickableSpan[] spans = buffer.getSpans(offset, offset, ClickableSpan.class);

        if (spans.length != 0) {
            int start = buffer.getSpanStart(spans[0]);
            int end = buffer.getSpanEnd(spans[0]);
            mIsLinkHit = true;
            if (action == MotionEvent.ACTION_DOWN) {
                buffer.setSpan(mGray, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            } else if (action == MotionEvent.ACTION_UP) {
                spans[0].onClick(widget);
                buffer.removeSpan(mGray);
            }
            return true;
        }
    } else {
        buffer.removeSpan(mGray);
    }

    return Touch.onTouchEvent(widget, buffer, event);
}

From source file:android.melbournehistorymap.MapsActivity.java

/**
 * Manipulates the map once available./* w  w w.jav a 2 s .  com*/
 * This callback is triggered when the map is ready to be used.
 * This is where we can add markers or lines, add listeners or move the camera. In this case,
 * we just add a marker near Sydney, Australia.
 * If Google Play services is not installed on the device, the user will be prompted to install
 * it inside the SupportMapFragment. This method will only be triggered once the user has
 * installed Google Play services and returned to the app.
 */
@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    spinner = (ProgressBar) findViewById(R.id.prograssSpinner);
    //check if permission has been granted
    if (ActivityCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(this,
                    Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // Permission has already been granted
        return;
    }
    mMap.setMyLocationEnabled(true);
    mMap.getUiSettings().setZoomControlsEnabled(false);

    double lat;
    double lng;
    final int radius;
    int zoom;

    lat = Double.parseDouble(CurrLat);
    lng = Double.parseDouble(CurrLong);

    //build current location
    LatLng currentLocation = new LatLng(lat, lng);
    final LatLng realLocation = currentLocation;

    if (MELBOURNE.contains(currentLocation)) {
        mMap.getUiSettings().setMyLocationButtonEnabled(true);
        zoom = 17;
    } else {
        mMap.getUiSettings().setMyLocationButtonEnabled(false);
        lat = -37.81161508043379;
        lng = 144.9647320434451;
        zoom = 15;
        currentLocation = new LatLng(lat, lng);
    }

    mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLocation, 13));

    CameraPosition cameraPosition = new CameraPosition.Builder().target(currentLocation) // Sets the center of the map to location user
            .zoom(zoom) // Sets the zoom
            .bearing(0) // Sets the orientation of the camera to east
            .tilt(25) // Sets the tilt of the camera to 30 degrees
            .build(); // Creates a CameraPosition from the builder

    //Animate user to map location, if in Melbourne or outside of Melbourne bounds
    mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition),
            new GoogleMap.CancelableCallback() {
                @Override
                public void onFinish() {
                    updateMap();
                }

                @Override
                public void onCancel() {

                }
            });

    final TextView placeTitle = (TextView) findViewById(R.id.placeTitle);
    final TextView placeVic = (TextView) findViewById(R.id.placeVic);
    final TextView expPlaceTitle = (TextView) findViewById(R.id.expPlaceTitle);
    final TextView expPlaceVic = (TextView) findViewById(R.id.expPlaceVic);
    final TextView expPlaceDescription = (TextView) findViewById(R.id.placeDescription);
    final TextView wikiLicense = (TextView) findViewById(R.id.wikiLicense);
    final TextView expPlaceDistance = (TextView) findViewById(R.id.expPlaceDistance);
    final RelativeLayout tile = (RelativeLayout) findViewById(R.id.tile);
    final TextView fab = (TextView) findViewById(R.id.fab);
    final RelativeLayout distanceCont = (RelativeLayout) findViewById(R.id.distanceContainer);

    //        String license = "Text is available under the <a rel=\"license\" href=\"//en.wikipedia.org/wiki/Wikipedia:Text_of_Creative_Commons_Attribution-ShareAlike_3.0_Unported_License\">Creative Commons Attribution-ShareAlike License</a><a rel=\"license\" href=\"//creativecommons.org/licenses/by-sa/3.0/\" style=\"display:none;\"></a>;\n" +
    //                "additional terms may apply.";
    //        wikiLicense.setText(Html.fromHtml(license));
    //        wikiLicense.setMovementMethod(LinkMovementMethod.getInstance());
    //Marker click
    mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {

        @Override
        public boolean onMarkerClick(Marker marker) {
            String title = marker.getTitle();
            mMap.setPadding(0, 0, 0, 620);
            //set clicked marker to full opacity
            marker.setAlpha(1f);
            //set previous marker back to partial opac (if there is a prevMarker
            if (dirtyMarker == 1) {
                prevMarker.setAlpha(0.6f);
            }
            prevMarker = marker;
            dirtyMarker = 1;

            //Set DB helper
            DBHelper myDBHelper = new DBHelper(MapsActivity.this, WikiAPI.DB_NAME, null, WikiAPI.VERSION);

            //Only search for Wiki API requests if no place article returned.
            // **
            //Open DB as readable only.
            SQLiteDatabase db = myDBHelper.getReadableDatabase();
            //Set the query
            String dbFriendlyName = title.replace("\'", "\'\'");
            //Limit by 1 rows
            Cursor cursor = db.query(DBHelper.TABLE_NAME, null, "PLACE_NAME = '" + dbFriendlyName + "'", null,
                    null, null, null, "1");

            //move through each row returned in the query results
            while (cursor.moveToNext()) {

                String place_ID = cursor.getString(cursor.getColumnIndex("PLACE_ID"));
                String placeName = cursor.getString(cursor.getColumnIndex("PLACE_NAME"));
                String placeLoc = cursor.getString(cursor.getColumnIndex("PLACE_LOCATION"));
                String placeArticle = cursor.getString(cursor.getColumnIndex("ARTICLE"));
                String placeLat = cursor.getString(cursor.getColumnIndex("LAT"));
                String placeLng = cursor.getString(cursor.getColumnIndex("LNG"));

                //Get Google Place photos
                //Source: https://developers.google.com/places/android-api/photos
                final String placeId = place_ID;
                Places.GeoDataApi.getPlacePhotos(mGoogleApiClient, placeId)
                        .setResultCallback(new ResultCallback<PlacePhotoMetadataResult>() {
                            @Override
                            public void onResult(PlacePhotoMetadataResult photos) {
                                if (!photos.getStatus().isSuccess()) {
                                    return;
                                }
                                ImageView mImageView = (ImageView) findViewById(R.id.imageView);
                                ImageView mImageViewExpanded = (ImageView) findViewById(R.id.headerImage);
                                TextView txtAttribute = (TextView) findViewById(R.id.photoAttribute);
                                TextView expTxtAttribute = (TextView) findViewById(R.id.expPhotoAttribute);
                                PlacePhotoMetadataBuffer photoMetadataBuffer = photos.getPhotoMetadata();
                                if (photoMetadataBuffer.getCount() > 0) {
                                    // Display the first bitmap in an ImageView in the size of the view
                                    photoMetadataBuffer.get(0).getScaledPhoto(mGoogleApiClient, 600, 200)
                                            .setResultCallback(mDisplayPhotoResultCallback);
                                    //get photo attributions
                                    PlacePhotoMetadata photo = photoMetadataBuffer.get(0);
                                    CharSequence attribution = photo.getAttributions();
                                    if (attribution != null) {
                                        txtAttribute.setText(Html.fromHtml(String.valueOf(attribution)));
                                        expTxtAttribute.setText(Html.fromHtml(String.valueOf(attribution)));
                                        //http://stackoverflow.com/questions/4303160/how-can-i-make-links-in-fromhtml-clickable-android
                                        txtAttribute.setMovementMethod(LinkMovementMethod.getInstance());
                                        expTxtAttribute.setMovementMethod(LinkMovementMethod.getInstance());
                                    } else {
                                        txtAttribute.setText(" ");
                                        expTxtAttribute.setText(" ");
                                    }
                                } else {
                                    //Reset image view as no photo was identified
                                    mImageView.setImageResource(android.R.color.transparent);
                                    mImageViewExpanded.setImageResource(android.R.color.transparent);
                                    txtAttribute.setText(R.string.no_photos);
                                    expTxtAttribute.setText(R.string.no_photos);
                                }
                                photoMetadataBuffer.release();
                            }
                        });

                LatLng destLocation = new LatLng(Double.parseDouble(placeLat), Double.parseDouble(placeLng));
                //Work out distance between current location and place location
                //Source Library: https://github.com/googlemaps/android-maps-utils
                double distance = SphericalUtil.computeDistanceBetween(realLocation, destLocation);
                distance = Math.round(distance);
                distance = distance * 0.001;
                String strDistance = String.valueOf(distance);
                String[] arrDistance = strDistance.split("\\.");
                String unit = "km";
                if (arrDistance[0] == "0") {
                    unit = "m";
                    strDistance = arrDistance[1];
                } else {
                    strDistance = arrDistance[0] + "." + arrDistance[1].substring(0, 1);
                }

                placeArticle = placeArticle
                        .replaceAll("(<div class=\"thumb t).*\\s.*\\s.*\\s.*\\s.*\\s<\\/div>\\s<\\/div>", " ");

                Spannable noUnderlineMessage = new SpannableString(Html.fromHtml(placeArticle));

                //http://stackoverflow.com/questions/4096851/remove-underline-from-links-in-textview-android
                for (URLSpan u : noUnderlineMessage.getSpans(0, noUnderlineMessage.length(), URLSpan.class)) {
                    noUnderlineMessage.setSpan(new UnderlineSpan() {
                        public void updateDrawState(TextPaint tp) {
                            tp.setUnderlineText(false);
                        }
                    }, noUnderlineMessage.getSpanStart(u), noUnderlineMessage.getSpanEnd(u), 0);
                }

                placeArticle = String.valueOf(noUnderlineMessage);
                placeArticle = placeArticle.replaceAll("(\\[\\d\\])", " ");

                placeTitle.setText(placeName);
                expPlaceTitle.setText(placeName);
                placeVic.setText(placeLoc);
                expPlaceVic.setText(placeLoc);
                expPlaceDescription.setText(placeArticle);
                if (MELBOURNE.contains(realLocation)) {
                    expPlaceDistance.setText("Distance: " + strDistance + unit);
                    distanceCont.setVisibility(View.VISIBLE);
                }
            }

            tile.setVisibility(View.VISIBLE);
            fab.setVisibility(View.VISIBLE);
            //Set to true to not show default behaviour.
            return false;
        }
    });

    mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
        @Override
        public void onMapClick(LatLng latLng) {
            int viewStatus = tile.getVisibility();
            if (viewStatus == View.VISIBLE) {
                tile.setVisibility(View.INVISIBLE);
                fab.setVisibility(View.INVISIBLE);
                //set previous marker back to partial opac (if there is a prevMarker
                if (dirtyMarker == 1) {
                    prevMarker.setAlpha(0.6f);
                }
            }

            mMap.setPadding(0, 0, 0, 0);
        }
    });

    FloatingActionButton shareIcon = (FloatingActionButton) findViewById(R.id.shareIcon);
    shareIcon.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //https://www.google.com.au/maps/place/Federation+Square/@-37.8179789,144.9668635,15z

            //Build implicit intent by triggering a SENDTO action, which will capture applications that allow for messages
            //that allow for messages to be sent to a specific user with data
            //http://developer.android.com/reference/android/content/Intent.html#ACTION_SENDTO
            Intent intent = new Intent(Intent.ACTION_SEND);
            intent.setType("text/plain");
            //Build SMS
            String encodedPlace = "empty";
            try {
                encodedPlace = URLEncoder.encode(String.valueOf(expPlaceTitle.getText()), "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            intent.putExtra(Intent.EXTRA_TEXT, String.valueOf(expPlaceTitle.getText())
                    + " \n\nhttps://www.google.com.au/maps/place/" + encodedPlace);
            Intent sms = Intent.createChooser(intent, null);
            startActivity(sms);
        }
    });

    TextView fullArticle = (TextView) findViewById(R.id.fullArticle);
    fullArticle.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String wikiPlace = WikiPlace.getName(String.valueOf(expPlaceTitle.getText()));
            String url = "https://en.wikipedia.org/wiki/" + wikiPlace;

            Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            startActivity(browserIntent);
        }
    });
}

From source file:android.support.text.emoji.EmojiProcessor.java

/**
 * Checks a given CharSequence for emojis, and adds EmojiSpans if any emojis are found.
 * <p>/* ww  w  .j ava 2  s . c  o  m*/
 * <ul>
 * <li>If no emojis are found, {@code charSequence} given as the input is returned without
 * any changes. i.e. charSequence is a String, and no emojis are found, the same String is
 * returned.</li>
 * <li>If the given input is not a Spannable (such as String), and at least one emoji is found
 * a new {@link android.text.Spannable} instance is returned. </li>
 * <li>If the given input is a Spannable, the same instance is returned. </li>
 * </ul>
 *
 * @param charSequence CharSequence to add the EmojiSpans, cannot be {@code null}
 * @param start start index in the charSequence to look for emojis, should be greater than or
 *              equal to {@code 0}, also less than {@code charSequence.length()}
 * @param end end index in the charSequence to look for emojis, should be greater than or
 *            equal to {@code start} parameter, also less than {@code charSequence.length()}
 * @param maxEmojiCount maximum number of emojis in the {@code charSequence}, should be greater
 *                      than or equal to {@code 0}
 * @param replaceAll whether to replace all emoji with {@link EmojiSpan}s
 */
CharSequence process(@NonNull final CharSequence charSequence, @IntRange(from = 0) int start,
        @IntRange(from = 0) int end, @IntRange(from = 0) int maxEmojiCount, final boolean replaceAll) {
    final boolean isSpannableBuilder = charSequence instanceof SpannableBuilder;
    if (isSpannableBuilder) {
        ((SpannableBuilder) charSequence).beginBatchEdit();
    }

    try {
        Spannable spannable = null;
        // if it is a spannable already, use the same instance to add/remove EmojiSpans.
        // otherwise wait until the the first EmojiSpan found in order to change the result
        // into a Spannable.
        if (isSpannableBuilder || charSequence instanceof Spannable) {
            spannable = (Spannable) charSequence;
        }

        if (spannable != null) {
            final EmojiSpan[] spans = spannable.getSpans(start, end, EmojiSpan.class);
            if (spans != null && spans.length > 0) {
                // remove existing spans, and realign the start, end according to spans
                // if start or end is in the middle of an emoji they should be aligned
                final int length = spans.length;
                for (int index = 0; index < length; index++) {
                    final EmojiSpan span = spans[index];
                    final int spanStart = spannable.getSpanStart(span);
                    final int spanEnd = spannable.getSpanEnd(span);
                    // Remove span only when its spanStart is NOT equal to current end.
                    // During add operation an emoji at index 0 is added with 0-1 as start and
                    // end indices. Therefore if there are emoji spans at [0-1] and [1-2]
                    // and end is 1, the span between 0-1 should be deleted, not 1-2.
                    if (spanStart != end) {
                        spannable.removeSpan(span);
                    }
                    start = Math.min(spanStart, start);
                    end = Math.max(spanEnd, end);
                }
            }
        }

        if (start == end || start >= charSequence.length()) {
            return charSequence;
        }

        // calculate max number of emojis that can be added. since getSpans call is a relatively
        // expensive operation, do it only when maxEmojiCount is not unlimited.
        if (maxEmojiCount != EmojiCompat.EMOJI_COUNT_UNLIMITED && spannable != null) {
            maxEmojiCount -= spannable.getSpans(0, spannable.length(), EmojiSpan.class).length;
        }
        // add new ones
        int addedCount = 0;
        final ProcessorSm sm = new ProcessorSm(mMetadataRepo.getRootNode());

        int currentOffset = start;
        int codePoint = Character.codePointAt(charSequence, currentOffset);

        while (currentOffset < end && addedCount < maxEmojiCount) {
            final int action = sm.check(codePoint);

            switch (action) {
            case ACTION_ADVANCE_BOTH:
                start += Character.charCount(Character.codePointAt(charSequence, start));
                currentOffset = start;
                if (currentOffset < end) {
                    codePoint = Character.codePointAt(charSequence, currentOffset);
                }
                break;
            case ACTION_ADVANCE_END:
                currentOffset += Character.charCount(codePoint);
                if (currentOffset < end) {
                    codePoint = Character.codePointAt(charSequence, currentOffset);
                }
                break;
            case ACTION_FLUSH:
                if (replaceAll || !hasGlyph(charSequence, start, currentOffset, sm.getFlushMetadata())) {
                    if (spannable == null) {
                        spannable = new SpannableString(charSequence);
                    }
                    addEmoji(spannable, sm.getFlushMetadata(), start, currentOffset);
                    addedCount++;
                }
                start = currentOffset;
                break;
            }
        }

        // After the last codepoint is consumed the state machine might be in a state where it
        // identified an emoji before. i.e. abc[women-emoji] when the last codepoint is consumed
        // state machine is waiting to see if there is an emoji sequence (i.e. ZWJ).
        // Need to check if it is in such a state.
        if (sm.isInFlushableState() && addedCount < maxEmojiCount) {
            if (replaceAll || !hasGlyph(charSequence, start, currentOffset, sm.getCurrentMetadata())) {
                if (spannable == null) {
                    spannable = new SpannableString(charSequence);
                }
                addEmoji(spannable, sm.getCurrentMetadata(), start, currentOffset);
                addedCount++;
            }
        }
        return spannable == null ? charSequence : spannable;
    } finally {
        if (isSpannableBuilder) {
            ((SpannableBuilder) charSequence).endBatchEdit();
        }
    }
}

From source file:cgeo.geocaching.CacheDetailActivity.java

private static void fixTextColor(final Spannable spannable, final int backgroundColor) {
    final ForegroundColorSpan[] spans = spannable.getSpans(0, spannable.length(), ForegroundColorSpan.class);

    for (final ForegroundColorSpan span : spans) {
        if (ColorUtils.getContrastRatio(span.getForegroundColor(), backgroundColor) < CONTRAST_THRESHOLD) {
            final int start = spannable.getSpanStart(span);
            final int end = spannable.getSpanEnd(span);

            //  Assuming that backgroundColor can be either white or black,
            // this will set opposite background color (white for black and black for white)
            spannable.setSpan(new BackgroundColorSpan(backgroundColor ^ 0x00ffffff), start, end,
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }/*from w w w. j ava 2  s  .  c om*/
    }
}

From source file:com.hippo.nimingban.ui.ListActivity.java

private Spanned fixURLSpan(Spanned spanned) {
    Spannable spannable;
    if (spanned instanceof Spannable) {
        spannable = (Spannable) spanned;
    } else {/*  ww  w. ja va 2  s  .  c  om*/
        spannable = new SpannableString(spanned);
    }

    URLSpan[] urlSpans = spannable.getSpans(0, spanned.length(), URLSpan.class);
    if (urlSpans == null) {
        return spanned;
    }

    for (URLSpan urlSpan : urlSpans) {
        String url = urlSpan.getURL();
        if (TextUtils.isEmpty(url)) {
            spannable.removeSpan(urlSpan);
        }

        try {
            new URL(url);
        } catch (MalformedURLException e) {
            URL absoluteUrl;
            // It might be relative path
            try {
                // Use absolute url
                absoluteUrl = new URL(new URL(ACUrl.HOST), url);
                int start = spannable.getSpanStart(urlSpan);
                int end = spannable.getSpanEnd(urlSpan);
                spannable.removeSpan(urlSpan);
                spannable.setSpan(new URLSpan(absoluteUrl.toString()), start, end,
                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            } catch (MalformedURLException e1) {
                // Can't get url
                spannable.removeSpan(urlSpan);
            }
        }
    }

    return spannable;
}

From source file:com.tct.mail.browse.MessageHeaderView.java

private void stripUnderlines(TextView textView, Account account) {
    final Spannable spannable = (Spannable) textView.getText();
    final URLSpan[] urls = textView.getUrls();

    for (URLSpan span : urls) {
        final int start = spannable.getSpanStart(span);
        final int end = spannable.getSpanEnd(span);
        spannable.removeSpan(span);//  w  w w  . j  a  va  2s. c o  m
        //TS: rong-tang 2016-04-19 EMAIL BUGFIX-1951808 MOD_S
        span = new EmailAddressSpan(getContext(), account, span.getURL().substring(7), mContactInfoSource);
        ((EmailAddressSpan) span).setFragmentManager(mFragmentManager);
        //TS: rong-tang 2016-04-19 EMAIL BUGFIX-1951808 MOD_E
        spannable.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }
}

From source file:com.android.ex.chips.RecipientEditTextView.java

/**
 * Remove the chip and any text associated with it from the RecipientEditTextView.
 *
 * @param alsoNotifyAboutDataChanges/*www .j  a v a  2  s .c o  m*/
 */
// Visible for testing.
/* package */void removeChip(final DrawableRecipientChip chip, final boolean alsoNotifyAboutDataChanges) {
    if (!alsoNotifyAboutDataChanges)
        --mPreviousChipsCount;
    final Spannable spannable = getSpannable();
    final int spanStart = spannable.getSpanStart(chip);
    final int spanEnd = spannable.getSpanEnd(chip);
    final Editable text = getText();
    int toDelete = spanEnd;
    final boolean wasSelected = chip == mSelectedChip;
    // Clear that there is a selected chip before updating any text.
    if (wasSelected)
        mSelectedChip = null;
    // Always remove trailing spaces when removing a chip.
    while (toDelete >= 0 && toDelete < text.length() && text.charAt(toDelete) == ' ')
        toDelete++;
    spannable.removeSpan(chip);
    if (spanStart >= 0 && toDelete > 0)
        text.delete(spanStart, toDelete);
    if (wasSelected)
        clearSelectedChip();
}

From source file:com.android.ex.chips.RecipientEditTextView.java

/**
 * Show specified chip as selected. If the RecipientChip is just an email address, selecting the chip will take the
 * contents of the chip and place it at the end of the RecipientEditTextView for inline editing. If the
 * RecipientChip is a complete contact, then selecting the chip will change the background color of the chip, show
 * the delete icon, and a popup window with the address in use highlighted and any other alternate addresses for the
 * contact./*from  ww w.ja va  2s  .  c  o  m*/
 *
 * @param currentChip
 * Chip to select.
 * @return A RecipientChip in the selected state or null if the chip just contained an email address.
 */
private DrawableRecipientChip selectChip(final DrawableRecipientChip currentChip) {
    if (shouldShowEditableText(currentChip)) {
        final CharSequence text = currentChip.getValue();
        final Editable editable = getText();
        final Spannable spannable = getSpannable();
        final int spanStart = spannable.getSpanStart(currentChip);
        final int spanEnd = spannable.getSpanEnd(currentChip);
        spannable.removeSpan(currentChip);
        editable.delete(spanStart, spanEnd);
        setCursorVisible(true);
        setSelection(editable.length());
        editable.append(text);
        return constructChipSpan(RecipientEntry.constructFakeEntry((String) text, isValid(text.toString())),
                true, false);
    } else if (currentChip.getContactId() == RecipientEntry.GENERATED_CONTACT || currentChip.isGalContact()) {
        final int start = getChipStart(currentChip);
        final int end = getChipEnd(currentChip);
        getSpannable().removeSpan(currentChip);
        DrawableRecipientChip newChip;
        try {
            if (mNoChips)
                return null;
            newChip = constructChipSpan(currentChip.getEntry(), true, false);
        } catch (final NullPointerException e) {
            Log.e(TAG, e.getMessage(), e);
            return null;
        }
        final Editable editable = getText();
        QwertyKeyListener.markAsReplaced(editable, start, end, "");
        if (start == -1 || end == -1)
            Log.d(TAG, "The chip being selected no longer exists but should.");
        else
            editable.setSpan(newChip, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        newChip.setSelected(true);
        if (shouldShowEditableText(newChip))
            scrollLineIntoView(getLayout().getLineForOffset(getChipStart(newChip)));
        //showAddress(newChip,mAddressPopup,getWidth());
        setCursorVisible(false);
        return newChip;
    } else {
        final int start = getChipStart(currentChip);
        final int end = getChipEnd(currentChip);
        getSpannable().removeSpan(currentChip);
        DrawableRecipientChip newChip;
        try {
            newChip = constructChipSpan(currentChip.getEntry(), true, false);
        } catch (final NullPointerException e) {
            Log.e(TAG, e.getMessage(), e);
            return null;
        }
        final Editable editable = getText();
        QwertyKeyListener.markAsReplaced(editable, start, end, "");
        if (start == -1 || end == -1)
            Log.d(TAG, "The chip being selected no longer exists but should.");
        else
            editable.setSpan(newChip, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        newChip.setSelected(true);
        if (shouldShowEditableText(newChip))
            scrollLineIntoView(getLayout().getLineForOffset(getChipStart(newChip)));
        //showAlternates(newChip,mAlternatesPopup,getWidth());
        setCursorVisible(false);
        return newChip;
    }
}

From source file:com.android.ex.chips.RecipientEditTextView.java

/**
 * Remove any characters after the last valid chip.
 *//*ww w  .  j a  va2  s  .co  m*/
// Visible for testing.
/* package */void sanitizeEnd() {
    // Don't sanitize while we are waiting for pending chips to complete.
    if (mPendingChipsCount > 0)
        return;
    // Find the last chip; eliminate any commit characters after it.
    final DrawableRecipientChip[] chips = getSortedRecipients();
    final Spannable spannable = getSpannable();
    if (chips != null && chips.length > 0) {
        int end;
        mMoreChip = getMoreChip();
        if (mMoreChip != null)
            end = spannable.getSpanEnd(mMoreChip);
        else
            end = getSpannable().getSpanEnd(getLastChip());
        final Editable editable = getText();
        final int length = editable.length();
        if (length > end) {
            // See what characters occur after that and eliminate them.
            if (Log.isLoggable(TAG, Log.DEBUG))
                Log.d(TAG, "There were extra characters after the last tokenizable entry." + editable);
            editable.delete(end + 1, length);
        }
    }
}

From source file:com.android.ex.chips.RecipientEditTextView.java

/**
 * Replace the more chip, if it exists, with all of the recipient chips it had replaced when the
 * RecipientEditTextView gains focus./*w  w w. j  a v  a  2s .  co m*/
 */
// Visible for testing.
/* package */void removeMoreChip() {
    if (mMoreChip != null) {
        final Spannable span = getSpannable();
        span.removeSpan(mMoreChip);
        mMoreChip = null;
        // Re-add the spans that were removed.
        if (mRemovedSpans != null && mRemovedSpans.size() > 0) {
            // Recreate each removed span.
            final DrawableRecipientChip[] recipients = getSortedRecipients();
            // Start the search for tokens after the last currently visible
            // chip.
            if (recipients == null || recipients.length == 0)
                return;
            int end = span.getSpanEnd(recipients[recipients.length - 1]);
            final Editable editable = getText();
            for (final DrawableRecipientChip chip : mRemovedSpans) {
                int chipStart;
                int chipEnd;
                String token;
                // Need to find the location of the chip, again.
                token = (String) chip.getOriginalText();
                // As we find the matching recipient for the remove spans,
                // reduce the size of the string we need to search.
                // That way, if there are duplicates, we always find the correct
                // recipient.
                chipStart = editable.toString().indexOf(token, end);
                end = chipEnd = Math.min(editable.length(), chipStart + token.length());
                // Only set the span if we found a matching token.
                if (chipStart != -1)
                    editable.setSpan(chip, chipStart, chipEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            mRemovedSpans.clear();
        }
    }
}