Android Decorated通知中如何创建大尺寸播放/暂停按钮?
我帮你搞定这个问题!你现在用DecoratedMediaCustomViewStyle却只能显示小按钮,想要那种中间播放/暂停按钮超大的效果对吧?其实核心是利用这个样式的自定义布局能力,同时配合正确的MediaSession配置来实现。
为什么当前按钮是小的?
你直接用addAction()添加的按钮,在DecoratedMediaCustomViewStyle下默认是系统控制的小尺寸样式。想要自定义按钮大小,必须用自定义布局替代默认的Action区域,这也是官方推荐这个样式的核心原因——兼顾系统适配和自定义UI的灵活性。
解决方案步骤
1. 创建自定义媒体通知布局
先写一个XML布局文件(比如res/layout/media_notification_control.xml),专门用来放置你的大尺寸按钮:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="16dp" android:gravity="center"> <!-- 后退按钮(稍小尺寸) --> <ImageButton android:id="@+id/btn_seek_prev" android:layout_width="48dp" android:layout_height="48dp" android:src="@drawable/prev10w" android:background="?attr/selectableItemBackgroundBorderless" android:contentDescription="后退10秒" /> <!-- 播放/暂停按钮(大尺寸) --> <ImageButton android:id="@+id/btn_play_pause" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginHorizontal="32dp" android:src="@drawable/ic_pause_white" android:background="?attr/selectableItemBackgroundBorderless" android:contentDescription="播放/暂停" /> <!-- 前进按钮(稍小尺寸) --> <ImageButton android:id="@+id/btn_seek_next" android:layout_width="48dp" android:layout_height="48dp" android:src="@drawable/next10w" android:background="?attr/selectableItemBackgroundBorderless" android:contentDescription="前进10秒" /> </LinearLayout>
这里把播放/暂停按钮设为64dp(比前后按钮大),同时用selectableItemBackgroundBorderless给按钮添加上原生的点击反馈效果。
2. 初始化自定义布局并绑定点击事件
在你的通知构建代码中,用RemoteViews加载这个布局,然后根据播放状态切换图标、绑定点击Intent:
// 加载自定义布局 RemoteViews customMediaView = new RemoteViews(getPackageName(), R.layout.media_notification_control); // 根据播放状态切换播放/暂停图标 if (statusPlay) { customMediaView.setImageViewResource(R.id.btn_play_pause, R.drawable.ic_pause_white); } else { customMediaView.setImageViewResource(R.id.btn_play_pause, R.drawable.ic_play_arrow_white); } // 绑定按钮点击事件 customMediaView.setOnClickPendingIntent(R.id.btn_seek_prev, lPendingSeekPrevIntent); customMediaView.setOnClickPendingIntent(R.id.btn_play_pause, statusPlay ? lPendingPauseIntent : lPendingPlayIntent); customMediaView.setOnClickPendingIntent(R.id.btn_seek_next, lPendingSeekNextIntent);
3. 修改通知构建代码,应用自定义布局
现在把原来的addAction()代码移除,改用自定义布局,同时保留DecoratedMediaCustomViewStyle的系统适配能力:
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { NotificationCompat.Builder builder = new NotificationCompat.Builder(this, FOREGROUND_CHANNEL_ID) .setSmallIcon(R.drawable.ic_books_mini2) .setContentTitle(tmpTitle) .setContentText(notificationPercentage + "% " + tmpAuthor) .setLargeIcon(artwork) .setCategory(NotificationCompat.CATEGORY_TRANSPORT) .setStyle(new androidx.media.app.NotificationCompat.DecoratedMediaCustomViewStyle() .setMediaSession(mediaSession.getSessionToken()) ) // 设置自定义布局(折叠和展开状态共用一个布局,也可以分开设置不同布局) .setCustomContentView(customMediaView) .setCustomBigContentView(customMediaView) .setPriority(NotificationCompat.PRIORITY_DEFAULT) // 把优先级从LOW改成DEFAULT,避免系统压缩布局 .setColorized(true) .setContentIntent(pendingIntent) .setAutoCancel(true) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setOngoing(true); notification = builder.build(); }
注意:这里移除了setShowActionsInCompactView(),因为我们已经用自定义布局替代了默认的Action区域。另外把优先级改成DEFAULT,低优先级的通知可能会被系统压缩显示,导致按钮变小。
4. 确保MediaSession配置正确
DecoratedMediaCustomViewStyle需要和MediaSession配合才能更好地适配系统(比如锁屏控制、系统媒体控件联动),所以要确保你的MediaSession设置了正确的播放状态:
// 构建播放状态对象 PlaybackStateCompat playbackState = new PlaybackStateCompat.Builder() .setState( statusPlay ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED, currentPlaybackPosition, // 传入当前播放位置 1.0f // 播放速度 ) .setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS | PlaybackStateCompat.ACTION_SKIP_TO_NEXT) .build(); // 给MediaSession设置播放状态 mediaSession.setPlaybackState(playbackState);
5. 检查通知渠道配置
确保你的前台通知渠道是用IMPORTANCE_DEFAULT创建的,低重要性的渠道也会影响通知的显示效果:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel mediaChannel = new NotificationChannel( FOREGROUND_CHANNEL_ID, "媒体播放", NotificationManager.IMPORTANCE_DEFAULT ); mediaChannel.setDescription("媒体播放前台通知"); mediaChannel.setShowBadge(false); mediaChannel.setSound(null, null); // 可选:关闭通知声音 NotificationManager notificationManager = getSystemService(NotificationManager.class); notificationManager.createNotificationChannel(mediaChannel); }
这样改完之后,你的通知就能显示出大尺寸的播放/暂停按钮了,同时还能保留DecoratedMediaCustomViewStyle带来的系统适配优势。
内容的提问来源于stack exchange,提问作者Stefan

