• RemoteViews 整理


    前言

    RemoteViews表面意思就是远程的view,这个就很难理解了,远程的view。但是英语是抽象,remote本身就是偏僻的,偏远的意思。
    所以remoteViews 就是地方view,天高皇帝远,要管理地方的view就需要下达圣旨了。
    用途:一般就是通知栏与桌面小部件。
    通知栏好理解,微信通知经常见到。
    桌面小部件,这个无论是苹果还是按照,都有这个东西。

    这些就是系统自带的,然后我们也可以自己开发,但是这东西用的并不多,也有特定的app专门做这个,可以把桌面定制的吊炸天。

    正文

    如果说起这个remoteView,就必须提到一个巡按,这个巡按的名字就叫做pendingIntent。古时候,有些君主会留一个巡按在某一个地方,如果发生了一些大事,就要禀报一下。
    remoteView 天高皇帝远,皇帝就要派一个自己人去体察民情,反馈和禀报。因为无法通过findViewById去直接控制地方,所以呢,当remoteView去上任的时候呢,一般都会带上pendingIntent。
    pendingIntent 走的时候呢,一般要带上一个intent。比如皇帝派下去一个pendingIntent 和 remoteView 去上任,remoteView 年轻力壮,怕自己不在了,所以走得时候下了一封密旨给pendingIntent。
    当用户点击的时候,pendingIntent就带上intent发给中央,留下老皇帝触发用户点击通知栏事件后续要做的事情,大概就是这么一个理。

    notification

    remoteView 其中一个应用就是通知栏。在通知栏的api(android 不同版本有不同的api,比如说android4.4的api就是19)中,因为api的变换,导致了需要根据不同版本去书写不同的code,美其名曰:兼容。

    简单的通知就是这样:

    public void createNotify(View view) {
    	Intent resultIntent = new Intent(this, MainActivity.class);
    	TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
    	stackBuilder.addParentStack(MainActivity.class);
    	stackBuilder.addNextIntent(resultIntent);
    	PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
    	NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
            /*
    	 使用Builder构造器来创建Notification对象
    	*/
    	Notification notification = new NotificationCompat.Builder(this, "defult")
    			//指定通知的标题内容
    			.setContentTitle("Hello Word")
    			//设置通知的内容
    			.setContentText("This is just text")
    			//指定通知被创建的时间
    			.setWhen(System.currentTimeMillis())
    			//设置通知的小图标
    			.setSmallIcon(R.drawable.ic_launcher_foreground)
    			//设置通知的大图标
    			.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_background))
    			//添加点击跳转通知跳转
    			.setContentIntent(resultPendingIntent)
    			//实现点击跳转后关闭通知
    			.setAutoCancel(true)
    			.build();
    			//id 固定只能是通知到这个通知块,可更新
    			notificationManager.notify(1, notification);
    }
    

    效果:

    然后定制是这样的:
    我们需要制定界面:

    <?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="80dp"
        >
        <ImageView
            android:layout_width="80dp"
            android:layout_height="match_parent"
            android:id="@+id/icon"
            android:src="@color/colorPrimary"
            />
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            >
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="title"
                android:textSize="20dp"
                android:id="@+id/title"
                android:layout_marginLeft="20dp"
                android:gravity="center|left"
                />
            <TextView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="content"
                android:textSize="18dp"
                android:id="@+id/content"
                android:layout_marginLeft="40dp"
                android:gravity="center|left"
                />
        </LinearLayout>
    </LinearLayout>
    

    然后通过remoteViews 来建立他们之间的沟通。
    其实简单来说,我们的通知消息就是一个app,通过remoteViews 实现了我们app和通知栏app之间的沟通。
    下面是实现code:

    public void createCustomNotify(View view) {
    	Intent resultIntent = new Intent(this, MainActivity.class);
    	TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
    	stackBuilder.addParentStack(MainActivity.class);
    	stackBuilder.addNextIntent(resultIntent);
    	PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
    
    	NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
       /*
    	 使用Builder构造器来创建Notification对象
    	*/
    	RemoteViews remoteView =new RemoteViews(getPackageName(),R.layout.notification_layout);
    	remoteView.setImageViewResource(R.id.icon,R.drawable.ic_launcher_foreground);
    	remoteView.setTextViewText(R.id.title,"标题");
    	remoteView.setTextViewText(R.id.content,"内容");
    	Notification notification = new NotificationCompat.Builder(this, "defult")
    			.setContent(remoteView)
    			//指定通知被创建的时间
    			.setWhen(System.currentTimeMillis())
    			//设置通知的小图标
    			.setSmallIcon(R.drawable.ic_launcher_foreground)
    			//设置通知的大图标
    			.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_background))
    			//添加点击跳转通知跳转
    			.setContentIntent(resultPendingIntent)
    			.setShowWhen(true)
    			//实现点击跳转后关闭通知
    			.setAutoCancel(true)
    			.build();
    
    	//id 固定只能是通知到这个通知块,可更新
    	notificationManager.notify(2, notification);
    }
    

    效果:

    非常不好看哈。
    如果是这样的自定义,只是界面上的花哨,我们可以点击图片后然后执行一些东西这样才能体现定义。
    remoteViews 比如说通知通过intent,然后会用startActivity 去执行intent,所以打开了。
    然后同样自定义的同样可以通过intent,在这里,假如自定义layout上有多个的事件,单纯去startActivity效果就无法实现了。
    但是如果我们能监听到这个intent那么很多问题就简单了。
    创建广播监听:

    public class myBroadcastReceiver extends BroadcastReceiver {
        public  static  final  String actionImage="imageCallback";
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (actionImage.equals(actionImage))
            {
                Toast.makeText(context,"do this",Toast.LENGTH_SHORT).show();
            }
        }
    }
    

    然后再去创建监听:

    private void init()
    {
    	myBroadcastReceiver = new myBroadcastReceiver();
    	IntentFilter intentFilter = new IntentFilter(myBroadcastReceiver.actionImage);
    	registerReceiver(myBroadcastReceiver, intentFilter);
    }
    

    最后只有设置绑定,也就是说用户点击某些事件后。

        public void createCustomNotify(View view) {
            Intent resultIntent = new Intent(this, MainActivity.class);
            TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
            stackBuilder.addParentStack(MainActivity.class);
            stackBuilder.addNextIntent(resultIntent);
            PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
            NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
           /*
             使用Builder构造器来创建Notification对象
            */
            RemoteViews remoteView =new RemoteViews(getPackageName(),R.layout.notification_layout);
            remoteView.setImageViewResource(R.id.icon,R.drawable.ic_launcher_foreground);
            remoteView.setTextViewText(R.id.title,"标题");
            remoteView.setTextViewText(R.id.content,"内容");
            Intent imageIntent=new Intent(myBroadcastReceiver.actionImage);
            PendingIntent imagePintent=PendingIntent.getBroadcast(this,0,imageIntent,0);
            remoteView.setOnClickPendingIntent(R.id.icon,imagePintent);
            Notification notification = new NotificationCompat.Builder(this, "defult")
                    .setContent(remoteView)
                    //指定通知被创建的时间
                    .setWhen(System.currentTimeMillis())
                    //设置通知的小图标
                    .setSmallIcon(R.drawable.ic_launcher_foreground)
                    //设置通知的大图标
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_background))
                    //添加点击跳转通知跳转
                    .setContentIntent(resultPendingIntent)
                    .setShowWhen(true)
                    //实现点击跳转后关闭通知
                    .setAutoCancel(true)
                    .build();
    
            //id 固定只能是通知到这个通知块,可更新
            notificationManager.notify(2, notification);
        }
    

    关键部分就是:

    // 实例化一个intent
    Intent imageIntent=new Intent(myBroadcastReceiver.actionImage);
    // 绑定intent,并且以广播的形式执行
    PendingIntent imagePintent=PendingIntent.getBroadcast(this,0,imageIntent,0);
    // 在icon 点击的时候触发
    remoteView.setOnClickPendingIntent(R.id.icon,imagePintent);
    

    效果:

    总之就是这个套路了,但是到了android 8 套路就换了,多了一个notificationChannel。
    notificationChannel 这个东西用来做啥的呢?
    我理解是频道的意思,比如说通知,用户可以更好的管理,接收还是不接受通知。
    这东西就是来管理通知的,以前通知过于分散,设置一个id就是一个通知,然后用户不想要要一个一个去取消,同样开发者也麻烦。

        @RequiresApi(api = Build.VERSION_CODES.O)
        public void createNotificationChannel(String id, String name, int importance, String desc, String groupId) {
            if (mNotificationManager.getNotificationChannel(id) != null) return;
            NotificationChannel notificationChannel = new NotificationChannel(id, name, importance);
            notificationChannel.enableLights(true);
            notificationChannel.enableVibration(true);
            notificationChannel.setLightColor(Color.RED);
            notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
            notificationChannel.setShowBadge(true);
            notificationChannel.setBypassDnd(true);
            notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400});
            notificationChannel.setDescription(desc);
            notificationChannel.setGroup(groupId);
    //      notificationChannel.setSound();
            mNotificationManager.createNotificationChannel(notificationChannel);
        }
    

    上述中关键部分就两个一个是创建:

    NotificationChannel notificationChannel = new NotificationChannel(id, name, importance);
    mNotificationManager.createNotificationChannel(notificationChannel);
    

    然后加入进去。中间的基本都是设置了,比如设置分为一个组setGroup,给一些描述setDescription等,必须这个id 注册后才能用于通知中。

    Notification notification = new NotificationCompat.Builder(this, "defult")
    

    上面这个defult设置为上面注册的id就行。
    然后还有一个关键点:

    Notification notification = new NotificationCompat.Builder(this, "defult")
    

    可以设置角标,这就非常好了。在android 我们看到很少有应用可以有角标,基本上看到的只有qq,微信这些霸主才可以。实际上android 系统本身并没有开发,到了8才开发,但是腾讯和这些手机商有一些XXX,所以能拿到手机应用的角标。
    到了8后,就不需要了,google本身就支持了。

    总结

    RemoteViews 不是一种远程view,而是一种远程控制view的方式。

  • 相关阅读:
    品优购注册页
    品优购详情页---产品细节模块product_detail
    品优购详情页---产品详细信息区域 iteminfo_wrap
    poj 3684
    POJ 2785
    POJ 3185
    POJ 3279
    POJ 3276
    POJ 2566
    POJ 2100
  • 原文地址:https://www.cnblogs.com/aoximin/p/12228497.html
Copyright © 2020-2023  润新知