use of android.text.style.StyleSpan in project Android-Week-View by alamkanak.
the class WeekView method drawEventTitle.
/**
* Draw the name of the event on top of the event rectangle.
* @param event The event of which the title (and location) should be drawn.
* @param rect The rectangle on which the text is to be drawn.
* @param canvas The canvas to draw upon.
* @param originalTop The original top position of the rectangle. The rectangle may have some of its portion outside of the visible area.
* @param originalLeft The original left position of the rectangle. The rectangle may have some of its portion outside of the visible area.
*/
private void drawEventTitle(WeekViewEvent event, RectF rect, Canvas canvas, float originalTop, float originalLeft) {
if (rect.right - rect.left - mEventPadding * 2 < 0)
return;
if (rect.bottom - rect.top - mEventPadding * 2 < 0)
return;
// Prepare the name of the event.
SpannableStringBuilder bob = new SpannableStringBuilder();
if (event.getName() != null) {
bob.append(event.getName());
bob.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, bob.length(), 0);
bob.append(' ');
}
// Prepare the location of the event.
if (event.getLocation() != null) {
bob.append(event.getLocation());
}
int availableHeight = (int) (rect.bottom - originalTop - mEventPadding * 2);
int availableWidth = (int) (rect.right - originalLeft - mEventPadding * 2);
// Get text dimensions.
StaticLayout textLayout = new StaticLayout(bob, mEventTextPaint, availableWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
int lineHeight = textLayout.getHeight() / textLayout.getLineCount();
if (availableHeight >= lineHeight) {
// Calculate available number of line counts.
int availableLineCount = availableHeight / lineHeight;
do {
// Ellipsize text to fit into event rect.
textLayout = new StaticLayout(TextUtils.ellipsize(bob, mEventTextPaint, availableLineCount * availableWidth, TextUtils.TruncateAt.END), mEventTextPaint, (int) (rect.right - originalLeft - mEventPadding * 2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
// Reduce line count.
availableLineCount--;
// Repeat until text is short enough.
} while (textLayout.getHeight() > availableHeight);
// Draw text.
canvas.save();
canvas.translate(originalLeft + mEventPadding, originalTop + mEventPadding);
textLayout.draw(canvas);
canvas.restore();
}
}
use of android.text.style.StyleSpan in project plaid by nickbutcher.
the class Bypass method recurseElement.
// The 'numberOfSiblings' parameters refers to the number of siblings within the parent, including
// the 'element' parameter, as in "How many siblings are you?" rather than "How many siblings do
// you have?".
private CharSequence recurseElement(Element element, int indexWithinParent, int numberOfSiblings, TextView textView, LoadImageCallback loadImageCallback) {
Type type = element.getType();
boolean isOrderedList = false;
if (type == Type.LIST) {
String flagsStr = element.getAttribute("flags");
if (flagsStr != null) {
int flags = Integer.parseInt(flagsStr);
isOrderedList = (flags & Element.F_LIST_ORDERED) != 0;
if (isOrderedList) {
mOrderedListNumber.put(element, 1);
}
}
}
int size = element.size();
CharSequence[] spans = new CharSequence[size];
for (int i = 0; i < size; i++) {
spans[i] = recurseElement(element.children[i], i, size, textView, loadImageCallback);
}
// Clean up after we're done
if (isOrderedList) {
mOrderedListNumber.remove(this);
}
CharSequence concat = TextUtils.concat(spans);
SpannableStringBuilder builder = new ReverseSpannableStringBuilder();
String text = element.getText();
if (element.size() == 0 && element.getParent() != null && element.getParent().getType() != Type.BLOCK_CODE) {
text = text.replace('\n', ' ');
}
switch(type) {
case LIST:
if (element.getParent() != null && element.getParent().getType() == Type.LIST_ITEM) {
builder.append("\n");
}
break;
case LINEBREAK:
builder.append("\n");
break;
case LIST_ITEM:
builder.append(" ");
if (mOrderedListNumber.containsKey(element.getParent())) {
int number = mOrderedListNumber.get(element.getParent());
builder.append(Integer.toString(number) + ".");
mOrderedListNumber.put(element.getParent(), number + 1);
} else {
builder.append(mOptions.mUnorderedListItem);
}
builder.append(" ");
break;
case AUTOLINK:
builder.append(element.getAttribute("link"));
break;
case HRULE:
// This ultimately gets drawn over by the line span, but
// we need something here or the span isn't even drawn.
builder.append("-");
break;
case IMAGE:
if (loadImageCallback != null && !TextUtils.isEmpty(element.getAttribute("link"))) {
// prepend a new line so that images are always on a new line
builder.append("\n");
// Display alt text (or title text) if there is no image
String alt = element.getAttribute("alt");
if (TextUtils.isEmpty(alt)) {
alt = element.getAttribute("title");
}
if (!TextUtils.isEmpty(alt)) {
alt = "[" + alt + "]";
builder.append(alt);
} else {
// Character to be replaced
builder.append("");
}
} else {
// Character to be replaced
builder.append("");
}
break;
}
builder.append(text);
builder.append(concat);
// of the last child within the parent.
if (element.getParent() != null || indexWithinParent < (numberOfSiblings - 1)) {
if (type == Type.LIST_ITEM) {
if (element.size() == 0 || !element.children[element.size() - 1].isBlockElement()) {
builder.append("\n");
}
} else if (element.isBlockElement() && type != Type.BLOCK_QUOTE) {
if (type == Type.LIST) {
// If this is a nested list, don't include newlines
if (element.getParent() == null || element.getParent().getType() != Type.LIST_ITEM) {
builder.append("\n");
}
} else if (element.getParent() != null && element.getParent().getType() == Type.LIST_ITEM) {
// List items should never double-space their entries
builder.append("\n");
} else {
builder.append("\n\n");
}
}
}
switch(type) {
case HEADER:
String levelStr = element.getAttribute("level");
int level = Integer.parseInt(levelStr);
setSpan(builder, new RelativeSizeSpan(mOptions.mHeaderSizes[level - 1]));
setSpan(builder, new StyleSpan(Typeface.BOLD));
break;
case LIST:
setBlockSpan(builder, new LeadingMarginSpan.Standard(mListItemIndent));
break;
case EMPHASIS:
setSpan(builder, new StyleSpan(Typeface.ITALIC));
break;
case DOUBLE_EMPHASIS:
setSpan(builder, new StyleSpan(Typeface.BOLD));
break;
case TRIPLE_EMPHASIS:
setSpan(builder, new StyleSpan(Typeface.BOLD_ITALIC));
break;
case BLOCK_CODE:
setSpan(builder, new LeadingMarginSpan.Standard(mCodeBlockIndent));
setSpan(builder, new TypefaceSpan("monospace"));
break;
case CODE_SPAN:
setSpan(builder, new TypefaceSpan("monospace"));
break;
case LINK:
case AUTOLINK:
String link = element.getAttribute("link");
if (!TextUtils.isEmpty(link) && Patterns.EMAIL_ADDRESS.matcher(link).matches()) {
link = "mailto:" + link;
}
setSpan(builder, new TouchableUrlSpan(link, textView.getLinkTextColors(), textView.getHighlightColor()));
break;
case BLOCK_QUOTE:
// We add two leading margin spans so that when the order is reversed,
// the QuoteSpan will always be in the same spot.
setBlockSpan(builder, new LeadingMarginSpan.Standard(mBlockQuoteIndent));
//setBlockSpan(builder, new QuoteSpan(mOptions.mBlockQuoteLineColor));
setBlockSpan(builder, new FancyQuoteSpan(mBlockQuoteLineWidth, mBlockQuoteLineIndent, mOptions.mBlockQuoteLineColor));
setBlockSpan(builder, new ForegroundColorSpan(mOptions.mBlockQuoteTextColor));
setBlockSpan(builder, new LeadingMarginSpan.Standard(mBlockQuoteIndent));
setBlockSpan(builder, new StyleSpan(Typeface.ITALIC));
break;
case STRIKETHROUGH:
setSpan(builder, new StrikethroughSpan());
break;
case HRULE:
setSpan(builder, new HorizontalLineSpan(mOptions.mHruleColor, mHruleSize, mHruleTopBottomPadding));
break;
case IMAGE:
String url = element.getAttribute("link");
if (loadImageCallback != null && !TextUtils.isEmpty(url)) {
setPrependedNewlineSpan(builder, mOptions.mPreImageLinebreakHeight);
ImageLoadingSpan loadingSpan = new ImageLoadingSpan();
setSpanWithPrependedNewline(builder, loadingSpan);
// make the (eventually loaded) image span clickable to open in browser
setSpanWithPrependedNewline(builder, new TouchableUrlSpan(url, textView.getLinkTextColors(), textView.getHighlightColor()));
loadImageCallback.loadImage(url, loadingSpan);
}
break;
}
return builder;
}
use of android.text.style.StyleSpan in project SeriesGuide by UweTrottmann.
the class NotificationService method onNotify.
private void onNotify(final Cursor upcomingEpisodes, List<Integer> notifyPositions, long latestAirtime) {
final Context context = getApplicationContext();
CharSequence tickerText;
CharSequence contentTitle;
CharSequence contentText;
PendingIntent contentIntent;
// base intent for task stack
final Intent showsIntent = new Intent(context, ShowsActivity.class);
showsIntent.putExtra(ShowsActivity.InitBundle.SELECTED_TAB, ShowsActivity.InitBundle.INDEX_TAB_UPCOMING);
final int count = notifyPositions.size();
if (count == 1) {
// notify in detail about one episode
upcomingEpisodes.moveToPosition(notifyPositions.get(0));
final String showTitle = upcomingEpisodes.getString(NotificationQuery.SHOW_TITLE);
// show title and number, like 'Show 1x01'
contentTitle = TextTools.getShowWithEpisodeNumber(this, showTitle, upcomingEpisodes.getInt(NotificationQuery.SEASON), upcomingEpisodes.getInt(NotificationQuery.NUMBER));
tickerText = getString(R.string.upcoming_show, contentTitle);
// "8:00 PM on Network"
final String releaseTime = TimeTools.formatToLocalTime(this, TimeTools.applyUserOffset(this, upcomingEpisodes.getLong(NotificationQuery.EPISODE_FIRST_RELEASE_MS)));
final String network = upcomingEpisodes.getString(NotificationQuery.NETWORK);
contentText = getString(R.string.upcoming_show_detailed, releaseTime, network);
Intent episodeDetailsIntent = new Intent(context, EpisodesActivity.class);
episodeDetailsIntent.putExtra(EpisodesActivity.InitBundle.EPISODE_TVDBID, upcomingEpisodes.getInt(NotificationQuery._ID));
episodeDetailsIntent.putExtra(KEY_EPISODE_CLEARED_TIME, latestAirtime);
contentIntent = TaskStackBuilder.create(context).addNextIntent(showsIntent).addNextIntent(episodeDetailsIntent).getPendingIntent(REQUEST_CODE_SINGLE_EPISODE, PendingIntent.FLAG_CANCEL_CURRENT);
} else {
// notify about multiple episodes
tickerText = getString(R.string.upcoming_episodes);
contentTitle = getString(R.string.upcoming_episodes_number, count);
contentText = getString(R.string.upcoming_display);
contentIntent = TaskStackBuilder.create(context).addNextIntent(showsIntent.putExtra(KEY_EPISODE_CLEARED_TIME, latestAirtime)).getPendingIntent(REQUEST_CODE_MULTIPLE_EPISODES, PendingIntent.FLAG_CANCEL_CURRENT);
}
final NotificationCompat.Builder nb = new NotificationCompat.Builder(context);
boolean richNotification = AndroidUtils.isJellyBeanOrHigher();
if (richNotification) {
// JELLY BEAN and above
if (count == 1) {
// single episode
upcomingEpisodes.moveToPosition(notifyPositions.get(0));
maybeSetPoster(nb, upcomingEpisodes.getString(NotificationQuery.POSTER));
if (!DisplaySettings.preventSpoilers(context)) {
final String episodeTitle = upcomingEpisodes.getString(NotificationQuery.TITLE);
final String episodeSummary = upcomingEpisodes.getString(NotificationQuery.OVERVIEW);
final SpannableStringBuilder bigText = new SpannableStringBuilder();
bigText.append(TextUtils.isEmpty(episodeTitle) ? "" : episodeTitle);
bigText.setSpan(new StyleSpan(Typeface.BOLD), 0, bigText.length(), 0);
bigText.append("\n");
bigText.append(TextUtils.isEmpty(episodeSummary) ? "" : episodeSummary);
nb.setStyle(new NotificationCompat.BigTextStyle().bigText(bigText).setSummaryText(contentText));
}
// Action button to check in
Intent checkInActionIntent = new Intent(context, QuickCheckInActivity.class);
checkInActionIntent.putExtra(QuickCheckInActivity.InitBundle.EPISODE_TVDBID, upcomingEpisodes.getInt(NotificationQuery._ID));
checkInActionIntent.putExtra(KEY_EPISODE_CLEARED_TIME, latestAirtime);
checkInActionIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
PendingIntent checkInIntent = PendingIntent.getActivity(context, REQUEST_CODE_ACTION_CHECKIN, checkInActionIntent, PendingIntent.FLAG_CANCEL_CURRENT);
nb.addAction(R.drawable.ic_action_checkin, getString(R.string.checkin), checkInIntent);
// Action button to set watched
Intent setWatchedIntent = new Intent(context, NotificationActionReceiver.class);
setWatchedIntent.putExtra(NotificationActionReceiver.EXTRA_EPISODE_TVDBID, upcomingEpisodes.getInt(NotificationQuery._ID));
// data to handle delete
checkInActionIntent.putExtra(KEY_EPISODE_CLEARED_TIME, latestAirtime);
PendingIntent setWatchedPendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE_ACTION_SET_WATCHED, setWatchedIntent, PendingIntent.FLAG_CANCEL_CURRENT);
nb.addAction(R.drawable.ic_action_tick, getString(R.string.action_watched), setWatchedPendingIntent);
nb.setNumber(1);
} else {
// multiple episodes
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
// display at most the first five
for (int displayIndex = 0; displayIndex < Math.min(count, 5); displayIndex++) {
if (!upcomingEpisodes.moveToPosition(notifyPositions.get(displayIndex))) {
// could not go to the desired position (testing just in case)
break;
}
final SpannableStringBuilder lineText = new SpannableStringBuilder();
// show title and number, like 'Show 1x01'
String title = TextTools.getShowWithEpisodeNumber(this, upcomingEpisodes.getString(NotificationQuery.SHOW_TITLE), upcomingEpisodes.getInt(NotificationQuery.SEASON), upcomingEpisodes.getInt(NotificationQuery.NUMBER));
lineText.append(title);
lineText.setSpan(new StyleSpan(Typeface.BOLD), 0, lineText.length(), 0);
lineText.append(" ");
// "8:00 PM on Network"
String releaseTime = TimeTools.formatToLocalTime(this, TimeTools.applyUserOffset(this, upcomingEpisodes.getLong(NotificationQuery.EPISODE_FIRST_RELEASE_MS)));
String network = upcomingEpisodes.getString(NotificationQuery.NETWORK);
lineText.append(getString(R.string.upcoming_show_detailed, releaseTime, network));
inboxStyle.addLine(lineText);
}
// tell if we could not display all episodes
if (count > 5) {
inboxStyle.setSummaryText(getString(R.string.more, count - 5));
}
nb.setStyle(inboxStyle);
nb.setNumber(count);
}
} else {
// ICS and below
if (count == 1) {
// single episode
upcomingEpisodes.moveToPosition(notifyPositions.get(0));
maybeSetPoster(nb, upcomingEpisodes.getString(NotificationQuery.POSTER));
}
}
// notification sound
final String ringtoneUri = NotificationSettings.getNotificationsRingtone(context);
// If the string is empty, the user chose silent...
boolean hasSound = ringtoneUri.length() != 0;
if (hasSound) {
// ...otherwise set the specified ringtone
nb.setSound(Uri.parse(ringtoneUri));
}
// vibration
boolean vibrates = NotificationSettings.isNotificationVibrating(context);
if (vibrates) {
nb.setVibrate(VIBRATION_PATTERN);
}
nb.setDefaults(Notification.DEFAULT_LIGHTS);
nb.setWhen(System.currentTimeMillis());
nb.setAutoCancel(true);
nb.setTicker(tickerText);
nb.setContentTitle(contentTitle);
nb.setContentText(contentText);
nb.setContentIntent(contentIntent);
nb.setSmallIcon(R.drawable.ic_notification);
nb.setColor(ContextCompat.getColor(this, R.color.accent_primary));
nb.setPriority(NotificationCompat.PRIORITY_DEFAULT);
Intent i = new Intent(this, NotificationService.class);
i.putExtra(KEY_EPISODE_CLEARED_TIME, latestAirtime);
PendingIntent deleteIntent = PendingIntent.getService(this, REQUEST_CODE_DELETE_INTENT, i, PendingIntent.FLAG_CANCEL_CURRENT);
nb.setDeleteIntent(deleteIntent);
// build the notification
Notification notification = nb.build();
// use a unique id within the app
NotificationManagerCompat nm = NotificationManagerCompat.from(getApplicationContext());
nm.notify(SgApp.NOTIFICATION_EPISODE_ID, notification);
Timber.d("Notification: count=%d, rich(JB+)=%s, sound=%s, vibrate=%s, delete=%d", count, richNotification ? "YES" : "NO", hasSound ? "YES" : "NO", vibrates ? "YES" : "NO", latestAirtime);
}
use of android.text.style.StyleSpan in project xabber-android by redsolution.
the class MessageNotificationCreator method getContactNameAndMessage.
private Spannable getContactNameAndMessage(MessageNotification messageNotification, boolean showText) {
String userName = getContactName(messageNotification);
Spannable spannableString;
if (showText) {
String contactAndMessage = application.getString(R.string.chat_contact_and_message, userName, messageNotification.getText());
spannableString = new SpannableString(contactAndMessage);
} else {
spannableString = new SpannableString(userName);
}
spannableString.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, userName.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return spannableString;
}
use of android.text.style.StyleSpan in project Shuttle by timusus.
the class PlaylistUtils method getPlaylistRemoveString.
private static SpannableStringBuilder getPlaylistRemoveString(Context context, Song song) {
SpannableStringBuilder spannableString = new SpannableStringBuilder(String.format(context.getString(R.string.dialog_message_playlist_add_duplicate), song.artistName, song.name));
final StyleSpan boldSpan = new StyleSpan(android.graphics.Typeface.BOLD);
spannableString.setSpan(boldSpan, 0, song.artistName.length() + song.name.length() + 3, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
return spannableString;
}
Aggregations