android widget 开发

   因为项目中需要用到widget,所以在这里大致记录一下widget的使用流程。因为没有深入的研究,所以仅仅是做一个大概的解析,因为需求简单,这里就不介绍RemoteViewService和RemoteViewFactory了,如果需要的不要浪费时间看下去,抱歉各位。widget也叫小部件,是一个微型视图,其实在手机launcher中的表就是个widget。在开始流程之前需要明白两个概念:

    AppWidgetProviderInfo

描述小部件的元数据元素,包括描述了部件的布局和更新频率,以及AppWidgetProvider的信息

   AppWidgetProvider

基于广播事件,,在这里可以对widget进行一些操作,包括widget的启用,更新,删除等操作。因为继承自BroadcastReceiver,因此也可以根据最基本的广播操作来进行事件的处理。

   接下来就是开始创建widget,其实过程比较简单,studio提供了很多帮助:

     在这里直接创建widget,填写细节之后,就会生成一个继承自AppWidgetProvider的类,

public class MyWidget extends AppWidgetProvider {

    static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                                int appWidgetId) {

        //在这里进行部件的更新。需要怎样操控部件都可以再这里通过RemoteViews实现。
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);
        appWidgetManager.updateAppWidget(appWidgetId, views);
    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        //这里会遍历所有的部件,然后都进行更新。
        for (int appWidgetId : appWidgetIds) {

            updateAppWidget(context, appWidgetManager, appWidgetId);
        }
    }

    @Override
    public void onEnabled(Context context) {
        // 当widget被创建的时候调用。
    }

    @Override
    public void onDisabled(Context context) {
        // Enter relevant functionality for when the last widget is disabled
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        //这里可以接收自定义的一些广播,进行处理。
    }
}

     同时在androidManifest文件中也会生成MyWidget的注册内容

<receiver
            android:name=".widget.MyWidget"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <!-- 在这里还可以添加其他自定义的广播 -->
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>

            <!-- widget的配置信息文件 -->
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/new_app_widget_info" />
        </receiver>

   其中name属性表明类名,intent-filter表示的是接收的广播action,meta中的属性name表示meta-data的名称,这里必须是android.appwidget.provider, resource这里是表示资源文件的目录。接下来看资源文件:

<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="170dp"
    android:minWidth="250dp"
    android:previewImage="@drawable/example_appwidget_preview"
    android:resizeMode="horizontal|vertical"
    android:updatePeriodMillis="86400000"
    android:widgetCategory="home_screen"></appwidget-provider>

     initialkeyguardlayout表示了一个资源文件,在widget创建的时候可以立刻出现。4.2以后引入的。

     initialLayout 表示了widget的资源文件。

     minHeight和minWidth定义了widget的最小高和宽,低于这个值widget不可以用。

     previewImage这个就是一个预览图的效果。就像app的桌面logo,默认是applogo。

     resizeMode:指定widget大小在哪个方向调整。

     updatePerionMillis:这个只的是部件的更新频率,最小是半小时,设置的很小也会默认为半小时。

     widgetCategory:表示部件是否可以显示在主屏上,默认home_screen,还有power属性。

     到这里就可以通过new_app_widget这个布局文件来写小部件的布局了。需要注意的是这个布局文件支持的控件是有限制的, 首先自定义的控件不支持, 支持的布局控件如下:

     布局:FrameLayout,RelativeLayout,Linearlayout,GridLayout

     控件:Button,ImageButton, ImageView,TextView,ListView,GridView,AnalogClock,Progressbar,ViewFlpper,StackView

     更新部件的功能都是通过RemoteView来实现的,至于怎样更新可以根据自己的需求来定。如果用到listview,gridview等布局可以通过RemoteviewService来实现这个部件的更新,在我的项目里比较简单,直接通过启动一个service进行来更新:在MyWidget中的onenable中通过启动一个service来实现更新,

private void updateWidget(Context context, WeatherWrap weatherWrap) {
        if (weatherWrap == null) {
            return;
        }
        ComponentName componentName = new ComponentName(context, WeatherWidget.class);
        RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);

        remoteViews.setTextViewText(R.id.temperature, weatherWrap.getNow().getTemp()+"°C");
        remoteViews.setTextViewText(R.id.weather_status, DBHelper.getInstance().getWeatherTypeByCode(
                weatherWrap.getNow().getWeatherType()));
        remoteViews.setTextViewText(R.id.city, weatherWrap.getRegion());


        remoteViews.setTextViewText(R.id.air_quality, weatherWrap.getAqi().getAqi() + " "
                + weatherWrap.getAqi().getQuality());

        if (weatherWrap.getSuggestion().getDressing() != null) {
            remoteViews.setTextViewText(R.id.clothing_index, weatherWrap.getSuggestion().getDressing().getBrief());
        }
        remoteViews.setTextViewText(R.id.humidity, weatherWrap.getNow().getHumidity() + "%");

        if(weatherWrap.getSuggestion().getHongfans() != null){
            remoteViews.setTextViewText(R.id.env_status,weatherWrap.getSuggestion().getHongfans().getDetails());
        }

        remoteViews.setImageViewResource(R.id.weather_bg, Utils.weatherCode2BG(weatherWrap.getNow().getWeatherType()));

        //在这里添加一个点击事件,当点击id为city的按钮会跳转到制定activity
        Intent intent = new Intent(context, WeatherActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
        remoteViews.setOnClickPendingIntent(R.id.city, pendingIntent);

        AppWidgetManager awm = AppWidgetManager.getInstance(context.getApplicationContext());
        awm.updateAppWidget(componentName, remoteViews);
    }

        可以看到remoteVIew的设置控件内容的方式,以及点击跳转的方式。最后都需要通过AppWidgetManager来进行更新。在MyWidget文件的updateAppWidget()函数中也需要添加好更新widget的方法。至于具体的更新方式要根据自己的项目需求而定。

    

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值