android 桌面小部件(App Widgets)如何显示自定义的view
写过 桌面小部件的同学都知道,由于小部件是在在部件加载的,所以支持的view比较有限,用官方的原话说就是
Creating the App Widget layout is simple if you're familiar with Layouts. However, you must be aware that App Widget layouts are based on RemoteViews
, which do not support every kind of layout or view widget.
那怎么在小部件上显示一些比较复杂的view呢? 通过正统的路径肯定是不行了,除非你能改到rom,但是是通过改rom来实现,就会造成这个应用在其他机器上就无法正常运行了。
其实还有一个方法可以实现,就是。。。。。。。。。。一句话:
将要显示的view画在一张图片上,然后将图片设置给ImageView
废话不多说,用代码说话:
1:首先创建一个AppWidgets,这个网上代码很多。如果还不清楚的直接看
https://developer.android.com/guide/topics/appwidgets/index.html
2:修改AppWidgets布局文件,在合适的地方加入一个ImageView
2: 生成所需的图片 这边提供一个示例的方法,生成图片有很多种方法,只要能生成图片即可
private void handleActionUpdateAppWidget() { AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this); ComponentName thisWidget = new ComponentName(this, CustomViewAppWidget.class); int ids[] = appWidgetManager.getAppWidgetIds(thisWidget); if (ids == null || ids.length <= 0) { return; } int width = this.getResources().getDimensionPixelSize(R.dimen.custom_app_widget_image_width); int height = this.getResources().getDimensionPixelSize(R.dimen.custom_app_widget_image_height); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(getResources().getColor(R.color.custom_app_widget_line_color)); paint.setStrokeWidth(getResources().getDimensionPixelSize(R.dimen.custom_app_widget_line_width)); canvas.drawLine(0, 0, width / 2, height, paint); canvas.drawLine(width / 2, height, width, 0, paint); String path = saveBitmapToPic(this, "customview.png", bitmap);}private String saveBitmapToPic(Context context, String name, Bitmap b) { if (b == null) { return null; } context.deleteFile(name); FileOutputStream fos = null; try { fos = context.openFileOutput(name, Context.MODE_PRIVATE); //fos = new FileOutputStream(screenShotFile,Context.MODE_WORLD_READABLE); if (null != fos) { b.compress(Bitmap.CompressFormat.PNG, 100, fos); fos.flush(); fos.close(); return context.getFilesDir() + "/" + name; } } catch (Exception e) { e.printStackTrace(); } return null; }
3:将图片uri设置给imageview,然后更新appwidget
File newFile = new File(path); Uri imageUri = CustomViewFileProvider.getUriForFile(this, CustomViewFileProvider.AUTHORITIES, newFile); CharSequence widgetText = getString(R.string.appwidget_text); // Construct the RemoteViews object RemoteViews views = new RemoteViews(getPackageName(), R.layout.custom_view_app_widget); views.setTextViewText(R.id.appwidget_text, widgetText); views.setImageViewUri(R.id.appwidget_image, imageUri); // Instruct the widget manager to update the widget appWidgetManager.updateAppWidget(thisWidget, views);
这边顺便说2个问题: 1:有的同学会问:为什么不将图片的bitmap直接设置给ImageView?
答:因为bitmap通常比较大,RemoteViews在传输过程中其实是要挂进程传输的,系统用来跨进程传输的内存空间有限。如果bitmap的大小大于剩余空间的话,会造成AppWidget更新失败。
2:Android 7.0后,跨应用传递 file://
的URI,会异常,官方推荐使用FileProvider
。
但是FileProvider有个问题,他需要临时授权后,其他应用才能使用,但是AppWidgets的方式造成它无法临时授权桌面应用。
这个问题我找了半天,终于找到了一个方法,见:
http://android.wekeepcoding.com/article/13447169/Android%3A+loading+bitmap+from+local+storage+into+app+widget+(RemoteViews)
最终的效果如图:下面2条奇怪的V线就是画的:
老样子,完整代码请访问
https://github.com/bobohuang1985/android-utils-api
代码在utils.bobo.com.boboutils.App.appwidget包内
更多相关文章
- 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
- Android(安卓)Watchdog 机制
- Android—fragment无法remove
- Android(安卓)RIL 本地代码(c/c++) 和 Java代码部分分析
- Android中BottomNavigationView切换时去除效果
- 【Android之隐藏状态栏、设置全屏、取消全屏】
- Android(安卓)Mediarecorder录制的时候屏蔽掉声音
- Android(安卓)Studio&Xcode常用快捷键整理
- Android(安卓)应用程序自动更新