Launcher3 怎么创建一个Widget

Launcher3 AppWidget挂件显示原理 手机开机和重启过程中,有低概率机出现挂件不显示的情况,对整个显示流程和原理进行梳理. 阅读详情

参考博客https://www.cnblogs.com/skywang12345/p/3158310.html

一.Widget是什么

Launcher中除了app,还有一些小部件作为各个app的延伸功能

二.Widget的创建

1,创建Widget工程

2.编辑AndroidManifest.XML文件

     <receiver android:name=".widgets.desktop.SmallWidget" android:label="@string/widget_small">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
                <action android:name="com.naman14.timber.metachanged" />
                <action android:name="com.naman14.timber.playstatechanged" />
            </intent-filter>
            <meta-data android:name="android.appwidget.provider"
                android:resource="@xml/widget_small" />
        </receiver>

申明了SmallWidget,SmallWidget是一个广播接收者,说明Widget的功能实现本质上是通过Widget实现,同时需要初始化SmallWidget的布局,由widget_small来配置:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="380dp"
    android:minHeight="40dp"
    android:updatePeriodMillis="86400000"
    android:previewImage="@drawable/widget_small"
    android:resizeMode="horizontal|vertical"
    android:initialLayout="@layout/widget_small" />

minWidth 和minHeight 
  它们指定了App Widget布局需要的最小区域。
  缺省的App Widgets所在窗口的桌面位置基于有确定高度和宽度的单元网格中。如果App Widget的最小长度或宽度和这些网格单元的尺寸不匹配,那么这个App Widget将上舍入(上舍入即取比该值大的最接近的整数——译者注)到最接近的单元尺寸。
  注意:app widget的最小尺寸,不建议比 “4x4” 个单元格要大。关于app widget的尺寸,后面在详细说明。

minResizeWidth 和 minResizeHeight 
  它们属性指定了 widget 的最小绝对尺寸。也就是说,如果 widget 小于该尺寸,便会因为变得模糊、看不清或不可用。 使用这两个属性,可以允许用户重新调整 widget 的大小,使 widget 的大小可以小于 minWidth 和 minHeight。
  注意:(01) 当 minResizeWidth 的值比 minWidth 大时,minResizeWidth 无效;当 resizeMode 的取值不包括 horizontal 时,minResizeWidth 无效。
           (02) 当 minResizeHeight 的值比 minHeight 大时,minResizeHeight 无效;当 resizeMode 的取值不包括 vertical 时,minResizeHeight 无效。

updatePeriodMillis 
  它定义了 widget 的更新频率。实际的更新时机不一定是精确的按照这个时间发生的。建议更新尽量不要太频繁,最好是低于1小时一次。 或者可以在配置 Activity 里面供用户对更新频率进行配置。 实际上,当updatePeriodMillis的值小于30分钟时,系统会自动将更新频率设为30分钟!关于这部分,后面会详细介绍。
  注意: 当更新时机到达时,如果设备正在休眠,那么设备将会被唤醒以执行更新。如果更新频率不超过1小时一次,那么对电池寿命应该不会造成多大的影响。 如果你需要比较频繁的更新,或者你不希望在设备休眠的时候执行更新,那么可以使用基于 alarm 的更新来替代 widget 自身的刷新机制。将 alarm 类型设置为 ELAPSED_REALTIME 或 RTC,将不会唤醒休眠的设备,同时请将 updatePeriodMillis 设为 0。

initialLayout 
  指向 widget 的布局资源文件

configure
  可选属性,定义了 widget 的配置 Activity。如果定义了该项,那么当 widget 创建时,会自动启动该 Activity。

previewImage
  指定预览图,该预览图在用户选择 widget 时出现,如果没有提供,则会显示应用的图标。该字段对应在 AndroidManifest.xml 中 receiver 的 android:previewImage 字段。由 Android 3.0 引入。

autoAdvanceViewId 
  指定一个子view ID,表明该子 view 会自动更新。在 Android 3.0 中引入。

resizeMode 
  指定了 widget 的调整尺寸的规则。可取的值有: "horizontal", "vertical", "none"。"horizontal"意味着widget可以水平拉伸,“vertical”意味着widget可以竖值拉伸,“none”意味着widget不能拉伸;默认值是"none"。Android 3.1 引入。

widgetCategory 
  指定了 widget 能显示的地方:能否显示在 home Screen 或 lock screen 或 两者都可以。它的取值包括:"home_screen" 和 "keyguard"。Android 4.2 引入。

initialKeyguardLayout 
  指向 widget 位于 lockscreen 中的布局资源文件。Android 4.2 引入。

minWidth和minHeigth设置Widget在Launcher中至少要占的格子数,格子数怎么算

 

但最终格子数,还是由Widget的布局说了算

然后通过android:initialLayout="@layout/widget_small"配置widget的布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black_translucent"
    android:padding="4dp">

    <ImageView
        android:id="@+id/imageView_cover"
        android:padding="4dp"
        android:layout_width="100dp"
        android:layout_height="100dp" />

    <ImageView
        android:id="@+id/image_playpause"
        android:layout_margin="25dp"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:scaleType="center"
        android:background="@drawable/selectable_item_background"
        android:src="@drawable/ic_play_white_36dp" />

    <TextView
        android:id="@+id/textView_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_toEndOf="@id/imageView_cover"
        android:layout_toRightOf="@id/imageView_cover"
        android:ellipsize="end"
        android:lines="1"
        android:text="@string/tap_to_start"
        android:textColor="@android:color/white"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/textView_subtitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_below="@id/textView_title"
        android:layout_toEndOf="@id/imageView_cover"
        android:layout_toRightOf="@id/imageView_cover"
        android:lines="1"
        android:textColor="@android:color/white" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_below="@id/textView_subtitle"
        android:layout_toEndOf="@id/imageView_cover"
        android:layout_toRightOf="@id/imageView_cover"
        android:gravity="bottom"
        tools:ignore="Suspicious0dp">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />


        <ImageView
            android:id="@+id/image_next"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/selectable_item_background"
            android:src="@drawable/ic_skip_next_white_36dp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />
    </LinearLayout>

</RelativeLayout>

Widget并不支持所有的布局和控件,而仅仅只是支持Android布局和控件的一个子集。
(01) App Widget支持的布局:
  FrameLayout
  LinearLayout
  RelativeLayout
  GridLayout
(02) App Widget支持的控件:
  AnalogClock
  Button
  Chronometer
  ImageButton
  ImageView
  ProgressBar
  TextView
  ViewFlipper
  ListView
  GridView
  StackView
  AdapterViewFlipper

三.SmallWidget实现功能原理

1.SmallWidget继承了AppWidgetProvider,AppWidgetProvider继承了BroadcastReceiver,AppWidgetProvider主要封装了onReceive方法,如下:

public void onReceive(Context context, Intent intent) {
        // Protect against rogue update broadcasts (not really a security issue,
        // just filter bad broacasts out so subclasses are less likely to crash).
        String action = intent.getAction();
        if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
            Bundle extras = intent.getExtras();
            if (extras != null) {
                int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
                if (appWidgetIds != null && appWidgetIds.length > 0) {
                    this.onUpdate(context, AppWidgetManager.getInstance(context), appWidgetIds);
                }
            }
        } else if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {
            Bundle extras = intent.getExtras();
            if (extras != null && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
                final int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
                this.onDeleted(context, new int[] { appWidgetId });
            }
        } else if (AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED.equals(action)) {
            Bundle extras = intent.getExtras();
            if (extras != null && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_ID)
                    && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS)) {
                int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
                Bundle widgetExtras = extras.getBundle(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS);
                this.onAppWidgetOptionsChanged(context, AppWidgetManager.getInstance(context),
                        appWidgetId, widgetExtras);
            }
        } else if (AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)) {
            this.onEnabled(context);
        } else if (AppWidgetManager.ACTION_APPWIDGET_DISABLED.equals(action)) {
            this.onDisabled(context);
        } else if (AppWidgetManager.ACTION_APPWIDGET_RESTORED.equals(action)) {
            Bundle extras = intent.getExtras();
            if (extras != null) {
                int[] oldIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS);
                int[] newIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
                if (oldIds != null && oldIds.length > 0) {
                    this.onRestored(context, oldIds, newIds);
                    this.onUpdate(context, AppWidgetManager.getInstance(context), newIds);
                }
            }
        }
    }

onUpdate()
  当 widget 更新时被执行。
  同样,当用户首次添加 widget 时,onUpdate() 也会被调用,这样 widget 就能进行必要的设置工作(如果需要的话) 。但是,如果定义了 widget 的 configure属性(即android:config,后面会介绍),那么当用户首次添加 widget 时,onUpdate()不会被调用;之后更新 widget 时,onUpdate才会被调用。
  
onAppWidgetOptionsChanged()
  当 widget 被初次添加 或者 当 widget 的大小被改变时,执行onAppWidgetOptionsChanged()。你可以在该函数中,根据 widget 的大小来显示/隐藏某些内容。可以通过 getAppWidgetOptions() 来返回 Bundle 对象以读取 widget 的大小信息,Bundle中包括以下信息:
  OPTION_APPWIDGET_MIN_WIDTH -- 包含 widget 当前宽度的下限,以dp为单位。
  OPTION_APPWIDGET_MIN_HEIGHT -- 包含 widget 当前高度的下限,以dp为单位。
  OPTION_APPWIDGET_MAX_WIDTH -- 包含 widget 当前宽度的上限,以dp为单位。
  OPTION_APPWIDGET_MAX_HEIGHT -- 包含 widget 当前高度的上限,以dp为单位。

onAppWidgetOptionsChanged() 是 Android 4.1 引入的。

onDeleted(Context, int[])
  当 widget 被删除时被触发。

onEnabled(Context)
  当第1个 widget 的实例被创建时触发。也就是说,如果用户对同一个 widget 增加了两次(两个实例),那么onEnabled()只会在第一次增加widget时触发。

onDisabled(Context)
  当最后1个 widget 的实例被删除时触发。

onReceive(Context, Intent)
  接收到任意广播时触发,并且会在上述的方法之前被调用

2.onReceive是如何判断触发的是哪个Widget控件的呢?

Bundle extras = intent.getExtras();
            if (extras != null) {
                int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
                if (appWidgetIds != null && appWidgetIds.length > 0) {
                    this.onUpdate(context, AppWidgetManager.getInstance(context), appWidgetIds);
                }
            }

通过intent获取到appWidgetIds触发更新

2.建立了BroadcastReceiver后,一般UI和功能的初始化绑定可在onUpdate()完成,通过RemoteView完成,RemotView详解请看

https://blog.youkuaiyun.com/yuemingxingxing/article/details/86234811.

3.RemoteView初始化完后,调用 appWidgetManager.updateAppWidget(appWidgetIds, remoteViews),更新Widget

这样,整个SmallWidget功能就实现了!!!

 

 

探秘 widget 之 launcher 添加 widget 的流程分析 最近打算研究下android的widget相关问题,并把一些心得在此稍作记录,哈哈,等研究完成了,如果有必要的话,也会把改动的源码贴出来,以飨读者。今天先来看看launcher2中添加widget的流程。 添加widget首先需要在laucher的空白处长按,所以首先定位在laucher的 public boolean onLongClick(View v) 中,看到: 阅读详情

相关推荐

Launcher3源码分析之Widget添加流程

Launcher3小部件Widget添加流程分析     首先,看看Launcher3原生的Widget是如何获取到并显示的。原生的Widget是在AllApps界面显示的,也就是抽屉界面。 在Launcher.java 的onCreate()函数中先获取AppWidgetProviderInfo信息:  protected void onCreate(Bundle savedInstanc

HelloKen的专栏 5094

Android10/11 原生Launcher3动态显示Widget

一、引言 Android11的Launcher3关于widget的运用很多,如果需要对Launcher3显示的widget进行自定义,就得对其流程进行研究,知晓原理后修改起来事半功倍,此文主要从两方面加一实例进行阐述: 1. Launcher3 widget初始化流程 2. 长按widget拖拽到桌面的流程 3. 动态实现添加widget的逻辑描述 1.1、涉及的类 1. packages/apps/Launcher3/src/com/android/launcher3/Launcher.jav

CGTAIHYQ的博客 5120

Android Launcher3分析及定制&主题实现

一. Launcher3 简介 launcher3是在Launcher2的基础上进化的版本,从Android 4.4 开始就使用Launcher3 .(kk版,kk2版)作为桌面使用,以前我们都在使用Launcher2,我们使用的是KK版本,具体区别后面再说. 1 Launcher3 桌面变成了动态管理,launcher2 里面默认最多加载五个workspace布局. 1.2......

Android 1万+

修改Launcher3代码--在加载Launcher时默认加载某个widget

synchronized public void loadDefaultFavoritesIfNecessary(int origWorkspaceResId) { String spKey = LauncherApplication.getSharedPreferencesKey(); SharedPreferences sp = getContext().getS

weixin_34967708的博客 2026

Android 10.0 Launcher3禁用widget微件功能实现

在10.0的系统rom定制化开发中,在一些Launcher3的定制化功能中,有些产品禁用appwidget微件功能,要求Launcher 去掉加载widget微件功能,接下来具体分析下widget微件的加载流程

安卓兼职framework和app工程师的博客 992

Android 10.0 Launcher3仿ios的folder文件夹widget功能实现一

在10.0的系统ROM开发中,在进行一些系统Launcher3定制功能开发中,需要实现folder文件夹widget的功能,由于launcher3 默认不支持folder跨行显示,所以就需要借助自定义的widget小部件功能来实现相关功能,接下来分析实现相关功能

安卓兼职framework和app工程师的博客 1074

Android ---【案例篇】带你学习Widget,从Launcher加载各个应用的Widget到各个应用是怎么创建的Widget整个流程

Android Widget开发与加载流程摘要 Widget开发包含四个关键步骤:1) 在res/xml/定义配置信息,包括尺寸、更新频率等;2) 创建布局文件设计UI;3) 继承AppWidgetProvider实现逻辑处理类,管理生命周期和交互;4) 在Manifest中声明Widget组件。Launcher通过AppWidgetManager和AppWidgetHost框架加载Widget,首先初始化宿主环境,绑定ID并监听变化,然后获取系统Widget列表,最后通过RemoteViews机制跨进程渲

梁同学与Android 1655

Android 11.0 Launcher3禁用widget微件功能实现

在11.0的系统rom定制化开发中,在一些Launcher3的定制化功能中,有些产品禁用appwidget微件功能,要求Launcher 去掉加载widget微件功能,接下来具体分析下widget微件的加载流程

安卓兼职framework和app工程师的博客 451

Android --- 带你学习Widget,从Launcher加载各个应用的Widget到各个应用是怎么创建的Widget整个流程

App 需要通过固定的组件和配置文件声明 Widget,系统会识别这些信息并允许 Launcher 加载。-- Widget的最小尺寸(宽x高,单位:dp),Launcher会根据这个适配网格 -->-- 拉伸时的自适应尺寸(可选,用于不同屏幕适配) -->-- Widget的布局文件 -->-- 自动更新间隔(毫秒,0表示不自动更新) -->-- 点击Widget时打开的Activity(可选) --><TextViewandroid:text="我的小卡片"

2509_93869530的博客 1012

偷懒必备:3种方法快速移植MFC界面资源(含.rc文件打不开解决方案)

本文针对MFC桌面应用开发,详细介绍了三种快速移植界面资源的实战方法:直接编辑.rc文件、利用Visual Studio“添加现有项”进行可视化挂载,以及双实例拖拽应急方案。文章重点剖析了.rc文件无法打开的常见问题,提供了通过修复rc.exe等关键文件来根治此问题的解决方案,帮助开发者高效复用资源,规避ID冲突等陷阱。

weixin_28358083的博客 273

富士SC2022,C325,C328打印机扫描到网络详细教程

富士打印机SC2022,C328,C325等型号扫描到电脑教程

weixin_41926602的博客 1万+

Android车载Launcher开发(1) - 显示Widget

Android launcher开发,讲述如何显示其他app的widget到launcher上

NYSM239的博客 8533

python 识别滑块验证码

博客来源于: https://www.cnblogs.com/wyh0923/p/16528354.html # -*- coding: utf-8 -*- # https://gov.pkulaw.cn/ 1. import io 2. import json 3. from pathlib import Path 4. from PIL import Image 5. import bas...

2102

Launcher3 Widget拖拽到桌面的流程分析

一:交互图 长按Launcher进入OverView Panel界面,点击WIDGETS进入Widgets界面,拖拽widgets到Launcher桌面,显示widget到桌面,完成widget的显示操作 二:逻辑思路 1.WidgetsContainerView为显示所有Widgets的View,初始化在Launcher的onCreate方法中调用setupViews方法初始化 2...

yuemingxingxing的博客 1019

【CarMaker实战指南】从零构建环形测试场景与车辆连续仿真

本文详细介绍了如何使用CarMaker软件从零构建环形测试场景与实现车辆连续仿真。通过分步指导搭建闭环道路、连接交叉路口、规划车辆轨迹等核心操作,帮助用户掌握CarMaker的基础应用技巧,并提供了常见问题排查与进阶优化建议,适用于车辆耐久性测试和自动驾驶算法验证等场景。

weixin_29274969的博客 234

超全!!snowboy语音唤醒(树莓派4b)

通过snowboy进行树莓派的语音唤醒

crimaster1024的博客 8734

Android Launcher3简介

Android Launcher3简介

j086924的专栏 1万+

Pyhon在振动信号处理中的高级应用(一):振动信号特征(时域、频域)提取

文章目录一、概述二、算法原理2.1 时域统计特征三、python代码实现 一、概述 二、算法原理   这里我们借鉴西安交通大学机械学院雷教授的论文《Fault diagnosis of rotating machinery based on multiple ANFIS combination with GAs》相关研究成果。雷教授在论文中共列举了4类共24种振动信号的时域和频域特征。 2.1 时域统计特征 p1=∑n=1Nx(n)NP2=∑n=1N(x(n)−p1)2N−1p3=(∑n=1N∣x(n)∣N

白银时代的博客 1万+

[sprd]Android Q在 Launcher 上添加时钟 widget

vendor/partner_gms/apps/GmsSampleIntegration/res_dhs_go/xml/partner_default_layout.xml <appwidget screen="0" x="0" y="2" packageName="com.android.deskclock" className="com.android.alarmclock.DigitalAppWidgetProvider" spanX="4" spanY="2" /> 这个文件的解析过程

zhangqi6627的专栏 1061

计算机组成原理(第三版)唐朔飞-第六章计算机的运算方法-课后习题(17-32)

计算机组成原理(第三版)唐朔飞-第六章计算机的运算方法-课后习题(17-32)

weixin_45735391的博客 12万+

基于STM32+4G模块设计的智能灌溉系统

当前智能灌溉系统分为三个部分:温湿度采集部分、灌溉系统部分、OneNet云平台。 灌溉系统部分增加刷卡功能,用户可以通过IC卡刷卡将金额刷到灌溉系统设备里,灌溉系统设备里会记录金额,并且在手机可视化页面上会显示当前的设备金额。 金额会随着时间进行递减,按分钟计费,如果计费到0,就无法启动灌溉,需要重新充值金额才能继续。

4512

Android launcher widget配置

Android launcher widget配置     第一屏,根据由几个屏来定,screen[0]就指第一屏     第二屏 这里放的是一个widget,属性包括:包名,类名,屏的id(第二屏id为1),坐标(x,y),所占大小(4*1)              launcher:packageName="com.android.sett

kaiyoushiwo007的专栏 1753

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

android launcher 调用 widget,Launcher3添加桌面appWidget

这是安卓系统移植开发--Launcher3在桌面上添加默认的appWidget为什么有这篇文章Launcher3相对于Launcher2改变了很多,网上大部分的资料也是说的4.4版本以前的Launcher2,按照以前Launcher2的修改方式对Launcher3是无效的,比如本文要讲述的在桌面添加appWidget.上正题Launcher3桌面的加载过程Launcher3在首次安装的时候,会检查...

weixin_35338559的博客 1689

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

launcher-给应用添加widget

给应用添加widget一共分为三步 1.创建一个类MyAppWidgetProvider继承AppWidgetProvider。 虽然命名是以Provider结尾,但实际上AppWidgetProvider是继承的BroadcastRecevier. 既然是广播接收者那么我们就需要在xml中注册了,如下便是在AndroidManifest.xml中注册 <receiver android:name=".widget.MyAppWidget"> <intent

qq_32521381的博客 1232

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

探秘widget之launcher添加widget的流程分析

添加widget首先需要在laucher的空白处长按,所以首先定位在laucher的 public boolean onLongClick(View v) 中,看到: [java] view plaincopy if (mWorkspace.allowLongPress()) { if (cellInfo.cell == null) { if (...

初心(linux,python,php,photoshop) 266
上一篇: Launcher3 定制桌面行列数
下一篇: Launcher3 RemoteView介绍和应用
网络卷毛
博客等级 码龄14年 13粉丝 129原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值