点击上图中箭头处的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-dataandroid:name="android.appwidget.provider"android:resource="@layout/widget_setting"/></receiver>04行:action是过滤条件,用来过滤行为,监测widget的更新。
<?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的布局。
<?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"> <TextViewandroid: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"/> <Buttonandroid: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);//需要构造一个RemoteViewsIntent 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); //点击完了之后,记得更新一下。 }代码解释:
@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之后,记得更新一下} }代码解释:
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);//需要构造一个RemoteViewsIntent 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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。