一文掌握android小组件(AppWidget)开发 | 您所在的位置:网站首页 › vivo怎么设置桌面小组件图标显示时间 › 一文掌握android小组件(AppWidget)开发 |
最近在学习android小组件开发,记之以便日后温习。桌面小组件可以方便使用app的隐藏功能,实现一键触达,提升用户体验。这样可以极大便捷家里的老人使用应用,享受到互联网带来的便捷。最近给家里的老人添加了追剧的小组件,这样她不需要学习怎么搜索、怎么选择,通过桌面小组件便可以快速触达。下面将分别介绍基础小组件开发、列表小组件开发、开发小组件的注意事项。 一、基础小组件的开发实现android的小组件需要按照一定的范式,主要包括四步,下面将以扫一扫的小组件入口为例分别介绍: 第一步:创建ScanWidgetProvider.java类,继承自android的AppWidgetProvider。小组件的核心逻辑包括点击、展示都在此处。后文会详细介绍。目前此类可以保持空实现。 第二步:在AndroidManifest中配置小组件的receiver,了解android的都知道receiver配置的是广播接收器,难道小组件是一个广播接收器?通过查看AppWidgetProvider的继承类发现,其继承了BroadcastReceiver,所以小组件实际上就是一个广播接收器。 //添加引导处展示的标签名称 //配置文件第三步:创建第二步中用到的resource文件widget_scan_resource.xml,创建在res/xml文件下,示例如下。 //更新时间间隔,单位是毫秒,上述代码需重点介绍minHeight和minWidth。手机将桌面划分成了一个个独立网格,然后桌面内容都展示在网格中,一个应用图标就占一格。小组件在桌面同样展示在网格中,当占一个网格时就是1X1的组件;横向两个网格就是2X1的组件,那么横纵各两个网格自然就是2X2的组件。此处的minHeight和minWidth是指需要占用的网格的总长和宽,常用经验公式计算:(m为横向网格数,n为竖向网格数) minWidth = 70 x m - 30(dp) minWidth = 70 x n - 30(dp) 此时你可能不禁会问,如果设置的最小宽高和手机网格的宽高不匹配怎么办。没关系,系统会帮取整找到最近的网格倍数设置给小组件。这也是为什么此参数需要加上min(最小)了。 第四步:创建小组件的布局文件scan_widget_layout.xml 至此一个简单的小组件就开发完成了。将以上代码放入项目中,手机中就可以添加扫一扫小组件了。如下图所示 小组件的更新代码都在onUpdate中实现,widget中只能使用RemoteViews提供的一些列set方法更新小组件的内容,例如使用setImageViewBitmap设置图片,使用setTextViewText设置文字,使用setOnClickPendingIntent设置点击事件等。 至此一个基础的小组件开发就完成了,由于小组件展示在“寸土寸金”的桌面,使用基础组件就可以完成绝大部分需求。但是如果碰到需要展示列表形式,则需要使用ListView、GridView。 二、列表组件的开发通过上文介绍知道小组件并不能像普通安卓应用开发那样,找到指定view,然后对view进行操作。小组件需要通过RemoteViews提供的一些列的set方法对视图渲染更新。那么listview和gridview也是一样的。回忆一下列表视图的正常开发流程,先创建listview的视图,然后为视图设置layoutmanager设置布局样式,最后创建列表的adapter进行数据填充。widget采用同样的实现流程,只是需要使用符合widget规范的特有方式实现。接下来将在上文案例的基础上进行修改: 第一步:修改widget_scan_resource.xml的最小宽高,设置为4X4的组件 android:minHeight="250dp" //最小高度 android:minWidth="250dp" //最小宽度第二步:修改布局文件scan_widget_layout.xml,在命名为tv_scan的Textview下增加girdlist ..... ......第三步:创建更新列表视图需要的“adapter”,此处打了双引号,就是说需要按照小组件的方式实现,下面两个类按照固定范式实现。 public class ListWidgetService extends RemoteViewsService { @Override public RemoteViewsFactory onGetViewFactory(Intent intent) { return new ListWidgetFactory(this); } } public class ListWidgetFactory implements RemoteViewsService.RemoteViewsFactory { private final List data = new ArrayList(); private final Context context; public ListWidgetFactory(Context context) { this.context = context; } @Override public void onCreate() { initData(); } private void initData() { data.clear(); for (int i = 0; i < 10; i++) { Random random = new Random(); String msg = "扫一扫" + random.nextInt(101); data.add(msg); } } @Override public void onDataSetChanged() { } @Override public void onDestroy() { data.clear(); } @Override public int getCount() { return data.size(); } //重点实现 @Override public RemoteViews getViewAt(int position) { RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.list_scan_item); remoteViews.setTextViewText(R.id.list_item_tv, data.get(position)); remoteViews.setImageViewResource(R.id.list_item_image, R.drawable.demo_scan); Intent intent = new Intent(); intent.putExtra("CLICK_POSITION", position); remoteViews.setOnClickFillInIntent(R.id.list_item_root, intent); return remoteViews; } @Override public RemoteViews getLoadingView() { return null; } @Override public int getViewTypeCount() { return 1; } @Override public long getItemId(int position) { return position; } @Override public boolean hasStableIds() { return true; } }这一步代码有点长,但是逻辑很简单。就是先创建RemoteViewsService ,通过此service返回一个RemoteViewsFactory ,RemoteViewsFactory 就是通常理解的列表更新的adapter,其实从内部的继承方法也可以看出。getItemId、getViewTypeCount、getCount是不是都似曾相识?没错,就是开发列表adapter常复写的方法。 此处重点介绍一下getViewAt,内部同样需要使用RemoteViews实现单个列表的view,列表内元素的信息更新需要使用RemoteViews提供的每个set方法。list_scan_item视图布局代码不再提供,很简单就是上图下文的形式。 第四步:更新ScanWidgetProvider,主要在onUpdate方法中设置列表的点击事件和“adapter” // 设置列表的adapter Intent listIntent = new Intent(context, ListWidgetService.class); remoteViews.setRemoteAdapter(R.id.scan_list, listIntent); //设置列表的点击事件 Intent intent1 = getCommenIntent(context); intent1.putExtra("CLICK_ACTION", "scan_demo_list_click"); PendingIntent pendingIntent1 = PendingIntent.getActivity(context, R.id.scan_list, intent1, PendingIntent.FLAG_UPDATE_CURRENT); remoteViews.setPendingIntentTemplate(R.id.scan_list, pendingIntent1);上述代码需重点关注列表的点击事件,setPendingIntentTemplate是设置列表的通用点击Intent,然后单个item的点击如果需要增加参数,则需使用setOnClickFillInIntent设置补充信息。接收方收到的intent中包含这两部分的内容,于是便可以区分出具体是哪个item的点击了。至此一个列表的小组件便实现完成了。 三、小组件的开发原理和注意事项1、小组件实际上是运行在系统进程中,所以和app进程涉及到跨进程通信,只能使用RemoteViews更新数据,使用PendingIntent执行延时意图。 2、RemoteViews支持的布局只有以下这些,开发的小组件布局不能超出这些范围。 布局:FrameLayout、LinearLayout、RelativeLayout、GridLayout。 View:Button、TextView、Chronometer、ImageButton、ImageView、ProgressBar、ViewFlipper、AnalogClock、AdapterViewFlipper、ViewStub、ListView、GridView、StackView 3、小组件类继承自AppWidgetProvider,实际上就是一个广播,可以通过发送广播和接受广播进行通信更新,广播接受在onReceive中实现。 onUpdate :小组件创建时和达到更新周期时触发。 onEnabl:第一个改类型小组件添加时触发。 onDeleted:每次删除该小组件时触发。 onDisabled:最后一个该类型小组件添加时触发。 4、在AndroidManifest注册小组件必须要有android.appwidget.action.APPWIDGET_UPDATE这个action,否则将无法安装,其他的action和自定义的action可根据需要添加。 |
CopyRight 2018-2019 实验室设备网 版权所有 |