RemoteViews用来自定义通知栏通知的布局,这里着重介绍一下。
1.RemoteViews与Activity的区别
- RemoteViews主要用于通知栏部件和桌面部件,而Activity用于页面。
- RemoteViews只支持少数几种控件,如TextView,ImageView,Button,ImageButton,ProgressBar,Chronometer(计时器)和AnalogClock(模拟时钟)。
- RemoteViews不可直接获取和设置控件信息,只能通过该对象的set方法修改控件信息。
2.RemoteViews中的常用方法
- 构造函数:创建一个RemoteViews对象。第一个参数是包名,第二个参数是布局文件id。
- setViewVisibility:设置指定控件是否可见。
- setViewPadding:设置指定控件的间距。
- setTextViewText:设置指定TextView或Button控件的文字内容。
- setTextViewTextSize:设置指定TextView或Button控件的文字大小。
- setTextColor:设置指定TextView或Button控件的文字颜色。
- setTextViewCompoundDrawables:设置指定TextView或Button控件的文字周围图标。
- setImageViewResource:设置ImageView或ImageButton控件的资源编号。
- setImageViewBitmap:设置ImageView或ImageButton控件的位图对象。
- setChronometer:设置计时器信息。
- setProgressBar:设置进度条信息,包括最大值与当前进度。
- setOnClickPendingIntent:设置指定控件的点击相应动作。
3.使用举例
布局文件notify_music.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="64dp"
android:orientation="horizontal" >
<!-- 这是通知栏左侧的图标,仿千千静听 -->
<ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:scaleType="fitCenter"
android:src="@mipmap/tt" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="4"
android:layout_margin="3dp"
android:orientation="vertical" >
<!-- 这是展示歌曲播放进度的进度条 -->
<ProgressBar
android:id="@+id/pb_play"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:max="100"
android:progress="10" />
<!-- 这是正在播放的歌曲名称 -->
<TextView
android:id="@+id/tv_play"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
style="@style/NotificationTitle"
android:textSize="17sp" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical" >
<!-- 这是计数器,用于显示歌曲已经播放的时长 -->
<TextView
android:id="@+id/chr_play"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:gravity="center"/>
<!-- 这是控制按钮,用于歌曲的暂停与恢复操作 -->
<Button
android:id="@+id/btn_play"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3"
android:gravity="center"
android:background="@drawable/btn_nine_selector"
android:text="暂停"
android:textColor="@color/black"
android:textSize="15sp" />
</LinearLayout>
</LinearLayout>
引用的Activity
public class MainActivity extends AppCompatActivity {
private Button bt;
private String PAUSE_EVENT = ""; // “暂停/继续”事件的标识串
private NotificationManager notifyMgr;
private Handler handler;
private Runnable runnable;
private int progress;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt = findViewById(R.id.bt);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 从系统服务中获取通知管理器
notifyMgr = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
// 获取自定义消息的通知对象
handler = new Handler();
runnable = new Runnable() {
@Override
public void run() {
progress++;
Notification notify = getNotify(MainActivity.this, PAUSE_EVENT,
"雪绒花", true, progress, SystemClock.elapsedRealtime());
// 使用通知管理器推送通知,然后在手机的通知栏就会看到该消息
notifyMgr.notify(R.string.app_name, notify);
handler.postDelayed(runnable,1000);
}
};
handler.postDelayed(runnable,100);
}
});
}
private Notification getNotify(Context ctx, String event, String song, boolean isPlaying, int progress, long time) {
SimpleDateFormat format = new SimpleDateFormat("mm:ss");
// 创建一个广播事件的意图
Intent intent1 = new Intent(event);
//调用后只有8.0以上执行
createNotifyChannel(notifyMgr,this,"channel_id");
// 创建一个用于广播的延迟意图
PendingIntent broadIntent = PendingIntent.getBroadcast(
ctx, R.string.app_name, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
// 根据布局文件notify_music.xml生成远程视图对象
RemoteViews notify_music = new RemoteViews(ctx.getPackageName(), R.layout.notify_music);
if (isPlaying) { // 正在播放
notify_music.setTextViewText(R.id.btn_play, "暂停"); // 设置按钮文字
notify_music.setTextViewText(R.id.tv_play, song + "正在播放"); // 设置文本文字
notify_music.setTextViewText(R.id.chr_play,format.format(time)); // 设置计数器
} else { // 不在播放
notify_music.setTextViewText(R.id.btn_play, "继续"); // 设置按钮文字
notify_music.setTextViewText(R.id.tv_play, song + "暂停播放"); // 设置文本文字
notify_music.setTextViewText(R.id.chr_play,"00:00"); // 设置计数器
}
// 设置远程视图内部的进度条属性
notify_music.setProgressBar(R.id.pb_play, 100, progress, false);
// 整个通知已经有点击意图了,那要如何给单个控件添加点击事件?
// 办法是设置控件点击的广播意图,一旦点击该控件,就发出对应事件的广播。
notify_music.setOnClickPendingIntent(R.id.btn_play, broadIntent);
// 创建一个跳转到活动页面的意图
Intent intent2 = new Intent(ctx, MainActivity.class);
// 创建一个用于页面跳转的延迟意图
PendingIntent clickIntent = PendingIntent.getActivity(ctx,
R.string.app_name, intent2, PendingIntent.FLAG_UPDATE_CURRENT);
// 创建一个通知消息的构造器
Notification.Builder builder = new Notification.Builder(ctx);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Android 8.0开始必须给每个通知分配对应的渠道
builder = new Notification.Builder(this,"channel_id");
}
builder.setContentIntent(clickIntent) // 设置内容的点击意图
.setContent(notify_music) // 设置内容视图
.setTicker(song) // 设置状态栏里面的提示文本
.setSmallIcon(R.mipmap.tt_s); // 设置状态栏里的小图标
// 根据消息构造器构建一个通知对象
Notification notify = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
notify = builder.build();
}
return notify;
}
/**
* 创建通知渠道,Android8.0开始必须给每个通知分配对应的渠道
* @param notifyMgr
* @param ctx
* @param channelId
*/
private void createNotifyChannel(NotificationManager notifyMgr,Context ctx,String channelId){
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
//创建一个默认重要性的通知渠道
NotificationChannel channel = new NotificationChannel(channelId,"Channel",NotificationManager.IMPORTANCE_DEFAULT);
channel.setSound(null,null);
channel.setShowBadge(true);
channel.canBypassDnd();//可否绕过请勿打扰模式
channel.enableLights(true);//闪光
channel.setLockscreenVisibility(Notification.FLAG_ONLY_ALERT_ONCE);//锁屏显示通知
channel.canShowBadge();//桌面ICON是否可以显示角标
channel.getGroup();//获取通知渠道组
channel.shouldShowLights();//是否会闪光
notifyMgr.createNotificationChannel(channel);
}
}
}
大家可以参考这个写法,实现自己的需求。