接口参考
星河岛 SDK 0.1.2 全部公开接口,位于 com.astraisland.sdk 包。签名以 Kotlin 书写;Java 中属性对应 getXxx() / isXxx(),带默认值的参数提供多个重载,工厂方法为静态方法。
以下签名以 Kotlin 书写;Java 中属性对应 getXxx() / isXxx(),带默认值的参数提供多个重载,工厂方法为静态方法。
IslandClient
class IslandClient(context: Context)星河岛客户端。context 可为任意上下文,客户端只保留其应用上下文。
| 成员 | 说明 |
|---|---|
enum class State { NOT_INSTALLED, WAITING, REJECTED, READY } | 连接状态,见下表 |
val state: State | 当前连接状态。创建后为 WAITING |
val isReady: Boolean | 是否已连接,可以显示内容 |
fun setCallback(callback: IslandCallback?) | 设置回调;为 null 时不再接收回调 |
fun isHostInstalled(): Boolean | 设备上是否安装了可用的星流(通信版本 7) |
fun connect() | 连接星河岛。未安装可用的星流时状态变为 NOT_INSTALLED;否则为 WAITING,星河岛响应后变为 READY。已连接时再次调用会重新连接 |
fun disconnect() | 断开连接,并结束本应用在星河岛上的全部内容 |
fun start(activity: IslandActivity): IslandResult | 显示一条内容;同一内容编号已在显示时整份替换。未连接时返回 NOT_CONNECTED |
fun update(activity: IslandActivity): IslandResult | 与 start 相同 |
fun end(id: String, outro: Outro? = null): IslandResult | 结束一条内容,可带收尾 |
fun endAll(): IslandResult | 结束本应用在星河岛上的全部内容;未连接时返回 NOT_CONNECTED |
fun listMine(): List<String> | 本应用仍在星河岛上的内容编号(含暂未显示、排在后面的内容);未连接时为空列表 |
const val SDK_VERSION: String = "0.1.2" | 伴生常量 |
const val PROTOCOL_VERSION: Int = 7 | 伴生常量 |
State 取值 | 含义 |
|---|---|
NOT_INSTALLED | 未安装星流,或已安装的星流不支持当前通信版本 |
WAITING | 正在等待星河岛响应;连接后长时间停留在此状态,说明星河岛未启用或设备尚未就绪(OPPO、一加、realme 手机上也可能是尚未启用插件「流体云事件接入」) |
REJECTED | 星河岛拒绝了连接(例如身份核对未通过) |
READY | 已连接,可以显示内容 |
IslandCallback
abstract class IslandCallback按需重写,所有方法默认不做任何处理,都在主线程调用。事件尽力送达,不作为业务依据。
| 方法 | 触发时机 |
|---|---|
open fun onStateChanged(state: IslandClient.State) | 连接状态变化 |
open fun onAction(activityId: String, actionId: String) | 用户点击了卡片上的按钮。actionId 为应用设置的按钮编号,或 TimerControl.actionId、MediaControl.actionId、StatusCard.ACTION_STOP |
open fun onReply(activityId: String, text: String) | 用户在消息卡片的回复输入框中发送了文字。星河岛交出文字后卡片提示「已交给应用发送」;实际发送由应用负责,发送后可用同一内容编号更新卡片 |
open fun onSeek(activityId: String, positionMs: Long) | 用户在音乐卡片上拖动进度条并松手,positionMs 为毫秒。跳到该位置后,请用同一内容编号更新播放进度 |
open fun onDismissed(activityId: String) | 用户在胶囊上划动,把这条内容从星河岛上收起。内容并未结束:有真实的新消息或新的重要提醒、用户进出一次本应用,或用户点击摄像头区域召回时,它会重新显示;普通进度刷新、换歌词等重复更新不视为新的提醒。用户开启「长时间未操作时收起」或「停留后收起」后,星河岛也会在设定时间内没有操作时自动收起内容,此情形不调用本方法。不再需要时请调用 end() |
open fun onExpanded(activityId: String) | 这条内容的卡片展开(包括用户操作与自动提醒) |
open fun onCollapsed(activityId: String) | 这条内容的卡片收起 |
open fun onEnded(activityId: String, reason: EndReason) | 这条内容被星河岛结束 |
enum class EndReason { EXPIRED, REMOVED }EndReason 取值 | 含义 |
|---|---|
EXPIRED | 到达自动消失时间,或显示满 8 小时 |
REMOVED | 用户在星流中关闭了本应用的内容或音乐内容,或星河岛停止运行 |
IslandResult
enum class IslandResult { OK, IMAGE_REJECTED, NO_PERMISSION, SOURCE_DISABLED, KIND_DISABLED, QUOTA_EXCEEDED, RATE_LIMITED, INVALID, BUSY, NOT_CONNECTED }| 取值 | 含义 |
|---|---|
OK | 已受理 |
IMAGE_REJECTED | 已受理,但有图片不符合要求而未显示,其余内容照常显示 |
NO_PERMISSION | 没有投送权限:清单中缺少 SDK 自带的权限声明 |
SOURCE_DISABLED | 用户在星流中关闭了本应用的内容 |
KIND_DISABLED | 用户在星流中关闭了「星河岛歌词」,音乐卡片不予显示 |
QUOTA_EXCEEDED | 本应用通过 SDK 提交且尚未结束的内容已达 3 条,排队内容也计入;请先结束旧内容 |
RATE_LIMITED | 提交过于频繁(每秒超过 10 次),本次未受理 |
INVALID | 内容无效(例如数值不是有限数),或连接尚未就绪;原有内容保持不变 |
BUSY | 星河岛暂时繁忙,本次未处理,请稍后重试 |
NOT_CONNECTED | 尚未连接到星河岛,或连接已断开 |
val accepted: Boolean:是否已受理(OK 或 IMAGE_REJECTED)。受理不等于已显示,例如本应用在前台、排位靠后时内容暂不显示。
IslandActivity
class IslandActivity // 通过 IslandActivity.Builder 生成
class IslandActivity.Builder(id: String, capsule: Capsule, card: IslandCard)放上星河岛的一条内容。id 为内容编号,本应用内唯一,1 至 128 个字符(不能为空白)。
| Builder 方法 | 默认值 | 说明 |
|---|---|---|
setPriority(priority: Priority) | DEFAULT | 排位参考。消息卡片不使用此项,按新消息排位 |
setAlertOnStart(alert: Boolean) | false | 首次显示时自动展开卡片片刻。同一应用 10 秒内最多自动展开一次 |
setAlertOnUpdate(alert: Boolean) | false | 更新(且内容有变化)时自动展开卡片片刻。同一应用 10 秒内最多自动展开一次;连续更新显示最新内容,期间提出的展开要求保留一次 |
setLockScreenVisibility(visibility: LockScreenVisibility) | PUBLIC | 锁屏时显示多少 |
setOpenIntent(intent: PendingIntent?) | null | 点击卡片时执行的操作 |
setOwnNotification(id: Int, tag: String? = null) | 未设置 | 说明这条内容对应本应用自己的哪一条通知(NotificationManager.notify 的编号与标签)。这条内容在星河岛上时,那条通知不再单独显示在星河岛上;内容显示在主岛或副岛上,且用户开启「屏蔽系统横幅」时,那条通知也不再弹出系统横幅。仅可关联星河岛所在用户中本应用自己的通知;内容结束后不重新显示旧通知,待通知下次更新时按通知规则处理 |
setPostedAt(timeMillis: Long) | 未设置 | 发送时间(System.currentTimeMillis() 口径,大于 0)。显示来源栏时,卡片来源栏右侧显示「刚刚」「5 分钟前」或具体时刻;消息卡片以发送时间区分新消息 |
setStaleAt(timeMillis: Long) | 未设置 | 过时时间(大于 0)。过了这个时间卡片注明「信息可能已过时」,内容仍保留 |
setDismissPolicy(policy: DismissPolicy) | untilEnded() | 消失方式 |
setLandscapeText(text: String?) | null | 横屏胶囊的完整短文字,最多 32 个字符,数字与英文按组竖排后须在四行以内;未设置或无法完整显示时,星河岛保留完整数值或短状态,不截取卡片标题。消息显示应用名称;音乐优先显示波形;空白及非文字的右侧内容保持原有形式 |
setAccentColor(color: Int?) | null | 强调色(ARGB),用于进度条、主要按钮、放大的数值等;过暗的颜色会被提亮 |
setContentDescription(text: String?) | null | 无障碍读屏说明,最多 256 个字符 |
build(): IslandActivity | 生成内容 |
异常:Builder(...) 在编号为空白或超过 128 个字符时抛出 IllegalArgumentException;setPostedAt、setStaleAt 在时间不大于 0 时抛出;setLandscapeText、setContentDescription 在文字为空白或超长时抛出;build() 在全部文字合计超过 8192 字节(UTF-8)时抛出。
只读属性:id、capsule、card、priority、alertOnStart、alertOnUpdate、lockScreenVisibility、openIntent、notificationId: Int?、notificationTag: String?、postedAtMillis: Long?、staleAtMillis: Long?、dismissPolicy、landscapeText、accentColor、contentDescription。
enum class Priority { LOW, DEFAULT, HIGH }| 取值 | 含义 |
|---|---|
LOW | 低:排在正在播放的音乐之后 |
DEFAULT | 默认:按卡片种类(计时、进度、音乐等)的默认排位 |
HIGH | 高:外部应用内容的最高档,与未到点的计时同档 |
enum class LockScreenVisibility { PUBLIC, TITLE_ONLY, HIDDEN }| 取值 | 含义 |
|---|---|
PUBLIC | 完整显示。设置了 requiresUnlock 的按钮仍在锁屏时隐藏,回复输入框锁屏时不显示 |
TITLE_ONLY | 只显示标题与头像等图片:说明、正文、码、明细、比分、数值、标签、阶段名、按钮与大图均不显示 |
HIDDEN | 锁屏时不显示 |
class DismissPolicy
companion object {
fun untilEnded(): DismissPolicy // 一直显示,直到应用调用 end();最长 8 小时
fun afterMillis(millis: Long): DismissPolicy // 显示后经过给定时长(大于 0,否则抛出 IllegalArgumentException)自动消失
}class Outro(val success: Boolean, val text: String)结束内容时可选的收尾:胶囊上显示对勾(success = true)或叉号和一句话,约 1.6 秒后消失;只在这条内容仍在星河岛上时显示。text 为空白或超过 128 个字符时抛出 IllegalArgumentException。
Capsule
class Capsule // 通过 Capsule.Builder 生成
class Capsule.Builder(leading: IslandImage)胶囊:左侧一张图片(必填),可跟一段小标题;右侧一项信息;最右端可再固定一个小图或进度环。
| Builder 方法 | 默认值 | 说明 |
|---|---|---|
setLabel(label: String?) | null | 左侧图片右边的小标题,最多 32 个字符 |
setTrailing(trailing: CapsuleTrailing?) | null | 右侧信息;为 null 时右侧留空 |
setTail(tail: CapsuleTail?) | null | 固定在胶囊最右端的小图或进度环;横屏时不显示 |
setBreathing(breathing: Boolean) | false | 左侧图标做明暗呼吸变化(3 秒一轮),表示正在进行中。照片类图片不支持 |
setLeadingTint(color: Int?) | null | 左侧内置符号的颜色(ARGB),仅对 IslandImage.symbol 生效 |
setSatellite(satellite: Satellite?) | null | 副岛内容;为 null 时显示左侧图片 |
build(): Capsule | 照片类图片设置了呼吸变化,或非内置符号设置了颜色时抛出 IllegalArgumentException |
只读属性:leading、leadingTint、breathing、label、trailing、tail、satellite。
CapsuleTrailing(胶囊右侧信息,静态工厂方法;颜色为 ARGB,null 时使用胶囊文字颜色或强调色,过暗的颜色会被提亮):
| 方法 | 说明 |
|---|---|
text(text: String, color: Int? = null) | 文字,放不下时滚动显示,最多 512 个字符 |
number(text: String, color: Int? = null) | 数字等宽显示,适合频繁变化的数值(例如「12 km」「45%」),最多 512 个字符 |
countdown(endAtMillis: Long, color: Int? = null) | 倒计时,由星河岛逐秒走动,到点停在 00:00。endAtMillis 为结束时刻(大于 0) |
stopwatch(startedAtMillis: Long, color: Int? = null) | 正计时,由星河岛逐秒走动。startedAtMillis 为开始时刻(大于 0) |
progress(fraction: Float, color: Int? = null) | 进度环,fraction 为 0 至 1 |
busy(color: Int? = null) | 忙碌指示:转圈的亮弧,用于没有具体进度的进行中状态 |
waveform(active: Boolean = true, color: Int? = null) | 跳动线条,用于声音、通话等持续进行的活动;active = false 时静止 |
CapsuleTail(胶囊最右端,静态工厂方法):image(image: IslandImage);progress(fraction: Float, color: Int? = null)(fraction 为 0 至 1)。
Satellite(副岛内容,静态工厂方法):image(image: IslandImage);progress(fraction: Float, image: IslandImage? = null, color: Int? = null)(进度环,环中间可放一张图片)。
以上工厂方法在文字为空白或超长、时间不大于 0、比例不在 0 至 1 之间(含非有限数)时抛出 IllegalArgumentException。
IslandImage 与 BuiltinSymbol
class IslandImage
companion object {
fun picture(bitmap: Bitmap): IslandImage // 照片类图片:头像、封面、商品图、截图,按原图显示
fun glyph(bitmap: Bitmap): IslandImage // 单色图标:按内置符号样式显示(卡片上带圆形浅色底,胶囊中不加描边)
fun symbol(symbol: BuiltinSymbol): IslandImage // 星河岛内置符号
fun appIcon(): IslandImage // 本应用的桌面图标,仅用于胶囊与副岛
}
val isAppIcon: Boolean
val isPicture: Boolean位图须满足:未被回收;宽和高均在 1 至 2048 像素之间;占用内存(Bitmap.getAllocationByteCount())不超过 8 MB(8388608 字节)。不满足时 picture、glyph 抛出 IllegalArgumentException。
卡片上的图片(卡片左图、头像、标题小图、进度小图、对称标志)不接受 appIcon():显示来源栏时,来源栏已显示应用图标与名称;用户关闭「显示应用来源」且卡片没有内容图片时,星河岛在卡片左侧显示应用图标。
enum class BuiltinSymbol:MUSIC(音乐)、TIMER(计时器)、ALARM(闹钟)、BATTERY(电池)、BOLT(闪电)、HEADPHONES(耳机)、BLUETOOTH(蓝牙)、MESSAGE(消息)、CHECK(对勾)、CLOSE(叉号)、PLAY(播放)、PAUSE(暂停)、SKIP_NEXT(下一首)、SKIP_PREV(上一首)、NAVIGATION(方向箭头)、HOURGLASS(沙漏)、INFO(提示)、DOWNLOAD(下载)。
IslandCard(展开卡片)
sealed class IslandCard { abstract val title: String }九种子类:GenericCard、ProgressCard、EmphasisCard、DetailsCard、StatusCard、PictureCard、MediaCard、MessageCard、MirrorCard,均通过各自的 Builder 生成。
所有卡片的共同规则:
- 用户开启「显示应用来源」时,卡片顶部由星河岛写上来源栏:本应用的图标与名称(名称取自系统,应用无法修改);设置了发送时间时在来源栏右侧写出时间。该开关位于星流「显示规则」页,默认关闭;关闭后不显示来源栏,卡片左侧没有内容图片时改为显示应用图标。
- 卡片左侧的图片只放内容自己的图片(头像、封面、商品图、符号),不接受应用图标。
- 文字长度按 UTF-16 字符计:标题最多 128 个字符,说明最多 256 个字符,正文最多 4096 个字符,其余短文字最多 32 个字符。必填文字不能为空白。
- 所有
setXxx方法传入null表示不显示该项。 - 文字不合规时,对应的
Builder构造方法或setXxx方法立即抛出IllegalArgumentException;组合规则(按钮数量、必填项等)在build()时检查。
GenericCard(通用)
左侧图片,标题(右侧可放大显示一项数值或时间),说明一行,正文最多两行,底部按钮。
GenericCard.Builder(title: String)
| 方法 | 说明 |
|---|---|
setSubtitle(subtitle: String?) | 说明,最多 256 个字符 |
setBody(body: String?) | 正文,最多 4096 个字符,卡片上最多显示两行 |
setImage(image: IslandImage?) | 左侧图片 |
setValue(value: CardValue?) | 标题右侧放大显示的一项 |
setTag(tag: CardTag?) | 说明后面的小标签 |
setTitleMark(mark: IslandImage?) | 标题后面的小图(例如完成时的对勾) |
addButton(button: IslandButton) / setButtons(buttons: List<IslandButton>) | 添加一个按钮 / 替换全部按钮;可用 TextButton、IconButton、BarIconButton、ToggleButton |
build(): GenericCard | 按钮种类或数量超出上限、编号重复时抛出 IllegalArgumentException |
属性:title、subtitle、body、image、value、tag、titleMark。
CardValue(静态工厂方法):text(text: String, color: Int? = null, icon: IslandImage? = null)(数值,最多 32 个字符;颜色为 null 时使用强调色,过暗的颜色会被提亮;icon 为数值前的小图);countdown(endAtMillis: Long);stopwatch(startedAtMillis: Long)。
CardTag:CardTag(text: String?, icon: IslandImage? = null)。文字最多 32 个字符;文字与图标都为 null 时抛出 IllegalArgumentException。属性:text、icon。
ProgressCard(进度)
左侧图片,标题(右侧自动显示百分比),说明与正文,底部一条进度条;进度条可分阶段并在下方写阶段名,也可带一个随进度移动的小图(例如骑手)。适用于外卖、打车、下载、上传等。
ProgressCard.Builder(title: String)
| 方法 | 说明 |
|---|---|
setSubtitle(subtitle: String?) | 说明,最多 256 个字符 |
setBody(body: String?) | 正文,最多 4096 个字符,卡片上显示一行 |
setImage(image: IslandImage?) | 左侧图片 |
setProgress(fraction: Float) | 确定的进度,0 至 1 |
setIndeterminate() | 进度不确定:进度条上一段亮条来回移动 |
setLabels(start: String?, end: String?) | 进度条下方左端与右端的文字,各最多 32 个字符;设置了阶段名时不可用 |
setStages(stages: List<String>) | 各阶段名称,2 至 16 个(传空列表表示清除),每个最多 32 个字符。进度条按阶段数平均分段、在分界处画节点;三个以上阶段时每个名称写在对应节点下方,两个阶段时写在两端 |
setMarker(marker: IslandImage?) | 随进度移动的小图(例如骑手、车辆),显示在强调色圆形底上 |
addButton / setButtons | 可用 TextButton、IconButton、BarIconButton、ToggleButton |
build(): ProgressCard | 未调用 setProgress 或 setIndeterminate;阶段名与两端文字同时设置;进度不确定时设置了阶段名;按钮超出上限时抛出 IllegalArgumentException |
属性:title、subtitle、body、image、fraction: Float?(null 表示进度不确定)、startLabel、endLabel、stages: List<String>、marker。
EmphasisCard(强调)
一张卡里最要紧的一串码或一段计时放大显示。
- 码(
EmphasisValue.code):标题作为上方一行小字写明是什么(例如「取件码」),码放大写在下方,说明与正文写在码下面。 - 计时(倒计时、正计时、已暂停):左侧图片(未设置时为计时符号),标题与说明写在放大的时间上方,正文写在时间下方,右侧可放
TimerControl控制按钮与圆形图标按钮。
EmphasisCard.Builder(title: String, value: EmphasisValue)
| 方法 | 说明 |
|---|---|
setSubtitle(subtitle: String?) | 说明,最多 256 个字符 |
setBody(body: String?) | 正文,最多 4096 个字符 |
setImage(image: IslandImage?) | 左侧图片 |
addControl(control: TimerControl) | 添加一个计时控制按钮,仅计时可用,按加入顺序排列 |
addButton / setButtons | 可用 TextButton、IconButton、BarIconButton、ToggleButton |
build(): EmphasisCard | 码设置了计时控制按钮,或按钮超出上限时抛出 IllegalArgumentException |
属性:title、value、subtitle、body、image、controls: List<TimerControl>。
EmphasisValue(静态工厂方法):code(text: String)(最多 32 个字符);countdown(endAtMillis: Long)(到点停在 00:00);stopwatch(startedAtMillis: Long);paused(durationMillis: Long)(已暂停的计时,静止显示给定时长,格式 mm:ss,满一小时为 h:mm:ss;时长不能为负数)。属性 isTimer: Boolean:是否为计时。
DetailsCard(明细)
通用卡片的排布,底部并排若干格(上方名称、下方数值),例如违章的车牌与时间、电影的场次与座位。
DetailsCard.Builder(title: String)
| 方法 | 说明 |
|---|---|
setSubtitle / setBody / setImage | 同通用卡片 |
addDetail(detail: CardDetail) / addDetail(label: String, value: String) | 添加一格明细 |
setTag(tag: CardTag?) | 说明后面的小标签 |
setTitleMark(mark: IslandImage?) | 标题后面的小图 |
addButton / setButtons | 可用 TextButton、IconButton、BarIconButton、ToggleButton |
build(): DetailsCard | 明细不在 1 至 6 格之间,或按钮超出上限时抛出 IllegalArgumentException |
属性:title、subtitle、body、image、details: List<CardDetail>、tag、titleMark。
CardDetail:CardDetail(label: String, value: String),名称与数值各最多 32 个字符。属性:label、value。
StatusCard(状态)
左侧图片,标题与说明,右侧放大显示一项数值或正计时,底部可带一条电量式的水平条;正文写在下方,最多两行。适用于设备连接、运行状态等。
StatusCard.Builder(title: String)
| 方法 | 说明 |
|---|---|
setSubtitle / setBody / setImage | 同通用卡片 |
setValue(value: StatusValue?) | 右侧放大显示的一项 |
setLevel(level: Float?) | 底部水平条的比例,0 至 1 |
setStopButton(show: Boolean) | 显示红色停止圆钮;点击后 onAction 收到按钮编号 StatusCard.ACTION_STOP("stop") |
addButton / setButtons | 可用 TextButton、IconButton、BarIconButton、ToggleButton |
build(): StatusCard | 按钮超出上限时抛出 IllegalArgumentException(停止圆钮计入圆形按钮) |
属性:title、subtitle、body、image、value、level: Float?、stopButton: Boolean。伴生常量:const val ACTION_STOP: String = "stop"。
StatusValue(静态工厂方法):text(text: String)(最多 32 个字符,例如「85%」「已连接」);stopwatch(startedAtMillis: Long)。
PictureCard(大图)
标题与一行正文,下方一张铺满卡片宽度的大图(最高约 140dp,超出部分居中裁切)。只有一个文字按钮时,按钮显示在标题右侧。锁屏只显示标题时不显示大图。
PictureCard.Builder(title: String, picture: IslandImage):picture 须为 IslandImage.picture,否则抛出 IllegalArgumentException。
| 方法 | 说明 |
|---|---|
setBody(body: String?) | 正文,最多 4096 个字符,卡片上显示一行 |
addButton / setButtons | 可用 TextButton、BarIconButton、ToggleButton |
build(): PictureCard | 使用了圆形图标按钮,或按钮超出上限时抛出 IllegalArgumentException |
属性:title、picture、body。
MediaCard(音乐)
左侧封面,歌名与歌手,一行歌词,播放按键与进度条。进度由星河岛按播放状态与速度自行推进。播放按键排在右侧或歌词下方,由用户在星流「星河岛歌词」页选择的「音乐卡片样式」决定,应用无需处理。
MediaCard.Builder(title: String):title 为歌名,最多 128 个字符。
| 方法 | 说明 |
|---|---|
setArtist(artist: String?) | 歌手,最多 256 个字符 |
setCover(cover: IslandImage?) | 封面,须为 IslandImage.picture;为 null 时显示音符占位 |
setPlaying(playing: Boolean) | 是否正在播放:决定播放键的图形与进度是否走动。默认 false |
setProgress(durationMillis: Long, positionMillis: Long, atMillis: Long = System.currentTimeMillis(), speed: Float = 1f) | 播放进度:总时长大于 0;位置在 0 至总时长之间;atMillis 为取得位置的时刻(大于 0);速度在 -16 至 16 之间 |
setLyric(lyric: String?) | 当前一句歌词,最多 512 个字符;为 null 时歌词行留空 |
addControl(control: MediaControl) | 仅加入应用实际支持的播放操作;未加入的按键不可操作 |
setSeekable(seekable: Boolean) | 进度条可拖动,松手位置由 onSeek 交给应用。须先设置播放进度 |
build(): MediaCard | 可拖动但未设置播放进度时抛出 IllegalArgumentException |
属性:title、artist、cover、playing、durationMillis: Long?、positionMillis: Long?、positionAtMillis: Long?、playbackSpeed: Float、lyric、controls: Set<MediaControl>、seekable。音乐卡片不接受其他按钮。
MessageCard(消息)
左侧头像,发送者与最新一条消息(最多两行),可带回复输入框与按钮。消息卡片按新消息排位:刚送达时优先显示在主岛,停留一段时间后让位;设置了发送时间时,发送时间变化才算新的一条,未设置时标题或消息内容变化才算。
MessageCard.Builder(sender: String, text: String):发送者最多 128 个字符;消息内容最多 4096 个字符,卡片上最多显示两行。
| 方法 | 说明 |
|---|---|
setAvatar(avatar: IslandImage?) | 头像 |
setReplyEnabled(enabled: Boolean) | 显示回复输入框,用户发送的文字由 onReply 交给应用;锁屏时不显示输入框。编辑或发送期间,新消息不替换当前回复卡片;未交给应用的文字保留为草稿 |
addButton / setButtons | 可用 TextButton、BarIconButton、ToggleButton |
build(): MessageCard | 使用了圆形图标按钮,或按钮超出上限时抛出 IllegalArgumentException |
属性:title(发送者)、text、avatar、replyEnabled。
MirrorCard(对称)
左右两侧各写一个名称(可带标志与小字),中间放大显示两侧的比分,下方一行写比赛信息。尚无比分时,中间放大显示 setCenterText 设置的文字(例如「19:30 开赛」)。卡片不显示按钮。
MirrorCard.Builder(title: String, left: MirrorSide, right: MirrorSide):title 不单独显示在卡片上,用于无障碍读屏。
| 方法 | 说明 |
|---|---|
setCenterText(text: String?) | 尚无比分时中间放大显示的文字,最多 32 个字符;设置后不显示比分 |
setDetail(detail: String?) | 下方一行小字(例如赛事与比赛阶段),最多 128 个字符 |
build(): MirrorCard | 未设置中间文字时两侧缺少比分,抛出 IllegalArgumentException |
属性:title、left、right、centerText、detail。
MirrorSide:MirrorSide(name: String, score: String? = null, logo: IslandImage? = null, note: String? = null)。名称、比分、小字各最多 32 个字符;logo 为名称上方的标志。属性:name、score、logo、note。
按钮
sealed class IslandButton(val id: String, val requiresUnlock: Boolean)用户点击后,onAction 收到内容编号与按钮编号。requiresUnlock = true 时,锁屏状态下隐藏此按钮。
按钮编号:非空白,最多 64 个字符,同一张卡片内不得重复;不得使用 SDK 保留的编号 pause、resume、stop、toggle、prev、play_pause、next。违反时构造方法或 build() 抛出 IllegalArgumentException。
| 类 | 构造方法 | 说明 |
|---|---|---|
TextButton | TextButton(id: String, label: String, style: ButtonStyle = NORMAL, icon: IslandImage? = null, fillColor: Int? = null, requiresUnlock: Boolean = false) | 文字按钮,可在文字前带小图标。排在卡片底部,默认每排三个、最多四个,排法见「按钮排法」。label 最多 32 个字符。fillColor 为自定义底色(ARGB),仅 NORMAL 样式可用:不透明度过半为实心底,否则为浅色底;白色、完全透明或在深色卡片上看不清的深色按普通灰色底显示 |
IconButton | IconButton(id: String, icon: IslandImage, description: String, requiresUnlock: Boolean = false) | 圆形图标按钮,显示在卡片第一行右侧,灰色圆形底。description 为读屏说明,最多 32 个字符 |
BarIconButton | BarIconButton(id: String, icon: IslandImage, description: String, requiresUnlock: Boolean = false) | 底部图标按钮:只有图标、没有文字,在卡片底部另起一排并列显示。description 最多 32 个字符 |
ToggleButton | ToggleButton(id: String, label: String, checked: Boolean, icon: IslandImage? = null, requiresUnlock: Boolean = false) | 开关按钮:在卡片底部并排成一排,打开时以强调色显示。点击后星河岛不会自行切换状态,请在 onAction 中处理后用同一内容编号更新 checked |
各类属性与构造参数同名。
enum class ButtonStyle { NORMAL, PRIMARY, DESTRUCTIVE }NORMAL:灰色底;PRIMARY:强调色实心底,用于最主要的操作;DESTRUCTIVE:浅红底红字,用于删除、取消等操作。
enum class TimerControl(val actionId: String) { PAUSE("pause"), RESUME("resume"), STOP("stop") }计时类强调卡片右侧的圆形控制按钮:PAUSE 暂停(强调色实心圆钮),RESUME 继续(强调色实心圆钮),STOP 结束(灰色圆钮,叉号)。
enum class MediaControl(val actionId: String) { PREVIOUS("prev"), PLAY_PAUSE("play_pause"), NEXT("next") }音乐卡片的播放按键:上一首、播放或暂停(图形随播放状态切换)、下一首。
数量上限(每张卡片):
| 种类 | 上限 |
|---|---|
文字按钮 TextButton | 4 |
圆形按钮(IconButton,以及 TimerControl、状态卡片停止圆钮) | 3 |
底部图标按钮 BarIconButton | 4 |
| 以上三类合计 | 4 |
开关按钮 ToggleButton | 3(另计) |
各卡片可用的按钮:
| 卡片 | TextButton | IconButton | BarIconButton | ToggleButton | 固定按钮 |
|---|---|---|---|---|---|
| 通用、进度、明细 | 可用 | 可用 | 可用 | 可用 | 无 |
| 强调 | 可用 | 可用 | 可用 | 可用 | TimerControl(仅计时) |
| 状态 | 可用 | 可用 | 可用 | 可用 | 停止圆钮 |
| 大图、消息 | 可用 | 不可用 | 可用 | 可用 | 无 |
| 音乐 | 不可用 | 不可用 | 不可用 | 不可用 | MediaControl |
| 对称 | 不可用 | 不可用 | 不可用 | 不可用 | 无 |
按钮的具体位置由星河岛按卡片排布决定:例如只有一个文字按钮且第一行右侧空闲时,它显示为第一行右侧的小按钮。底部文字按钮的排法可用 setButtonLayout 调整,见「按钮排法」。
按钮排法
底部带字的按钮默认每排 3 个、各占三分之一;4 个时平均分两排、各两个;一排里只剩 1 个时占半排居中。可用卡片构建器的 setButtonLayout 按卡修改,不设置时按默认排法。
class ButtonLayout @JvmOverloads constructor(
val perRow: Int = 3,
val rowFill: RowFill = RowFill.EQUAL,
val loneFill: LoneFill = LoneFill.HALF,
val loneAlign: LoneAlign = LoneAlign.CENTER,
)| 参数 | 取值 | 说明 |
|---|---|---|
perRow | 1 至 4 | 一排最多几个文字按钮;超出范围时构造方法抛出 IllegalArgumentException |
rowFill | EQUAL(默认)、WEIGHT、CONTENT | 一排里按钮的宽度怎么分:等分;带底色的按钮(PRIMARY 或设置了 fillColor 的文字按钮)占两份宽,其余平分剩下的宽度;按文字长短排 |
loneFill | HALF(默认)、FULL、CONTENT | 一排里只剩一个按钮时占多宽:半排、整排、按文字长短 |
loneAlign | START、CENTER(默认)、END | 只剩一个按钮时靠左、居中、靠右;loneFill = FULL 时不生效 |
GenericCard.Builder("停车计费")
.addButton(TextButton("pay", "缴费", ButtonStyle.PRIMARY))
.addButton(TextButton("later", "稍后"))
.addButton(TextButton("detail", "详情"))
.setButtonLayout(ButtonLayout(perRow = 3))
.build()- 有底部文字按钮的卡片(通用、进度、强调、明细、状态、大图、消息)都可以设置;音乐与对称卡片没有文字按钮。
- 只影响底部排开的文字按钮。圆形按钮、底部图标按钮(一排最多 4 个)与开关(单独一排)不按这套排法。
- 四个是文字按钮的总数上限;每排个数大于按钮总数时按实际数量排。
- 设置只在 0.1.2 及以上的星河岛生效;旧版星河岛读不到这项设置,仍按每排两个排,不会报错。