实践--桌面小组件之天气小组件

  • 首先感谢这篇博客的博主,通过他的博客才学会的如何使用小组件。
  • 效果图如下
    这里写图片描述

  • 关于小组件的原理已经在 UI控件–桌面小组件(1)介绍过了,又需要的自行去浏览。

1.在res/xml下创建配置文件appwidget_provider.xml

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="250dp"
    android:minHeight="50dp"
    android:updatePeriodMillis="86400000"
    android:initialLayout="@layout/layout_widget">
</appwidget-provider>

2.配置文件布局appwidget_provider.xml

  • 布局就是简单的相对布局和线性布局的简单组合
    这里写图片描述
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/widget_bg"
    android:orientation="vertical"
    android:padding="5dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true">

        <TextView
            android:id="@+id/textView_widget_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="10:25"
            android:textColor="@color/colorWhite"
            android:textSize="50dp" />

        <ImageView
            android:id="@+id/imageView_widget_location"
            android:layout_width="15dp"
            android:layout_height="15dp"
            android:layout_below="@+id/textView_widget_time"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="3dp"
            android:src="@mipmap/widget_local" />

        <TextView
            android:id="@+id/textView_widget_location"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/textView_widget_time"
            android:layout_toRightOf="@+id/imageView_widget_location"
            android:text="位置"
            android:textColor="@color/colorWhite"
            android:textSize="15dp" />


        <ImageView
            android:id="@+id/imageView_widget_weather_ic1"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="20dp"
            android:src="@mipmap/wind_power_pic" />


        <TextView
            android:id="@+id/textView_widget_avgTemp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_marginTop="5dp"
            android:text="30℃ 阴"
            android:textColor="@color/colorWhite"
            android:textSize="20dp" />

        <TextView
            android:id="@+id/textView_widget_lowHighTemp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_below="@+id/textView_widget_avgTemp"
            android:text="18/30℃"
            android:textColor="@color/colorWhite"
            android:textSize="20dp" />

        <TextView
            android:id="@+id/textView_widget_date"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_below="@+id/textView_widget_lowHighTemp"
            android:text="4-24 星期日"
            android:textColor="@color/colorWhite"
            android:textSize="20dp" />
    </RelativeLayout>

</RelativeLayout>

通过扩展系统类AppWidgetProvider来实现,主要是重写里面的函数来完成你所需要的功能。

  • 这一部分是重点
  • 由于这个组件是我写的一个天气相关的小软件里的,所以里面会有一些从数据库获取的数据操作,不过大体给相对控件设置内容的操作都是一个原理。
public class MyWedget01 extends AppWidgetProvider {
    //这些是我的数数据库的获取数据的实例
    private CoolWeatherDB coolWeatherDB;
    private List<CountyWeather> listWeather;

    @Override
    public void onEnabled(Context context) {
        super.onEnabled(context);
    }
    //初始化我的数据库相关的实例
    private void initDB(Context context) {
        coolWeatherDB = CoolWeatherDB.newInstance(context);
        listWeather = coolWeatherDB.loadCountyWeather();
    }

    @Override
    public void onUpdate(final Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);
        updateMywidget(context, appWidgetManager);
    }

    //update是我用来更新小组件上内容提取的一个方法
    private void updateMywidget(Context context, AppWidgetManager appWidgetManager) {
        initDB(context);
        //定义了一个RemoteViews 实例,加载的布局就是我们刚刚定义的小组件的布局
        RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.layout_widget);
        //这些代码是不是看着很眼熟,没错,这里和自定义notification很是相似
        //就是更具刚才定义的RemoteViews 设置其当中的各种子控件的内容,这里不用数据库,直接设置内容也是可以的
        rv.setTextViewText(R.id.textView_widget_time, new SimpleDateFormat("hh:mm").format(System.currentTimeMillis()));
        rv.setTextViewText(R.id.textView_widget_location, listWeather.get(0).getCitynm());
        rv.setTextViewText(R.id.textView_widget_avgTemp, ((Integer.parseInt(listWeather.get(0).getTemp_high()) + (Integer.parseInt(listWeather.get(0).getTemp_low()))) / 2) + "℃ " + listWeather.get(0).getWeather());
        rv.setTextViewText(R.id.textView_widget_lowHighTemp, listWeather.get(0).getTemp_low() + "/" + listWeather.get(0).getTemp_high() + "℃");
        String date = listWeather.get(0).getDays().substring(5, 10);
        rv.setTextViewText(R.id.textView_widget_date, date + " " + listWeather.get(0).getWeek());
        String weather;
        //下面这就是我根据天气的不同,来加载不同的图片,显示在小控件上的操作
        if (listWeather.get(0).getWeather().contains("转")) {
            weather = listWeather.get(0).getWeather().substring(0, listWeather.get(0).getWeather().indexOf("转"));
        } else {
            weather = listWeather.get(0).getWeather();
        }

        if (weather.contains("晴")) {
            rv.setImageViewResource(R.id.imageView_widget_weather_ic1, R.mipmap.icon_sunnay);
        } else if (weather.contains("雨")) {
            rv.setImageViewResource(R.id.imageView_widget_weather_ic1, R.mipmap.icon_yu);
        } else if (weather.contains("雪")) {
            rv.setImageViewResource(R.id.imageView_widget_weather_ic1, R.mipmap.icon_xue);
        } else if (weather.contains("霾")) {
            rv.setImageViewResource(R.id.imageView_widget_weather_ic1, R.mipmap.icon_mai);
        } else if (weather.contains("多云")) {
            rv.setImageViewResource(R.id.imageView_widget_weather_ic1, R.mipmap.icon_duoyun);
        } else if (weather.contains("阴")) {
            rv.setImageViewResource(R.id.imageView_widget_weather_ic1, R.mipmap.icon_yintian);
        } else {
            rv.setImageViewResource(R.id.imageView_widget_weather_ic1, R.mipmap.icon_duoyun);
        }
        //最后,调用调用组件管理器的修改所有小组件,让刚才的更改生效
        ComponentName componentName = new ComponentName(context, MyWedget01.class);
        appWidgetManager.updateAppWidget(componentName, rv);
    }

    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        super.onDeleted(context, appWidgetIds);
    }

    //我们在一篇博客中说过,小组件是基于广播实现的,所以它可以接受广播并处理,我在这里的处理是我收到广播后,就更新小组件
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
        updateMywidget(context, appWidgetManager);
    }

}

小组件是基于广播的,所以必须在AndroidManifest文件中注册

  • android.appwidget.action.APPWIDGET_UPDATE
  • 是系统定义的小组件的广播
        <receiver
            android:name=".widget.MyWedget01"
            android:label="电雨天气4*1">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/appwidget_provider01" />
        </receiver>
  • 大概代码就是这些
  • 小组件的点击事件我没写实现,基本实现和notification是一样的
  • 通过PendingIntent我们可以发送官博,开启活动等等。
          Intent intent = new Intent("update_appwidget_textview");
          intent.putExtra("appWidgetId", appWidgetId);
          PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent,
                           PendingIntent.FLAG_CANCEL_CURRENT);
          点击按钮将触发广播,当前接收器将即时接收和处理广播消息
          views.setOnClickPendingIntent(R.id.mybutton, pendingIntent);

小补充,要实现时间实时变化,我们需要接收系统的时间变化的广播

  • 系统时间变化的Action
  • android.intent.action.TIME_TICK

  • 需要注意的是,这个接收系统时间变化的广播,只能在代码动态注册,静态注册不会接收相应的广播动作,并且这个广播是分钟改变才会发送的,秒的变化不会发送广播的

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
你可以通过以下步骤在Android上动态添加桌面组件: 1. 创建小组件布局:首先,创建一个布局文件来定义小组件的外观。这可以在res/layout目录下的XML文件中完成。你可以使用不同的视图和布局来设计小组件。 2. 创建小组件提供者:创建一个扩展AppWidgetProvider类的Java类。这个类将负责处理小组件的生命周期事件,例如创建、更新和删除小组件。 3. 配置小组件提供者:在AndroidManifest.xml文件中,注册你的小组件提供者类。使用<receiver>标签来指定小组件提供者类,并使用<intent-filter>标签来定义处理小组件生命周期事件的操作。 4. 更新桌面:当用户将小组件拖放到桌面时,你需要在运行时动态添加小组件。为此,你可以使用AppWidgetManager类的updateAppWidget()方法来更新小组件视图。 下面是一个示例代码,展示如何动态添加桌面组件: ```java // 创建小组件布局 RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout); // 配置小组件点击事件 Intent intent = new Intent(context, MyWidgetProvider.class); intent.setAction("ACTION_WIDGET_CLICKED"); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0); remoteViews.setOnClickPendingIntent(R.id.widget_button, pendingIntent); // 更新桌面组件 AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); ComponentName componentName = new ComponentName(context, MyWidgetProvider.class); appWidgetManager.updateAppWidget(componentName, remoteViews); ``` 请注意,你需要根据你的需求适应以上代码,并根据你的小组件布局和逻辑进行修改。 希望这能帮助到你!如有任何进一步的问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值