Android UI组件AppWidget控件入门详解_Android

Widget引入 

我们可以把Widget理解成放置在桌面上的小组件(挂件),有了Widget,我们可以很方便地直接在桌面上进行各种操作,例如播放音乐。 

当我们长按桌面时,可以看到Widget选项,如下图所示: 

点击上图中箭头处的widgets图标,会出现如下界面:(都是widget) 

长按上图中的任意一个widget,就可以将其放到桌面上。 

Widget的使用
Widget的实现思路 
(1)在AndroidManifest中声明AppWidget; 
(2)在xml目录中定义AppWidget的配置文件; 
(3)在layout目录中定义Widget的布局文件; 
(4)新建一个类,继承AppWidgetProvider类,实现具体的widget业务逻辑。 

我们需要新建一个类,继承AppWidgetProvider。点开AppWidgetProvider,发现AppWidgetProvider竟然是继承自BroadcastReceiver。 

为什么Widget是一个广播接收器呢?我们知道,BroadcastReceiver类中有一个onReceive方法,用来接收广播。当我们在桌面挂件上去做操作时,必然引起应用的改变,这就涉及到挂件和应用之间的通信,此时用广播来通信是再好不过了。 

Widget的具体使用步骤 

(1)新建一个类TestWidget.java,继承AppWidgetProvider:
 TestWidget.java: 

import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
/**
 * Created by smyhvae on 2016/9/7.
 */
public class TestWidget extends AppWidgetProvider{
 @Override
 public void onReceive(Context context, Intent intent) {
  super.onReceive(context, intent);
 }
}

(2)因为Widget是一个广播接收器,所以我们需要在清单文件中注册:

 <!-- 声明widget对应的AppWidgetProvider -->
  <receiver android:name=".TestWidget">
   <intent-filter>
    <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
   </intent-filter>
   <meta-data
    android:name="android.appwidget.provider"
    android:resource="@layout/widget_setting"/>
  </receiver>

04行:action是过滤条件,用来过滤行为,监测widget的更新。
08行:android:resource指定了widget的配置。我们知道,属性在清单文件中是用来存储数据的。 

(3)layout文件夹中新建文件widget_setting.xml:(widget的配置文件)
 setting_widget.xml: 

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:initialLayout="@layout/layout_widget"
     android:minHeight="140dp"
     android:minWidth="140dp"
     android:previewImage="@mipmap/ic_launcher"
     android:updatePeriodMillis="20000"
     android:widgetCategory="home_screen"
 >
</appwidget-provider>

08行: android:initialLayout 指定了widget的布局。
09行:android:updatePeriodMillis 指定更新的时间周期
10行: android:widgetCategory="home_screen" 将widget显示在主屏幕上(也可以显示在锁屏上)

(4)layout文件夹中新建文件layout_widget.xml:(widget的布局)
 layout_widget.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">
 <TextView
  android:id="@+id/textView"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_gravity="center_horizontal"
  android:text="Large Text"
  android:textAppearance="?android:attr/textAppearanceLarge"/>
 <Button
  android:id="@+id/button2"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_gravity="center_horizontal"
  android:text="New Button"/>
</LinearLayout>

到此,程序就可以跑起来了。运行程序之后,长按桌面,点开"Widget"按钮,可以看到我们刚刚设计出的widget: 

长按上图中的箭头处,就可以将我们设计出的widget拖放到桌面上了: 

Widget的点击和更新【重要】 

我们知道,TestWidget.java继承自AppWidgetProvider,而AppWidgetProvider在继承BroadcastReceiver之后,重写onReceive方法,然后还自定义了很多方法: 

上图中,包含了被删除时、被禁用时、被启用时、被更新时等各种方法。尤其重要的是onReceive()方法和onUpDate()方法。
 当小部件被改变时(比如被安装到桌面),系统会发送一个更新的广播(上图红框部分所示)。我们在setting_widget.xml中设置了widget的更新频率,这个也会调用更新。 

有人可能会问,我开机之后,天气等widget为何不更新了?这是因为进程被杀死了,那我们只能把这个控件先移除,然后再装上,此时应用会发update更新的广播。 

当需要做widget的点击和更新时,我们需要在需要重写onUpdate()方法,用来发送广播。当程序初始化的时候,系统就会调用onUpdate()方法。 

onUpdate()方法中的代码如下:

  @Override
 public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
  super.onUpdate(context, appWidgetManager, appWidgetIds);
  RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.layout_widget);//需要构造一个RemoteViews
  Intent intent = new Intent();
  intent.setClass(context, TestWidget.class); //通过intent把广播发给TestWidget本身,TestWidget接受到广播之后,会调用。。进而刷新借鉴  // 。
  intent.setAction(WIDGET_BTN_ACTION);
  PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
  remoteViews.setOnClickPendingIntent(R.id.widget_btn, pendingIntent);//控件btn_widget的点击事件:点击按钮时,会发一个带action的广播。
  appWidgetManager.updateAppWidget(appWidgetIds, remoteViews); //点击完了之后,记得更新一下。
 }

代码解释:
首先需要new一个RemoteViews,构造方法里需要传递两个参数,一个是包名(context.getPacakgeName),一个是布局文件(layout_widget)。
 然后通过remoteViews.setOnClickPendingIntent()设置按钮的点击事件。setOnClickPendingIntent()中需要传递两个参数:一个是id(比如需要被点击的button),一个是PendingIntent。PendingIntent是未来的意图。
 于是我们需要事先构造一个PendingIntent,这个需要通过 PendingIntent.getBroadcast()来构造。getBroadcast()方法中需要传递四个参数,其中有一个是Intent。
 于是我们需要构造一个Intent。在intent里发送广播,并设置Action。
 按钮点击完了之后,记得调用appWidgetManager.updateAppWidget(int[] appWidgetIds, RemoteViews views)方法更新一下,第一个参数就是onUpdate方法中的参数,代表的是所有的控件。 

在onUpdate()方法中通过intent发送按钮点击时间的广播之后,我们需要在onReceive()方法中进行广播的接收。
 onReceive()方法中的代码如下: 

 @Override
 public void onReceive(Context context, Intent intent) {
  super.onReceive(context, intent);
  if (intent != null && TextUtils.equals(intent.getAction(), WIDGET_BTN_ACTION)) { //当intent不为空,且action匹配成功时,就接收广播,然后点击事件成功
   Log.i(WIDGET_BTN_ACTION, "is clicked");
   //接下来开始做点击事件里面的内容
   RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.layout_widget);//注意:需要【重新】构造一个RemoteViews
   remoteViews.setTextViewText(R.id.widget_tv, "be clicked");
   remoteViews.setTextColor(R.id.widget_tv, Color.RED);
   AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);// 单例模式
   ComponentName componentName = new ComponentName(context, TestWidget.class);
   appWidgetManager.updateAppWidget(componentName, remoteViews);//setText之后,记得更新一下
  }
 }

代码解释:
 当intent的action匹配成功时,开始执行做点击时间之后的setText,不过这里需要重新new 一个 RemoteViews,而不能共用onUpdate()方法中的RemoteViews(这是一个很大的坑)。
 执行完点击事件之后的setText之后,记得调用appWidgetManager.updateAppWidget(ComponentName, RemoteViews)方法,第一个参数为组件名,需要我们自己new一下,第二个参数很好解释。 

综合来说,TestWidget.java的完整版代码如下:
Testwidget.java:

 import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.text.TextUtils;
import android.util.Log;
import android.widget.RemoteViews;
/**
 * Created by smyhvae on 2016/9/7.
 */
public class TestWidget extends AppWidgetProvider {
 public static final String WIDGET_BTN_ACTION = "widget_btn_action";
 @Override
 public void onReceive(Context context, Intent intent) {
  super.onReceive(context, intent);
  if (intent != null && TextUtils.equals(intent.getAction(), WIDGET_BTN_ACTION)) { //当intent不为空,且action匹配成功时,就接收广播,然后点击事件成功
   Log.i(WIDGET_BTN_ACTION, "is clicked");
   //接下来开始做点击事件里面的内容
   RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.layout_widget);//注意:需要【重新】构造一个RemoteViews
   remoteViews.setTextViewText(R.id.widget_tv, "be clicked");
   remoteViews.setTextColor(R.id.widget_tv, Color.RED);
   AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);// 单例模式
   ComponentName componentName = new ComponentName(context, TestWidget.class);
   appWidgetManager.updateAppWidget(componentName, remoteViews);//setText之后,记得更新一下
  }
 }
 @Override
 public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
  super.onUpdate(context, appWidgetManager, appWidgetIds);
  RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.layout_widget);//需要构造一个RemoteViews
  Intent intent = new Intent();
  intent.setClass(context, TestWidget.class); //通过intent把广播发给TestWidget本身,TestWidget接受到广播之后,会调用。。进而刷新借鉴  // 。
  intent.setAction(WIDGET_BTN_ACTION);
  PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
  remoteViews.setOnClickPendingIntent(R.id.widget_btn, pendingIntent);//控件btn_widget的点击事件:点击按钮时,会发一个带action的广播。
  appWidgetManager.updateAppWidget(appWidgetIds, remoteViews); //点击完了之后,记得更新一下。
 }
}

运行之后,把widget拖到桌面上,效果如下:

 

点击按钮后,效果如下:

 

工程文件:(Android Studio 2.1) 

当然,widget还有很多其他的用途。比如:
 •与Service进行通信
 •widget控件的交互方法。
 •如何做一个桌面播放器Widget

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索android
, appwidget
ui组件
widget组件、淘宝widget组件、bootstrap widget组件、淘宝widget组件教程、android widget组件,以便于您获取更多的相关知识。

时间: 2024-10-29 17:26:08

Android UI组件AppWidget控件入门详解_Android的相关文章

Android UI组件AppWidget控件入门详解

Widget引入 我们可以把Widget理解成放置在桌面上的小组件(挂件),有了Widget,我们可以很方便地直接在桌面上进行各种操作,例如播放音乐. 当我们长按桌面时,可以看到Widget选项,如下图所示: 点击上图中箭头处的widgets图标,会出现如下界面:(都是widget) 长按上图中的任意一个widget,就可以将其放到桌面上. Widget的使用 Widget的实现思路  (1)在AndroidManifest中声明AppWidget:  (2)在xml目录中定义AppWidget

android之SeekBar控件用法详解_Android

MainActivity.java package com.example.mars_2400_seekbar; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBar; import android.support.v4.app.Fragment; import android.app.Activity; import android.os.Bundle; import a

android之RatingBar控件用法详解_Android

MainActivity.java package com.example.mars_2500_ratingbar; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBar; import android.support.v4.app.Fragment; import android.app.Activity; import android.os.Bundle; import

Android 仿淘宝、京东商品详情页向上拖动查看图文详情控件DEMO详解_Android

一.淘宝商品详情页效果 我们的效果 二.实现思路      使用两个scrollView,两个scrollView 竖直排列,通过自定义viewGroup来控制两个scrollView的竖直排列,以及滑动事件的处理.如下图 三.具体实现 1.继承viewGroup自定义布局View 重写onMeasure()和onLayout方法,在onLayout方法中完成对两个子ScrollView的竖直排列布局,代码如下: 布局文件: <RelativeLayout xmlns:android="h

Android实现在列表List中显示半透明小窗体效果的控件用法详解_Android

本文实例讲述了Android实现在列表List中显示半透明小窗体效果的控件用法.分享给大家供大家参考,具体如下: Android 在列表List中显示半透明小窗体效果的控件,多的不多直接上代码,要说的都在注释里了: import com.hiapk.market.R; import android.content.Context; import android.graphics.PixelFormat; import android.os.Handler; import android.view

Android自定义日历控件实例详解_Android

为什么要自定义控件 有时,原生控件不能满足我们对于外观和功能的需求,这时候可以自定义控件来定制外观或功能:有时,原生控件可以通过复杂的编码实现想要的功能,这时候可以自定义控件来提高代码的可复用性. 如何自定义控件 下面我通过我在github上开源的Android-CalendarView项目为例,来介绍一下自定义控件的方法.该项目中自定义的控件类名是CalendarView.这个自定义控件覆盖了一些自定义控件时常需要重写的一些方法. 构造函数 为了支持本控件既能使用xml布局文件声明,也可在ja

Android滚轮选择时间控件使用详解_Android

滚轮选择控件 Android自带的选择时间控件有点丑,往往产品和设计都比较嫌弃,希望做成ios一样的滚轮选择,下面是我在NumberPicker的基础上自定义的选择控件,效果如下: 原理 基于NumberPicker实现 动态填充数值 联动 接口监听回调 实现滚轮效果有github上mark比较多的WheelView,但是阅读源码发现数据是一次性填入的,选择时间的话,填入10年就是10*365=3650条数据,也就是new出三千多个TextView,想想都觉得恐怖,肯定是不行的,于是便想到用Nu

Android UI系列-----ScrollView和HorizontalScrollView的详解_Android

本篇随笔将讲解一下Android当中比较常用的两个布局容器--ScrollView和HorizontalScrollView,从字面意义上来看也是非常的简单的,ScrollView就是一个可以滚动的View,这个滚动的方向是垂直方向的,而HorizontalScrollView则是一个水平方向的可以滚动的View.本篇随笔可能描述性的知识比较少,最主要还是通过代码来看看如何使用这两个View. 一.ScrollView的简单介绍 首先来看看ScrollView和HorizontalScrollV

Android四大组件之Service(服务)实例详解_Android

本文实例讲述了Android四大组件之服务用法.分享给大家供大家参考,具体如下: 很多情况下,一些与用户很少需要产生交互的应用程序,我们一般让它们在后台运行就行了,而且在它们运行期间我们仍然能运行其他的应用. 为了处理这种后台进程,Android引入了Service的概念.Service在Android中是一种长生命周期的组件,它不实现任何用户界面. 基本概念 Ÿ   Service是一种在后台运行,没有界面的组件,由其他组件调用开始. Ÿ   创建Service,定义类继承Service,An