Android桌面小部件AppWidget开发

作者: 郑旭泽 | 来源:发表于2017-01-10 10:38 被阅读5610次

    Android桌面小部件AppWidget开发

    在Android我们经常可以看到各种桌面小部件,比如时钟、天气、音乐播放器等等。我们可以使用AppWidgetProvider来实现小部件的开发。

    AppWidgetProvider是Android中提供的用于实现桌面小工具的类,其本质是一个广播,即BroadcastReceiver。

    开发一个桌面小部件的步骤:

    一、自定义小部件界面

    在res/layout/下新建一个布局文件,名称和内容自定义,看你想把小工具做成什么样。需要注意的是系统默认的小工具布局中只支持以下这些标签,如果用了列表以外的标签,会导致小工具加载错误:

    • FrameLayout、LinearLayout、RelativeLayout
    • TextClock、Button、Chronometer、ImageButton、ImageView、ProgressBar、TextView

    比如,我们创建了一个名为widget_layout.xml的布局文件:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">
    
        <ImageView
            android:id="@+id/doge_imageView"
            android:layout_width="110dp"
            android:layout_height="110dp"
            android:src="@drawable/doge" />
    
    </LinearLayout>
    
    二、定义小部件配置信息

    定义小部件的配置信息需要在res目录下新建一个xml目录,然后在res/xml/目录下创建一个配置文件,配置文件名称随意。新建app_widget_provider_info.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
        android:initialLayout="@layout/widget_layout"
        android:minHeight="110dp"
        android:minWidth="110dp"
        android:previewImage="@drawable/doge"
        android:updatePeriodMillis="864000" />
    

    上面的参数意义很明确,initialLayout指小部件的初始化布局,一般与最终布局相同;minHeight和minWidth定义了小部件的最小宽高,与小部件所占网格大小有关;previewImage可以指定在添加小部件时看到的预览图;updatePeriodMillis指定了小部件的自动更新周期,单位为毫秒。

    其中minHeight和minWidth的定义可以参考官方文档:https://developer.android.com/guide/practices/ui_guidelines/widget_design.html#design

    小部件最小宽高选取.png
    三、定义小部件类,继承自AppWidgetProvider
    import android.app.PendingIntent;
    import android.appwidget.AppWidgetManager;
    import android.appwidget.AppWidgetProvider;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    import android.widget.RemoteViews;
    import android.widget.Toast;
    
    /**
     * @author zhengxuze
     * @date 2017/1/10 create
     */
    
    public class TestWidgetProvider extends AppWidgetProvider {
        public static final String CLICK_ACTION = "com.seewo.appwidgettest.action.CLICK"; // 点击事件的广播ACTION
    
        /**
         * 每次窗口小部件被更新都调用一次该方法
         */
        @Override
        public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
            super.onUpdate(context, appWidgetManager, appWidgetIds);
    
            RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
            Intent intent = new Intent(CLICK_ACTION);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(context, R.id.doge_imageView, intent, PendingIntent.FLAG_UPDATE_CURRENT);
            remoteViews.setOnClickPendingIntent(R.id.doge_imageView, pendingIntent);
    
            for (int appWidgetId : appWidgetIds) {
                appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
            }
        }
    
        /**
         * 接收窗口小部件点击时发送的广播
         */
        @Override
        public void onReceive(Context context, Intent intent) {
            super.onReceive(context, intent);
    
            if (CLICK_ACTION.equals(intent.getAction())) {
                Toast.makeText(context, "hello dog!", Toast.LENGTH_SHORT).show();
            }
        }
    
        /**
         * 每删除一次窗口小部件就调用一次
         */
        @Override
        public void onDeleted(Context context, int[] appWidgetIds) {
            super.onDeleted(context, appWidgetIds);
        }
    
        /**
         * 当最后一个该窗口小部件删除时调用该方法
         */
        @Override
        public void onDisabled(Context context) {
            super.onDisabled(context);
        }
    
        /**
         * 当该窗口小部件第一次添加到桌面时调用该方法
         */
        @Override
        public void onEnabled(Context context) {
            super.onEnabled(context);
        }
    
        /**
         * 当小部件大小改变时
         */
        @Override
        public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
            super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
        }
    
        /**
         * 当小部件从备份恢复时调用该方法
         */
        @Override
        public void onRestored(Context context, int[] oldWidgetIds, int[] newWidgetIds) {
            super.onRestored(context, oldWidgetIds, newWidgetIds);
        }
    }
    
    四、在AndroidManifest.xml中声明小部件
    <receiver android:name=".TestWidgetProvider">
        <meta-data
            android:name="android.appwidget.provider"
            android:resource="@xml/app_widget_provider_info" />
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            <action android:name="com.seewo.homewidgets.action.CLICK" />
        </intent-filter>
    </receiver>
    

    OK,小部件完成了,运行一下看看效果:

    相关文章

      网友评论

      • x枫x:为啥找不到 写的部件??
        9d2d64a6e7b0:有些定制UI (MUI)根本没有这个,然后官方系统都放在widget里了,需要自己去找到拖桌面上去,根本没意义,除非跟厂商合作
      • Lshare_Blog:实际上RemoteViews 支持的layout 和view 不止楼主所罗列的,建议参考《Andriod 开发艺术探索》进行补充。
        sunrain_:@夏Jue 看文档就好 :blush: https://developer.android.com/guide/topics/appwidgets/#CreatingLayout
        Lshare_Blog:@夏Jue 因为我把书借给别人了:grin:
        1fd0e6df5152:那你为啥不补充一下嘞???:smiley:

      本文标题:Android桌面小部件AppWidget开发

      本文链接:https://www.haomeiwen.com/subject/cbdkbttx.html