通知样式之InboxStyle的设计

32

我尝试实现一个可扩展的通知,我使用了InboxStyle

基于文档中的以下图像:

inboxstyle notification

应该可以对文本进行格式化。在这种情况下,将“Google Play”设置为粗体。

InboxStyle仅具有addLine() 方法,可以传递CharSequence。我尝试使用Html.fromHtml() 并使用一些HTML格式化,但我没有成功。

NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
inboxStyle.setBigContentTitle("title");
inboxStyle.setSummaryText("summarytext");
// fetch push messages
synchronized (mPushMessages) {
    HashMap<String, PushMessage> messages = mPushMessages.get(key);
    if (messages != null) {
        for (Entry<String, PushMessage> msg : messages.entrySet()) {
            inboxStyle.addLine(Html.fromHtml("at least <b>one word</b> should be bold!");
        }
        builder.setStyle(inboxStyle);
        builder.setNumber(messages.size());
    }
}

对此有什么想法吗?

5个回答

50
您不需要使用fromHtml。我曾经遇到过fromHtml的问题(当您显示的内容来自用户时,代码注入可能导致丑陋的事情)。此外,我不喜欢在strings.xml中放置格式化元素(如果您使用服务进行翻译,则可能会损坏HTML标记)。
大多数用于设置通知文本的方法(setTickersetContentInfosetContentTitle等)都采用CharSequence作为参数。因此,您可以传递一个Spannable。假设您想要"Bold this and italic that.",您可以按以下方式格式化它(当然不要硬编码位置):
Spannable sb = new SpannableString("Bold this and italic that.");
sb.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
sb.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 14, 20, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
inboxStyle.addLine(sb);

如果您需要使用本地化字符串动态构建字符串,例如“今天是[DAY],早上好!”,请将带有占位符的字符串放在strings.xml中:

<string name="notification_line_format">Today is %1$s, good morning!</string>

然后按照以下方式进行格式化:
String today = "Sunday";
String lineFormat = context.getString(R.string.notification_line_format);
int lineParamStartPos = lineFormat.indexOf("%1$s");
if (lineParamStartPos < 0) {
  throw new InvalidParameterException("Something's wrong with your string! LINT could have caught that.");
}
String lineFormatted = context.getString(R.string.notification_line_format, today);

Spannable sb = new SpannableString(lineFormatted);
sb.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), lineParamStartPos, lineParamStartPos + today.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
inboxStyle.addLine(sb);

你会得到“今天是星期日,早上好!”,据我所知它适用于所有版本的Android。


7

I have made helper method for this:

private final StyleSpan mBoldSpan = new StyleSpan(Typeface.BOLD);

private SpannableString makeNotificationLine(String title, String text) {
    final SpannableString spannableString;
    if (title != null && title.length() > 0) {
        spannableString = new SpannableString(String.format("%s  %s", title, text));
        spannableString.setSpan(mBoldSpan, 0, title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    } else {
        spannableString = new SpannableString(text);
    }
    return spannableString;
}

使用方法如下:

inboxStyle.addLine(makeNotificationLine("UserXYZ", "How are you?"));

7

你的代码在我使用安装有Android 4.1.1的三星S3上非常好用。你使用的是哪个Android版本?

import android.app.Activity;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.text.Html;
import android.view.Menu;

public class MainActivity extends Activity {

    private final int ID = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
                this).setSmallIcon(R.drawable.ic_launcher);
        NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
        inboxStyle.addLine(Html
                .fromHtml("<i>italic</i> <b>bold</b> text works"));
        mBuilder.setStyle(inboxStyle);
        mBuilder.setNumber(1);

        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(ID, mBuilder.build());
    }

}

我正在使用原版 Android 4.2.1(现在是4.2.2)。 - WarrenFaith
很有趣。那么,使用上面编辑过的Activity示例代码,你得到了什么结果?我在Android 4.2模拟器上尝试了一下,它也可以工作。 - riwnodennyk
3
我可以深入了解并找到问题的原因:我只想给消息的一部分添加样式,所以我只在字符串的一部分使用了 fromHtml()。我使用了 fromHtml("<b>加粗</b>") + " 其他文本",结果没有样式。将剩余的字符串移到 fromHtml() 调用中可以完美解决问题!谢谢! - WarrenFaith
fromHtml() 有很多缺点。请查看下面的解决方案,我认为它更加健壮。 - tdevaux

3

这里是最简单的解决方案

它没有使用InboxStyle,因为在我的情况下不需要它


CharSequence boldUsernameMessage = Html.fromHtml("<b>@" + username +"</b> " + message);

NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext())
    .setContentText(boldUsernameMessage)
    .setStyle(new NotificationCompat.BigTextStyle().bigText(boldUsernameMessage)) // Makes it expandable to show the message
    .build();

结果

这里输入图片描述


这是一个关于IT技术的图片,无法为您提供更多信息。

当通知未展开时,用户名mikemilla不是粗体。如何将mikemilla显示为粗体?当我展开mikemilla时,它是粗体的,这很好。 - User12111111

2

加粗文本应使用<strong>标签。您的代码没有问题,只需将<b>更改为<strong>即可。

编辑: 您应该将代码更改为以下内容:

NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
inboxStyle.setBigContentTitle("title");
inboxStyle.setSummaryText("summarytext");
// fetch push messages
synchronized (mPushMessages) {
    HashMap<String, PushMessage> messages = mPushMessages.get(key);
    if (messages != null) {
        for (Entry<String, PushMessage> msg : messages.entrySet()) {
            inboxStyle.addLine(Html.fromHtml("at least <strong>one word</strong> should be bold!");
        }
        builder.setStyle(inboxStyle);
        builder.setNumber(messages.size());
    }
}

你的回答完整吗?似乎缺少了关键部分。 - WarrenFaith
我不想在这里复制粘贴您的代码。只需将<b>一个单词</b>更改为<strong>一个单词</strong>即可完成。我现在正在更新我的答案。 - tasomaniac

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接