android学习笔记

android的widget基础用法

2019-05-22  本文已影响0人  heheworld

准备工作

app\src\main\res\xml\下新建一个appwidget-provider文件,文件名:test_widget_info
内容如下:

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/test_widget" //widget 布局文件
    android:minWidth="300dp"  //widget最小宽度
    android:minHeight="200dp" // widget最小高度
    android:resizeMode="horizontal|vertical" 
    android:updatePeriodMillis="86400000"  // 最短刷新时间间隔
    android:previewImage="@drawable/widget_preview" //widget选择列表里的预览图
    android:widgetCategory="home_screen"></appwidget-provider>  // 类型 主屏,还有种是基于锁屏的

androidmanifest文件里注册下widget,可以看出widget是继承自receiver的。
public class AppWidgetProvider extends BroadcastReceiver
我们的widget继承AppWidgetProvider
AndroidManifest配置文件里加上

        <receiver android:name=".widget.appwidget.TestWidget">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> // 这个action类似于广播的action
            </intent-filter>
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/test_widget_info" />  //指向我们刚配置的文件
        </receiver>

写一个widget继承AppWidgetProvider

public class TestWidget extends AppWidgetProvider {


    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);
        //更新widget会调用这个方法
    }

    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        super.onDeleted(context, appWidgetIds);
        //删除widget时调用这个方法
    }

    @Override
    public void onEnabled(Context context) {
        super.onEnabled(context);
        //widget被第一次添加时会调用这个方法,这个方法应该只会有系统来调用
    }

    @Override
    public void onDisabled(Context context) {
        super.onDisabled(context);
        // 最后一个widget被删除时会调用这个方法
    }
}

简单看下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);
                }
            }
        }
    }

具体UI相关的。
widget的view还比较特殊,叫RemoteViews
跟我们常见的view集成viewgroup不同,它继承的是Parcelable, Filter
自然不能用findviewbyid之类的,代码里动态设置布局什么的都不太好搞了
但官方也给我们开放了一些接口用来设置控件。

基础的 设置textview,imageview


RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.test_widget); //test_widget.xml 就是widgetview的布局文件
views.setTextViewText(R.id.tv, "helloworld");
views.setImageViewResource(R.id.iv,R.drawable/test_iv);

设置点击事件


        Intent intent = new Intent(context, NewActivity.class);
        PendingIntent pIntent = PendingIntent.getActivity(context, UUID.randomUUID().hashCode(),
                upload, PendingIntent.FLAG_UPDATE_CURRENT);//widget如果有多个点击事件需要这么写,否则点击事件只响应最先设置的那个
        views.setOnClickPendingIntent(R.id.btn, pIntent);

结束语:
基础的东西大概就这么多了。
个人觉得remoteview需要仔细研究下源码,不然没法使用一些图片加载框架,很不方便

另外widget也不支持constraint-layout,(手头华为,三星,vivo,小米都试了不行),很不美好
强上后报的异常日志

 Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.constraint.ConstraintLayout" on path: DexPathList[[zip file "/system/app/HwLauncher6/HwLauncher6.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
        at android.view.LayoutInflater.createView(LayoutInflater.java:590)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:762)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:501) 
        at android.view.LayoutInflater.inflate(LayoutInflater.java:425) 
        at android.widget.RemoteViews.apply(RemoteViews.java:2636) 
        at android.appwidget.AppWidgetHostView.updateAppWidget(AppWidgetHostView.java:401) 
        at android.appwidget.AppWidgetHost.createView(AppWidgetHost.java:325) 
        at com.huawei.android.launcher.Launcher.addWidgetToScreen(Launcher.java:3053) 
        at com.huawei.android.launcher.Launcher.completeAddAppWidget(Launcher.java:3118) 
        at com.huawei.android.launcher.Launcher.addAppWidgetImpl(Launcher.java:4056) 
        at com.huawei.android.launcher.Launcher.addAppWidgetFromDrop(Launcher.java:4130) 
        at com.huawei.android.launcher.Workspace.addPendingAddItemInfoToDesktop(Workspace.java:9914) 
        at com.huawei.android.launcher.Workspace$9.run(Workspace.java:5676) 
        at com.huawei.android.launcher.DragLayer$3.onAnimationEnd(DragLayer.java:982) 
        at android.animation.ValueAnimator.endAnimation(ValueAnimator.java:1171) 
        at android.animation.ValueAnimator$AnimationHandler.doAnimationFrame(ValueAnimator.java:722) 
        at android.animation.ValueAnimator$AnimationHandler.run(ValueAnimator.java:738) 
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:799) 
        at android.view.Choreographer.doCallbacks(Choreographer.java:612) 
        at android.view.Choreographer.doFrame(Choreographer.java:580) 
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:785) 
        at android.os.Handler.handleCallback(Handler.java:739) 
        at android.os.Handler.dispatchMessage(Handler.java:95) 
        at android.os.Looper.loop(Looper.java:135) 
        at android.app.ActivityThread.main(ActivityThread.java:5593) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:372) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:967) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:762) 
        Suppressed: java.lang.ClassNotFoundException: android.support.constraint.ConstraintLayout
        at java.lang.Class.classForName(Native Method)
        at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
        at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
                ... 30 more

上一篇 下一篇

猜你喜欢

热点阅读