自定义notification布局,加仿消息通知悬浮效果,加通知中控件点击事件 刷新界面的代码实现。

本文介绍了一种自定义Android通知栏的方法,通过创建NotificationChannel,使用RemoteViews设置自定义布局,并通过PendingIntent响应不同按钮操作。文章详细展示了如何在Android Oreo及以上版本中解决通知不显示的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一部分java文件:
package com.lenovo.dinghao1.mydialog.notification;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.support.v4.app.NotificationCompat;
import android.widget.RemoteViews;

import com.lenovo.dinghao1.mydialog.R;

public class MyNotification {
    private Context mContext;
    private NotificationManager notificationManager =null;
    private Notification mNotification = null;

    public MyNotification(Context context){
        mContext = context;
        init();
    }

    private void init(){
        IntentFilter intent = new IntentFilter();
        intent.addAction("android.intent.action_MTP");
        intent.addAction("android.intent.action_PTP");
        intent.addAction("android.intent.action_CHAR");
        mContext.registerReceiver(new MyNotificationReceiver(),intent);

    }

    public void createCustomNotification(int code,String channel_id,String channel_name){
        notificationManager = (NotificationManager) mContext.getApplicationContext().getSystemService(mContext.NOTIFICATION_SERVICE);
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            NotificationChannel channel = new NotificationChannel(channel_id,channel_name, NotificationManager.IMPORTANCE_HIGH);
            channel.setLightColor(R.color.account_item_add);
            channel.canShowBadge();
            channel.enableVibration(false);
            channel.getGroup();
            channel.shouldShowLights();
            notificationManager.createNotificationChannel(channel);
        }
        Notification.Builder builder = getBuilder(channel_id,"title","this is noti!");
        builder.setDefaults(NotificationCompat.FLAG_ONLY_ALERT_ONCE);
        RemoteViews remoteViews = null;

        remoteViews = new RemoteViews(mContext.getApplicationContext().getPackageName(),R.layout.notifaction_layout);
        if(remoteViews==null){
            return;
        }
        builder.setCustomContentView(remoteViews);

        Intent intentMtp = new Intent();
        intentMtp.setAction("android.intent.action_MTP");
        PendingIntent pendingIntentMtp = PendingIntent.getBroadcast(mContext.getApplicationContext(),-1,intentMtp,PendingIntent.FLAG_UPDATE_CURRENT);
        remoteViews.setOnClickPendingIntent(R.id.btMpt,pendingIntentMtp);

        Intent intentPtp = new Intent();
        intentPtp.setAction("android.intent.action_PTP");
        PendingIntent pendingIntentPtp = PendingIntent.getBroadcast(mContext.getApplicationContext(),-1,intentPtp,PendingIntent.FLAG_UPDATE_CURRENT);
        remoteViews.setOnClickPendingIntent(R.id.btPtp,pendingIntentPtp);

        Intent intentCharg = new Intent();
        intentCharg.setAction("android.intent.action_CHAR");
        PendingIntent pendingIntentCharg = PendingIntent.getBroadcast(mContext.getApplicationContext(),-1,intentCharg,PendingIntent.FLAG_UPDATE_CURRENT);
        remoteViews.setOnClickPendingIntent(R.id.btCharging,pendingIntentCharg);

        mNotification = builder.build();
        notificationManager.notify(1000,mNotification);
    }

    public  Notification.Builder getBuilder(String channel_id,String title,String context){
        return new Notification.Builder(mContext.getApplicationContext())
                .setAutoCancel(false)
                .setChannelId(channel_id)
                .setContentTitle(title)
                .setContentText(context)
                .setAutoCancel(true)
                .setWhen(0)
                .setOngoing(true)
                .setTicker("ticker")
                .setDefaults(0)
                .setSmallIcon(R.mipmap.ic_launcher);
    }


    private class MyNotificationReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
              if(intent!=null){
                  if("android.intent.action_MTP".equals(intent.getAction())){
                      mNotification.contentView.setTextColor(R.id.btMpt,mContext.getResources().getColor(R.color.colorPrimary));
                      mNotification.contentView.setTextColor(R.id.btPtp,mContext.getResources().getColor(R.color.default_bt));
                      mNotification.contentView.setTextColor(R.id.btCharging,mContext.getResources().getColor(R.color.default_bt));
                      notificationManager.notify(1000,mNotification);
                  }else if("android.intent.action_PTP".equals(intent.getAction())){
                      mNotification.contentView.setTextColor(R.id.btMpt,mContext.getResources().getColor(R.color.default_bt));
                      mNotification.contentView.setTextColor(R.id.btPtp,mContext.getResources().getColor(R.color.colorPrimary));
                      mNotification.contentView.setTextColor(R.id.btCharging,mContext.getResources().getColor(R.color.default_bt));
                      notificationManager.notify(1000,mNotification);
                  }else if("android.intent.action_CHAR".equals(intent.getAction())){
                      mNotification.contentView.setTextColor(R.id.btMpt,mContext.getResources().getColor(R.color.default_bt));
                      mNotification.contentView.setTextColor(R.id.btPtp,mContext.getResources().getColor(R.color.default_bt));
                      mNotification.contentView.setTextColor(R.id.btCharging,mContext.getResources().getColor(R.color.colorPrimary));
                      notificationManager.notify(1000,mNotification);
                  }
              }
        }
    }

}

 

第二部分布局xml文件notifaction_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >
   <RelativeLayout
       android:id="@+id/rlNotiBg"
       android:layout_width="match_parent"
       android:layout_height="120dp"
       >
       <TextView
           android:id="@+id/btMpt"
           android:layout_width="130dp"
           android:layout_height="50dp"
           android:layout_alignParentLeft="true"
           android:layout_alignParentBottom="true"
           android:text="传文件"
           />
       <TextView
           android:id="@+id/btPtp"
           android:layout_width="130dp"
           android:layout_height="50dp"
           android:layout_centerInParent="true"
           android:layout_alignParentBottom="true"
           android:text="看照片"
           android:textColor="@color/colorPrimary"
           />
       <TextView
           android:id="@+id/btCharging"
           android:layout_width="130dp"
           android:layout_height="50dp"
           android:layout_alignParentRight="true"
           android:layout_alignParentBottom="true"
           android:text="仅充电"
           android:textColor="@color/colorPrimary"
           />
   </RelativeLayout>
</LinearLayout>

 

第三部分用法:

MyNotification myNotification = new MyNotification(mContext);
myNotification.createCustomNotification(1,"10000","adbcdefg");
注:已适配8.0以上通知不显示问题。

 

 

 

### Android实现秒表功能并处理悬浮窗影响 在开发具有秒表功能的应用程序时,如果涉及到悬浮窗的设计,则需特别关注权限管理、窗口布局以及生命周期管理等问题。 #### 权限声明与请求 为了创建和显示悬浮窗,在 `AndroidManifest.xml` 文件中应声明相应的权限: ```xml <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> ``` 对于 API Level 23 及以上版本,还需要动态向用户申请此权限[^1]。可以通过调用 `Settings.canDrawOverlays()` 方法来判断当前应用是否有绘制覆盖层的权限;如果没有,则引导用户前往设置页面授予权限。 #### 创建悬浮视图 定义一个自定义 View 或者使用现有的控件作为悬浮窗的内容,并通过 WindowManager 将其添到屏幕上。这里需要注意的是要合理配置 LayoutParams 参数以适应不同场景下的需求。 例如,可以这样初始化悬浮窗: ```java WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY : WindowManager.LayoutParams.TYPE_PHONE, // 针对 Oreo及以上 版本调整类型 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, PixelFormat.TRANSLUCENT); // 设置初始位置和其他属性... windowManager.addView(view,params); ``` #### 处理生命周期变化 由于秒表可能处于前台运行状态也可能被最小化至后台继续计时,因此需要妥善保存时间数据并在恢复时同步更新 UI 显示。这通常涉及 Activity/Service 的生命周期回调函数中的逻辑编写[^2]。 另外值得注意的是,“Remote Video”窗口作为一个特殊的全屏窗口,它不会响应鼠标事件,仅能通过底部任务栏进行切换操作[^3]。虽然这不是直接关于秒表的功能描述,但在设计多组件交互界面时同样值得借鉴——即某些特定类型的浮动元素可能会有独特的交互特性或限制条件。 #### 示例代码片段 下面给出一段简单的 Service 类用于维持秒表服务持续工作的同时允许展示悬浮窗控制面板: ```java public class StopwatchService extends Service { private Handler handler; private Runnable runnable; @Override public void onCreate() { super.onCreate(); handler = new Handler(Looper.getMainLooper()); runnable = () -> { updateUI(); // 更新界面上的时间数值 handler.postDelayed(runnable, 100); // 每隔一段时间刷新一次 }; startForeground(NOTIFICATION_ID, createNotification()); // 后台保持活跃 } @Override public int onStartCommand(Intent intent, int flags, int startId) { handler.removeCallbacks(runnable); handler.post(runnable); return START_STICKY; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值