安卓桌面小部件开发

作者: fushuang | 来源:发表于2017-11-22 17:38 被阅读105次
    GIF.gif

    RemoteView 自定义桌面小部件

    效果如上图, class AppWidgetProvider extends BroadcastReceiver,不难看出桌面小部件本质上是一个广播,至于为什么是一个广播的形势,我猜...是因为桌面小部件运行在SystemService进程中,通过PendingIntent这种方式传递,避免了自己写IPC通信。

    自定义小部件统共分几步

    1.定义小部件界面

    在layout 下创建xml 文件

    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <ImageView
            android:id="@+id/tv_content"
            android:src="@mipmap/ic_launcher"
            android:gravity="center"
            android:textSize="20sp"
            android:layout_width="100dp"
            android:layout_height="100dp" />
    </RelativeLayout>
    

    2.定义小部件配置信息

    通过as自带的创建app widget功能会自动创建该文件,否则需要手动指定,定义小部件刷新,最小宽高等信息

    <?xml version="1.0" encoding="utf-8"?>
    <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
        android:initialKeyguardLayout="@layout/new_app_widget"
        android:initialLayout="@layout/new_app_widget"
        android:minHeight="110dp"
        android:minWidth="110dp"
        android:previewImage="@mipmap/ic_launcher"
        android:resizeMode="horizontal|vertical"
        android:updatePeriodMillis="86400000"
        android:widgetCategory="home_screen" />
    
    • resizeMode 小部件可伸缩方向
    • minHeight,minWidth 小部件最宽高
    • previewImage 拖动到桌面前的预览图片
    • nitialLayout初始化布局
    • updatePeriodMillis小部件的刷新间隔,单位是秒,默认是一天

    3. 继承AppWidgetProvider

    public class NewAppWidget extends AppWidgetProvider {
    
        private static final String fs="com.example.admin.customview.click";
    
        static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                                    int appWidgetId) {
    
            RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
            Intent clickIntent = new Intent();
    
            clickIntent.setAction(fs);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, clickIntent, 0);
            remoteViews.setOnClickPendingIntent(R.id.tv_content,pendingIntent);
    
            // Instruct the widget manager to update the widget
            appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
        }
    
        @Override
        public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
            // There may be multiple widgets active, so update all of them
            for (int appWidgetId : appWidgetIds) {
                updateAppWidget(context, appWidgetManager, appWidgetId);
            }
        }
        @Override
        public void onEnabled(Context context) {
            // Enter relevant functionality for when the first widget is created
        }
    
        @Override
        public void onDisabled(Context context) {
            // Enter relevant functionality for when the last widget is disabled
        }
    
        @Override
        public void onReceive(final Context context, Intent intent) {
            super.onReceive(context, intent);
            Log.d("88888888888", "onReceive: ");
    
            String action = intent.getAction();
            final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
            //判断是否是自定义点击action
            if (action.equals(fs)){
                Toast.makeText(context, "clicked it", Toast.LENGTH_SHORT).show();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        AppWidgetManager manager = AppWidgetManager.getInstance(context);
    
                        for (int i = 0; i < 37; i++) {
                            RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
                            remoteViews.setImageViewBitmap(R.id.tv_content,rotateBitmap(bitmap,i*10));
                            Intent clickIntent = new Intent();
                            clickIntent.setAction(fs);
                            PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, clickIntent, 0);
                            remoteViews.setOnClickPendingIntent(R.id.tv_content,pendingIntent);
                            Log.d("8888888", "run: ");
                            manager.updateAppWidget(new ComponentName(context,NewAppWidget.class),remoteViews);
    
                            SystemClock.sleep(30);
    
                        }
                    }
                }).start();
            }
        }
    
        private Bitmap rotateBitmap(Bitmap bitmap,float degree) {
            Matrix matrix = new Matrix();
            matrix.reset();
            matrix.setRotate(degree);
            Bitmap bm = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    
    
            return bm;
        }
    }
    
    • onEnabled 当小部件第一次添加到桌面时调用
    • onUpdate 当小部件被添加或者更新时调用
    • onReceive 作为一个广播,当接接受到Intent消息的时候调用

    4.在AndroidManifest 中声明小部件

      <receiver android:name=".NewAppWidget">
                <intent-filter>
                    <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
                    <action android:name="com.example.admin.customview.click" />
                </intent-filter>
    
                <meta-data
                    android:name="android.appwidget.provider"
                    android:resource="@xml/new_app_widget_info" />
            </receiver>
    

    第一个action 作为小部件的标记存在,在安装时系统让系统检测到包含小部件组件
    第二个action 用于BrocastReceiver 接受点击事件

    相关文章

      网友评论

        本文标题:安卓桌面小部件开发

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