/** * Create Span for matches in ParcelableSpan's. Note that this will highlight the full matched pattern * (including optionals) if no group parameters are given. * * @param editable Text editable * @param pattern The pattern to match * @param creator A ParcelableSpanCreator for ParcelableSpan * @param groupsToMatch (optional) groups to be matched, indexes start at 1. */ protected void createSpanForMatches(final Editable editable, final Pattern pattern, final ParcelableSpanCreator creator, int... groupsToMatch) { if (groupsToMatch == null || groupsToMatch.length < 1) { groupsToMatch = new int[]{0}; } int i = 0; for (Matcher m = pattern.matcher(editable); m.find(); i++) { ParcelableSpan span = creator.create(m, i); if (span != null) { for (int g : groupsToMatch) { if (g == 0 || g <= m.groupCount()) { editable.setSpan(span, m.start(g), m.end(g), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } } } } }
/** * Returns a {@link Spannable} which attaches the specified {@link ParcelableSpan} to the given * substring * * @param text Text * @param span array of {@link ParcelableSpan} that will be applied * @param spanTexts array of substrings that will be modified * * @return {@link Spannable} */ @NonNull public Spannable createSpan(String text, ParcelableSpan[] span, String... spanTexts) { Spannable result = new SpannableString(text); if (span != null && spanTexts != null && span.length <= spanTexts.length) { for (int i = 0; i < span.length; i++) { String spanText = spanTexts[i]; int spanTextStart = text.indexOf(spanText); if (spanTextStart >= 0 && spanTextStart < text.length() && spanText.length() <= text.length()) { result.setSpan(span[i], spanTextStart, (spanTextStart + spanText.length()), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } } } return result; }
@NonNull public Spannable createMultiSpan(String text, ParcelableSpan[] span, String... spanTexts) { Spannable result = new SpannableString(text); for (ParcelableSpan parcelableSpan : span) { for (String spanText : spanTexts) { int spanTextStart = text.indexOf(spanText); if (spanTextStart >= 0 && spanTextStart < text.length() && spanText.length() <= text.length()) { result.setSpan(parcelableSpan, spanTextStart, (spanTextStart + spanText.length()), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } } } return result; }
@Override public void setPost(TimelineUser card, int position) { followers.setText(spannableFactory.createSpan(itemView.getContext() .getString(R.string.timeline_button_followers, card.getFollowers()), new ParcelableSpan[] { new ForegroundColorSpan(Color.BLACK) }, String.valueOf(card.getFollowers()), String.valueOf(card.getFollowers()))); following.setText(spannableFactory.createSpan(itemView.getContext() .getString(R.string.timeline_button_followed, card.getFollowing()), new ParcelableSpan[] { new ForegroundColorSpan(Color.BLACK) }, String.valueOf(card.getFollowing()), String.valueOf(card.getFollowing()))); followers.setOnClickListener(click -> cardTouchEventPublishSubject.onNext( new TimelineStatsTouchEvent(card, TimelineStatsTouchEvent.ButtonClicked.FOLLOWERS, CardTouchEvent.Type.TIMELINE_STATS, position))); following.setOnClickListener(click -> cardTouchEventPublishSubject.onNext( new TimelineStatsTouchEvent(card, TimelineStatsTouchEvent.ButtonClicked.FOLLOWING, CardTouchEvent.Type.TIMELINE_STATS, position))); }
public ParcelableSpan create(Matcher m, int iM) { final char[] charSequence = extractMatchingRange(m); Float proportion = calculateProportionBasedOnHeaderType(charSequence); Float size = calculateAdjustedSize(proportion); return new TextAppearanceSpan(_highlighter._fontType, Typeface.BOLD, (int) size.byteValue(), ColorStateList.valueOf(_color), null); }
private Spannable createSpan(String text, ParcelableSpan span, String[] spanTexts) { final Spannable result = new SpannableString(text); for (String spanText : spanTexts) { int spanTextStart = text.indexOf(spanText); if (spanTextStart >= 0 && spanTextStart < text.length() && spanText.length() <= text.length()) { result.setSpan(span, spanTextStart, (spanTextStart + spanText.length()), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } } return result; }
CharSequence getFollowersText(Context context) { return spannableFactory.createSpan(context.getString(R.string.timeline_button_followers, getPojo().getData() .getFollowers()), new ParcelableSpan[] { new ForegroundColorSpan(Color.BLACK) }, String.valueOf(getPojo().getData() .getFollowers()), String.valueOf(getPojo().getData() .getFollowers())); }
CharSequence getFollowingText(Context context) { return spannableFactory.createSpan(context.getString(R.string.timeline_button_followed, getPojo().getData() .getFollowing()), new ParcelableSpan[] { new ForegroundColorSpan(Color.BLACK) }, String.valueOf(getPojo().getData() .getFollowing()), String.valueOf(getPojo().getData() .getFollowing())); }
private void showAppsCount(long appsCount, ParcelableSpan[] textStyle, boolean showApps, long storeName) { if (showApps) { appsCountTv.setVisibility(View.VISIBLE); String count = AptoideUtils.StringU.withSuffix(appsCount); String followingText = String.format(getContext().getString(R.string.storehometab_short_apps), count); appsCountTv.setText(spannableFactory.createMultiSpan(followingText, textStyle, count)); appsCountTv.setOnClickListener(v -> navigateToAppsListScreen(storeName)); } else { appsCountTv.setVisibility(View.GONE); } }
/** * This is used to remove all style-impacting spans from text before new * extracted text is being replaced into it, so that we don't have any * lingering spans applied during the replace. */ static void removeParcelableSpans(Spannable spannable, int start, int end) { Object[] spans = spannable.getSpans(start, end, ParcelableSpan.class); int i = spans.length; while (i > 0) { i--; spannable.removeSpan(spans[i]); } }
public static void clear(final Editable editable) { final int end = editable.length() - 1; for (Class<? extends ParcelableSpan> clazz : SPAN_CLASSES) { for (ParcelableSpan span : editable.getSpans(0, end, clazz)) { editable.removeSpan(span); } } }
private static ParcelableSpan createSpanForStyle(ImStyleParser.Style style) { switch (style.getKeyword()) { case "*": return new StyleSpan(Typeface.BOLD); case "_": return new StyleSpan(Typeface.ITALIC); case "~": return new StrikethroughSpan(); case "`": case "```": return new TypefaceSpan("monospace"); default: throw new AssertionError("Unknown Style"); } }
public ParcelableSpan create(Matcher m) { final char[] charSequence = extractMatchingRange(m); Float proportion = calculateProportionBasedOnHeaderType(charSequence); Float size = calculateAdjustedSize(proportion); return new TextAppearanceSpan(highlighter.fontType, Typeface.BOLD, (int) size.byteValue(), ColorStateList.valueOf(color), null); }
private void createMonospaceSpanForMatches(Editable e, Pattern pattern) { createSpanForMatches(e, pattern, new SpanCreator() { @Override public ParcelableSpan create(Matcher m) { return new TypefaceSpan("monospace"); } }); }
private void createSpanWithStrikeThroughForMatches(Editable e, Pattern pattern) { createSpanForMatches(e, pattern, new SpanCreator() { @Override public ParcelableSpan create(Matcher m) { return new StrikethroughSpan(); } }); }
private void createStyleSpanForMatches(final Editable e, final Pattern pattern, final int style) { createSpanForMatches(e, pattern, new SpanCreator() { @Override public ParcelableSpan create(Matcher m) { return new StyleSpan(style); } }); }
private void createColorSpanForMatches(final Editable e, final Pattern pattern, final int color) { createSpanForMatches(e, pattern, new SpanCreator() { @Override public ParcelableSpan create(Matcher m) { return new ForegroundColorSpan(color); } }); }
@Override public void bindView(GridStoreMetaDisplayable displayable) { badgeDialogFactory = displayable.getBadgeDialogFactory(); accountManager = ((AptoideApplication) getContext().getApplicationContext()).getAccountManager(); final BodyInterceptor<BaseBody> bodyInterceptor = ((AptoideApplication) getContext().getApplicationContext()).getAccountSettingsBodyInterceptorPoolV7(); final OkHttpClient httpClient = ((AptoideApplication) getContext().getApplicationContext()).getDefaultClient(); storeAccessor = AccessorFactory.getAccessorFor( ((AptoideApplication) getContext().getApplicationContext()).getDatabase(), Store.class); storeUtilsProxy = new StoreUtilsProxy(accountManager, bodyInterceptor, new StoreCredentialsProviderImpl(storeAccessor), AccessorFactory.getAccessorFor( ((AptoideApplication) getContext().getApplicationContext() .getApplicationContext()).getDatabase(), Store.class), httpClient, WebService.getDefaultConverter(), ((AptoideApplication) getContext().getApplicationContext()).getTokenInvalidator(), ((AptoideApplication) getContext().getApplicationContext()).getDefaultSharedPreferences()); spannableFactory = new SpannableFactory(); storeCredentialsProvider = new StoreCredentialsProviderImpl(storeAccessor); FragmentNavigator fragmentNavigator = getFragmentNavigator(); Resources resources = getContext().getResources(); followersCountTv.setOnClickListener(v -> { navigateToFollowersScreen(displayable, resources, fragmentNavigator); }); followingCountTv.setOnClickListener( v -> navigateToFollowingScreen(displayable, fragmentNavigator, resources)); compositeSubscription.add(createHomeMeta(displayable).observeOn(AndroidSchedulers.mainThread()) .doOnNext(homeMeta -> { ParcelableSpan[] textStyle = { new StyleSpan(android.graphics.Typeface.BOLD), new ForegroundColorSpan(homeMeta.getThemeColor()) }; showMainIcon(homeMeta.getMainIcon()); showSecondaryIcon(homeMeta.getSecondaryIcon()); showMainName(homeMeta.getMainName()); showSecondaryName(homeMeta.getSecondaryName()); setupActionButton(homeMeta.isShowButton(), homeMeta.isOwner(), homeMeta.getStoreId(), StoreTheme.get(homeMeta.getThemeColor()) .getThemeName(), homeMeta.getMainName(), homeMeta.getDescription(), homeMeta.getMainIcon(), homeMeta.isFollowingStore(), homeMeta.getSocialChannels()); showSocialChannels(homeMeta.getSocialChannels()); showAppsCount(homeMeta.getAppsCount(), textStyle, homeMeta.isShowApps(), homeMeta.getStoreId()); showFollowersCount(homeMeta.getFollowersCount(), textStyle); showFollowingCount(homeMeta.getFollowingCount(), textStyle); showDescription(homeMeta.getDescription()); showBadge(homeMeta.getBadge(), homeMeta.isOwner()); }) .subscribe()); }
private void showFollowingCount(long followingCount, ParcelableSpan[] textStyle) { String countText = AptoideUtils.StringU.withSuffix(followingCount); String followingText = String.format(getContext().getString(R.string.storehometab_short_following), countText); followingCountTv.setText(spannableFactory.createMultiSpan(followingText, textStyle, countText)); }
private void showFollowersCount(long followersCount, ParcelableSpan[] textStyle) { String count = AptoideUtils.StringU.withSuffix(followersCount); String followingText = String.format(getContext().getString(R.string.storehometab_short_subscribers), count); followersCountTv.setText(spannableFactory.createMultiSpan(followingText, textStyle, count)); }
@Override public void bindView(MyStoreDisplayable displayable) { final FragmentActivity context = getContext(); Store store = displayable.getMeta() .getData() .getStore(); suggestionMessage.setText(displayable.getSuggestionMessage(context)); exploreButton.setText(displayable.getExploreButtonText()); String storeTheme = store.getAppearance() .getTheme(); ImageLoader.with(context) .loadWithShadowCircleTransform(store.getAvatar(), storeIcon); storeName.setText(store.getName()); compositeSubscription.add(RxView.clicks(exploreButton) .subscribe(click -> { getFragmentNavigator().navigateTo(AptoideApplication.getFragmentProvider() .newStoreFragment(store.getName(), storeTheme), true); storeAnalytics.sendStoreTabInteractEvent("View Store"); storeAnalytics.sendStoreOpenEvent("View Own Store", store.getName()); })); SpannableFactory spannableFactory = new SpannableFactory(); String followersText = String.format(getContext().getString(R.string.storetab_short_followers), String.valueOf(displayable.getFollowers())); ParcelableSpan[] textStyle = { new StyleSpan(android.graphics.Typeface.BOLD), new ForegroundColorSpan(getTextColor()) }; followers.setText(spannableFactory.createMultiSpan(followersText, textStyle, String.valueOf(displayable.getFollowers()))); String followingText = String.format(getContext().getString(R.string.storetab_short_followings), String.valueOf(displayable.getFollowings())); following.setText(spannableFactory.createMultiSpan(followingText, textStyle, String.valueOf(displayable.getFollowings()))); compositeSubscription.add(RxView.clicks(followers) .subscribe(click -> getFragmentNavigator().navigateTo( TimeLineFollowersFragment.newInstanceUsingUser(storeTheme, AptoideUtils.StringU.getFormattedString( R.string.social_timeline_followers_fragment_title, getContext().getResources(), displayable.getFollowers()), displayable.getStoreContext()), true))); compositeSubscription.add(RxView.clicks(following) .subscribe(click -> getFragmentNavigator().navigateTo( TimeLineFollowingFragment.newInstanceUsingUser(storeTheme, AptoideUtils.StringU.getFormattedString( R.string.social_timeline_following_fragment_title, getContext().getResources(), displayable.getFollowings()), displayable.getStoreContext()), true))); }
boolean extractTextInternal(ExtractedTextRequest request, int partialStartOffset, int partialEndOffset, int delta, ExtractedText outText) { final CharSequence content = mText; if (content != null) { if (partialStartOffset != EXTRACT_NOTHING) { final int N = content.length(); if (partialStartOffset < 0) { outText.partialStartOffset = outText.partialEndOffset = -1; partialStartOffset = 0; partialEndOffset = N; } else { // Adjust offsets to ensure we contain full spans. if (content instanceof Spanned) { Spanned spanned = (Spanned)content; Object[] spans = spanned.getSpans(partialStartOffset, partialEndOffset, ParcelableSpan.class); int i = spans.length; while (i > 0) { i--; int j = spanned.getSpanStart(spans[i]); if (j < partialStartOffset) partialStartOffset = j; j = spanned.getSpanEnd(spans[i]); if (j > partialEndOffset) partialEndOffset = j; } } outText.partialStartOffset = partialStartOffset; outText.partialEndOffset = partialEndOffset; // Now use the delta to determine the actual amount of text // we need. partialEndOffset += delta; if (partialStartOffset > N) { partialStartOffset = N; } else if (partialStartOffset < 0) { partialStartOffset = 0; } if (partialEndOffset > N) { partialEndOffset = N; } else if (partialEndOffset < 0) { partialEndOffset = 0; } } if ((request.flags&InputConnection.GET_TEXT_WITH_STYLES) != 0) { outText.text = content.subSequence(partialStartOffset, partialEndOffset); } else { outText.text = TextUtils.substring(content, partialStartOffset, partialEndOffset); } } else { outText.partialStartOffset = 0; outText.partialEndOffset = 0; outText.text = ""; } outText.flags = 0; if (JotaTextKeyListener.getMetaStateSelecting(mText) != 0) { outText.flags |= ExtractedText.FLAG_SELECTING; } if (mSingleLine) { outText.flags |= ExtractedText.FLAG_SINGLE_LINE; } outText.startOffset = 0; outText.selectionStart = getSelectionStart(); outText.selectionEnd = getSelectionEnd(); return true; } return false; }
/** * Flatten a CharSequence and whatever styles can be copied across processes * into the parcel. */ public static void writeToParcel(CharSequence cs, Parcel p, int parcelableFlags) { if (cs instanceof Spanned) { p.writeInt(0); p.writeString(cs.toString()); Spanned sp = (Spanned) cs; Object[] os = sp.getSpans(0, cs.length(), Object.class); // note to people adding to this: check more specific types // before more generic types. also notice that it uses // "if" instead of "else if" where there are interfaces // so one object can be several. for (int i = 0; i < os.length; i++) { Object o = os[i]; Object prop = os[i]; if (prop instanceof CharacterStyle) { prop = ((CharacterStyle) prop).getUnderlying(); } if (prop instanceof ParcelableSpan) { ParcelableSpan ps = (ParcelableSpan)prop; // dont percel unknown span id int id = ps.getSpanTypeId(); if ( id <= ANNOTATION ){ p.writeInt(id); ps.writeToParcel(p, parcelableFlags); writeWhere(p, sp, o); } // p.writeInt(ps.getSpanTypeId()); // ps.writeToParcel(p, parcelableFlags); // writeWhere(p, sp, o); } } p.writeInt(0); } else { p.writeInt(1); if (cs != null) { p.writeString(cs.toString()); } else { p.writeString(null); } } }
public ParcelableSpan create(Matcher matcher, int iM) { return new ColorUnderlineSpan(Color.parseColor(matcher.group(1)), null); }
ParcelableSpan create(Matcher matcher, int iM);
ParcelableSpan create(Matcher m);