Search in sources :

Example 66 with ClickableSpan

use of android.text.style.ClickableSpan in project twicalico by moko256.

the class TwitterStringUtils method setLinkedSequenceTo.

@SuppressLint("StaticFieldLeak")
public static void setLinkedSequenceTo(Status item, TextView textView) {
    Context context = textView.getContext();
    String tweet = item.getText();
    if (GlobalApplication.clientType == Type.MASTODON) {
        Spanned html = Html.fromHtml(tweet);
        int length = html.length();
        // Trim unless \n\n made by fromHtml() after post
        if (length == 3 && item.getMediaEntities().length > 0 && html.charAt(0) == ".".charAt(0)) {
            // If post has media only, context of post from Mastodon is "."
            textView.setText("");
            return;
        } else if (length >= 2) {
            html = (Spanned) html.subSequence(0, length - 2);
        }
        SpannableStringBuilder builder = convertUrlSpanToCustomTabs(html, context);
        textView.setText(builder);
        List<Emoji> list = ((StatusCacheMap.CachedStatus) item).getEmojis();
        if (list != null) {
            Matcher matcher = containsEmoji.matcher(builder);
            boolean matches = matcher.matches();
            int imageSize;
            if (matches) {
                imageSize = (int) Math.floor((textView.getTextSize() * 1.15) * 2.0);
            } else {
                imageSize = (int) Math.floor(textView.getTextSize() * 1.15);
            }
            new AsyncTask<Void, Void, Map<String, Drawable>>() {

                @Override
                protected Map<String, Drawable> doInBackground(Void... params) {
                    Map<String, Drawable> map = new ArrayMap<>();
                    GlideRequests glideRequests = GlideApp.with(context);
                    for (Emoji emoji : list) {
                        try {
                            Drawable value = glideRequests.load(emoji.getUrl()).submit().get();
                            value.setBounds(0, 0, imageSize, imageSize);
                            map.put(emoji.getShortCode(), value);
                        } catch (InterruptedException | ExecutionException e) {
                            e.printStackTrace();
                        }
                    }
                    return map;
                }

                @Override
                protected void onPostExecute(Map<String, Drawable> map) {
                    if (TextUtils.equals(builder, textView.getText())) {
                        boolean found = matches || matcher.find();
                        while (found) {
                            String shortCode = matcher.group(1);
                            Drawable drawable = map.get(shortCode);
                            if (drawable != null) {
                                builder.setSpan(new ImageSpan(drawable), matcher.start(), matcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                            }
                            found = matcher.find();
                        }
                        textView.setText(builder);
                    }
                }
            }.execute();
        }
        return;
    }
    SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(tweet);
    for (SymbolEntity symbolEntity : item.getSymbolEntities()) {
        spannableStringBuilder.setSpan(new ClickableSpan() {

            @Override
            public void onClick(View view) {
                context.startActivity(SearchResultActivity.getIntent(context, symbolEntity.getText()));
            }
        }, tweet.offsetByCodePoints(0, symbolEntity.getStart()), tweet.offsetByCodePoints(0, symbolEntity.getEnd()), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
    }
    for (HashtagEntity hashtagEntity : item.getHashtagEntities()) {
        spannableStringBuilder.setSpan(new ClickableSpan() {

            @Override
            public void onClick(View view) {
                context.startActivity(SearchResultActivity.getIntent(context, "#" + hashtagEntity.getText()));
            }
        }, tweet.offsetByCodePoints(0, hashtagEntity.getStart()), tweet.offsetByCodePoints(0, hashtagEntity.getEnd()), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
    }
    for (UserMentionEntity userMentionEntity : item.getUserMentionEntities()) {
        spannableStringBuilder.setSpan(new ClickableSpan() {

            @Override
            public void onClick(View view) {
                context.startActivity(ShowUserActivity.getIntent(context, userMentionEntity.getScreenName()));
            }
        }, tweet.offsetByCodePoints(0, userMentionEntity.getStart()), tweet.offsetByCodePoints(0, userMentionEntity.getEnd()), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
    }
    boolean hasMedia = item.getMediaEntities().length > 0;
    List<URLEntity> urlEntities = new ArrayList<>(item.getURLEntities().length + (hasMedia ? 1 : 0));
    urlEntities.addAll(Arrays.asList(item.getURLEntities()));
    if (hasMedia) {
        urlEntities.add(item.getMediaEntities()[0]);
    }
    int tweetLength = tweet.codePointCount(0, tweet.length());
    int sp = 0;
    for (URLEntity entity : urlEntities) {
        String url = entity.getURL();
        String displayUrl = entity.getDisplayURL();
        int urlLength = url.codePointCount(0, url.length());
        int displayUrlLength = displayUrl.codePointCount(0, displayUrl.length());
        if (entity.getStart() <= tweetLength && entity.getEnd() <= tweetLength) {
            int dusp = displayUrlLength - urlLength;
            spannableStringBuilder.replace(tweet.offsetByCodePoints(0, entity.getStart()) + sp, tweet.offsetByCodePoints(0, entity.getEnd()) + sp, displayUrl);
            spannableStringBuilder.setSpan(new ClickableSpan() {

                @Override
                public void onClick(View view) {
                    AppCustomTabsKt.launchChromeCustomTabs(context, entity.getExpandedURL());
                }
            }, tweet.offsetByCodePoints(0, entity.getStart()) + sp, tweet.offsetByCodePoints(0, entity.getEnd()) + sp + dusp, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
            sp += dusp;
        }
    }
    textView.setText(spannableStringBuilder);
}
Also used : Matcher(java.util.regex.Matcher) GlideRequests(com.github.moko256.twicalico.GlideRequests) ArrayList(java.util.ArrayList) SymbolEntity(twitter4j.SymbolEntity) Emoji(com.github.moko256.twicalico.entity.Emoji) HashtagEntity(twitter4j.HashtagEntity) Context(android.content.Context) URLEntity(twitter4j.URLEntity) Drawable(android.graphics.drawable.Drawable) Spanned(android.text.Spanned) ClickableSpan(android.text.style.ClickableSpan) View(android.view.View) TextView(android.widget.TextView) SuppressLint(android.annotation.SuppressLint) UserMentionEntity(twitter4j.UserMentionEntity) ArrayMap(android.support.v4.util.ArrayMap) Map(java.util.Map) StatusCacheMap(com.github.moko256.twicalico.cacheMap.StatusCacheMap) SpannableStringBuilder(android.text.SpannableStringBuilder) ImageSpan(android.text.style.ImageSpan) SuppressLint(android.annotation.SuppressLint)

Aggregations

ClickableSpan (android.text.style.ClickableSpan)66 View (android.view.View)29 Layout (android.text.Layout)20 TextPaint (android.text.TextPaint)19 TextView (android.widget.TextView)19 SpannableString (android.text.SpannableString)15 Spannable (android.text.Spannable)14 Paint (android.graphics.Paint)13 SpannableStringBuilder (android.text.SpannableStringBuilder)11 Intent (android.content.Intent)7 InputMethodManager (android.view.inputmethod.InputMethodManager)7 Context (android.content.Context)5 CustomTabsIntent (android.support.customtabs.CustomTabsIntent)4 StyleSpan (android.text.style.StyleSpan)4 SuppressLint (android.annotation.SuppressLint)3 DialogInterface (android.content.DialogInterface)3 AlertDialog (android.support.v7.app.AlertDialog)3 ImageView (android.widget.ImageView)3 SpanInfo (org.chromium.ui.text.SpanApplier.SpanInfo)3 PendingIntent (android.app.PendingIntent)2