Android实现桌面小部件:今天吃什么

server/2024/11/30 20:11:09/

今天吃什么桌面小部件是专为解决日常选择困难症而设计的安卓小部件,它通过轻松愉快的滚动机制,帮助玩家在诸如“今天吃什么”这样的日常琐事中迅速做出决定。
不知道吃什么?别担心,点我帮你选择!

创建各个UI背景

app_widget_background.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><corners android:radius="?attr/appWidgetRadius" /><solid android:color="#BF000000" /><gradient android:startColor="#66CA740B" android:endColor="#99EACB10" android:angle="80"/>
</shape>

shape_eat_background.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><sizeandroid:width="110dp"android:height="50dp" /><corners android:radius="5dp" /><solid android:color="#FFD154" /><strokeandroid:width="5dp"android:color="#FFD154" />
</shape>

shape_eat_foreground.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><sizeandroid:width="110dp"android:height="50dp" /><corners android:radius="5dp" /><strokeandroid:width="5dp"android:color="#FFE58A" />
</shape>

shape_start_btn.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"><size android:width="110dp" android:height="50dp"/><solid android:color="#E63A75FF"/><corners android:radius="10dp"/><gradient android:startColor="#fd7147" android:endColor="#FFB39C" android:angle="50"/><stroke android:color="#33FFFFFF" android:width="12dp"/>
</shape>

创建小部件布局layout_eat_app_widget.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"xmlns:tools="http://schemas.android.com/tools"tools:layout_height="150dp"tools:layout_width="150dp"android:orientation="vertical"><RelativeLayoutstyle="@style/Widget.TodayEatWhat.AppWidget.Container"android:layout_width="match_parent"android:layout_height="wrap_content"android:theme="@style/Theme.TodayEatWhat.AppWidgetContainer"><ImageViewandroid:id="@+id/iv_background"android:layout_width="match_parent"android:layout_height="wrap_content"android:adjustViewBounds="true"android:contentDescription="@null"android:scaleType="centerCrop"android:src="@drawable/app_widget_background" /><RelativeLayoutstyle="@style/Widget.TodayEatWhat.AppWidget.ContainerInnerView"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignTop="@id/iv_background"android:layout_alignBottom="@id/iv_background"><ImageViewandroid:layout_width="wrap_content"android:layout_height="50dp"android:layout_alignStart="@id/fl_container"android:layout_alignTop="@id/fl_container"android:layout_alignEnd="@id/fl_container"android:layout_marginTop="5dp"android:background="@drawable/shape_eat_foreground"android:backgroundTint="@color/white"android:contentDescription="@null" /><FrameLayoutandroid:id="@+id/fl_container"android:layout_width="match_parent"android:layout_height="50dp"android:background="@drawable/shape_eat_background" /><ImageViewandroid:layout_width="wrap_content"android:layout_height="50dp"android:layout_alignStart="@id/fl_container"android:layout_alignTop="@id/fl_container"android:layout_alignEnd="@id/fl_container"android:background="@drawable/shape_eat_foreground"android:contentDescription="@null" /><TextViewandroid:id="@+id/tv_last_food"android:layout_width="match_parent"android:layout_height="50dp"android:gravity="center"android:shadowColor="#FFE58A"android:shadowDy="1"android:shadowRadius="1"android:text="吃点什么?"android:textColor="@color/white"android:textSize="14sp" /><TextViewandroid:id="@+id/go_btn"android:layout_width="match_parent"android:layout_height="50dp"android:layout_alignParentBottom="true"android:background="@drawable/shape_start_btn"android:gravity="center"android:text="吃点别的"android:textColor="@color/white"android:textSize="13sp"android:textStyle="bold|italic" /></RelativeLayout></RelativeLayout><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:layout_margin="8dp"android:text="@string/app_widget_label"android:textColor="@color/white"android:textSize="12sp" />
</LinearLayout>

创建layoutAnimation动画widget_food_animation.xml

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"android:animation="@anim/widget_food_animation"android:interpolator="@android:anim/overshoot_interpolator" />

创建set>translate动画widget_food_animation.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"android:fillAfter="true"android:interpolator="@android:anim/overshoot_interpolator"><translateandroid:duration="800"android:fromYDelta="0%"android:toYDelta="-900%p" />
</set>

创建动画布局layout_eat_app_widget_textview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/layContent"android:layout_width="match_parent"android:layout_height="wrap_content"android:layoutAnimation="@anim/widget_food_animation_controller"android:orientation="vertical"><TextViewandroid:id="@+id/text1"android:layout_width="match_parent"android:layout_height="50dp"android:gravity="center"android:textColor="@color/white"android:shadowColor="#FFE58A"android:shadowDy="1"android:shadowRadius="1"android:textSize="14sp" /><TextViewandroid:id="@+id/text2"android:layout_width="match_parent"android:layout_height="50dp"android:gravity="center"android:textColor="@color/white"android:shadowColor="#FFE58A"android:shadowDy="1"android:shadowRadius="1"android:textSize="14sp" /><TextViewandroid:id="@+id/text3"android:layout_width="match_parent"android:layout_height="50dp"android:gravity="center"android:textColor="@color/white"android:shadowColor="#FFE58A"android:shadowDy="1"android:shadowRadius="1"android:textSize="14sp" /><TextViewandroid:id="@+id/text4"android:layout_width="match_parent"android:layout_height="50dp"android:gravity="center"android:textColor="@color/white"android:shadowColor="#FFE58A"android:shadowDy="1"android:shadowRadius="1"android:textSize="14sp" /><TextViewandroid:id="@+id/text5"android:layout_width="match_parent"android:layout_height="50dp"android:gravity="center"android:textColor="@color/white"android:shadowColor="#FFE58A"android:shadowDy="1"android:shadowRadius="1"android:textSize="14sp" /><TextViewandroid:id="@+id/text6"android:layout_width="match_parent"android:layout_height="50dp"android:gravity="center"android:textColor="@color/white"android:shadowColor="#FFE58A"android:shadowDy="1"android:shadowRadius="1"android:textSize="14sp" /><TextViewandroid:id="@+id/text7"android:layout_width="match_parent"android:layout_height="50dp"android:gravity="center"android:textColor="@color/white"android:shadowColor="#FFE58A"android:shadowDy="1"android:shadowRadius="1"android:textSize="14sp" /><TextViewandroid:id="@+id/text8"android:layout_width="match_parent"android:layout_height="50dp"android:gravity="center"android:textColor="@color/white"android:shadowColor="#FFE58A"android:shadowDy="1"android:shadowRadius="1"android:textSize="14sp" /><TextViewandroid:id="@+id/text9"android:layout_width="match_parent"android:layout_height="50dp"android:gravity="center"android:textColor="@color/white"android:shadowColor="#FFE58A"android:shadowDy="1"android:shadowRadius="1"android:textSize="14sp" /><TextViewandroid:id="@+id/text10"android:layout_width="match_parent"android:layout_height="50dp"android:gravity="center"android:textColor="@color/white"android:shadowColor="#FFE58A"android:shadowDy="1"android:shadowRadius="1"android:textSize="14sp" /><TextViewandroid:id="@+id/text11"android:layout_width="match_parent"android:layout_height="50dp"android:gravity="center"android:textColor="@color/white"android:shadowColor="#FFE58A"android:shadowDy="1"android:shadowRadius="1"android:textSize="14sp" /></LinearLayout>

创建EatAppWidget.kt 继承 AppWidgetProvider

package com.actionbar.todayeatwhatimport android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.RemoteViews
import java.util.*/*** Implementation of App Widget functionality.*/
class EatAppWidget : AppWidgetProvider() {companion object {private const val TAG = "EatAppWidget"private const val ACTION_EAT_WHAT_UPDATE ="com.actionbar.todayeatwhat.action.EAT_WHAT_UPDATE"private val foodList = arrayListOf("螺蛳粉","酸菜鱼","黄焖鸡米饭","麻辣烫","新疆炒米粉","花甲米线","酸辣粉","鸭血粉丝汤","兰州拉面","炸酱面","南昌拌粉","云吞面","麻辣香锅","蛋炒饭","沙县小吃","卤肉饭","炸鸡汉堡","水饺馄饨","烧烤烤串","烤冷面","北京烤鸭","蒸饺小笼包","披萨","串串香","钵钵鸡","意大利面","寿司饭团","拉面","煎饼","手抓饼","肉夹馍","过桥米线","慕斯蛋糕","羊肉串","烤鱼","墨西哥卷饼","蒜蓉扇贝","小龙虾","剁椒鱼头","盖浇饭","凉面凉皮","手撕兔","豆腐脑","土豆泥","糯米饭","臭豆腐","大盘鸡","辣卤卤菜","曹氏鸭脖","轻食沙拉","湖南米粉","烤苕皮豆干","章鱼小丸子","吐司三明治","春卷","铁板烤鱿鱼","牛排","韩式部队锅","烤肠热狗","水煮肉片","生煎包","锅包肉","糖醋排骨","金汤肥牛","叉烧饭","广东肠粉","热干面","潮汕牛肉火锅","豉汁蒸排骨","酥皮蛋挞","麻辣脆皮鸭","福鼎肉片","东北大拉皮","小炒黄牛肉","羊肉泡馍","油泼面","酱香饼","铁板烧","甜不辣","沙茶面","牛肉炒河粉","台湾炸鸡排","鲜肉蛋堡","捞汁海鲜","冬阴功海鲜","猪扒包","里脊夹饼","菠萝海鲜炒饭","油炸串串","蛋烘糕","糯米鸡","酸汤鱼","鸡汤饭","梅菜扣肉饼","油炸串串","口水鸡","椒麻鸡","烤肉","柴火鸡","葱油饼","辣炒年糕","驴肉火烧","麻辣火锅","重庆小面","烤鳗鱼饭","盐水鸭","烧腊","猪脚面")}private var lastFood: String = "吃点什么?"override fun onReceive(context: Context?, intent: Intent?) {super.onReceive(context, intent)Log.d(TAG, "onReceive() called with: context = $context, intent = $intent")context ?: returnval action = intent?.action ?: returnwhen (ACTION_EAT_WHAT_UPDATE) {action -> {val componentName = ComponentName(context, EatAppWidget::class.java)val appWidgetManager = AppWidgetManager.getInstance(context)val appWidgetIds = appWidgetManager.getAppWidgetIds(componentName)val views = RemoteViews(context.packageName, R.layout.layout_eat_app_widget)doAnimation(context, views, foodList.shuffled())appWidgetManager.partiallyUpdateAppWidget(appWidgetIds, views)}}}override fun onUpdate(context: Context,appWidgetManager: AppWidgetManager,appWidgetIds: IntArray) {Log.d(TAG,"onUpdate() called with: context = $context, appWidgetManager = $appWidgetManager, appWidgetIds = $appWidgetIds")for (appWidgetId in appWidgetIds) {updateAppWidget(context, appWidgetManager, appWidgetId)}}override fun onEnabled(context: Context) {Log.d(TAG, "onEnabled() called with: context = $context")}override fun onDisabled(context: Context) {Log.d(TAG, "onDisabled() called with: context = $context")}override fun onAppWidgetOptionsChanged(context: Context?,appWidgetManager: AppWidgetManager?,appWidgetId: Int,newOptions: Bundle?) {super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions)Log.d(TAG,"onAppWidgetOptionsChanged() called with: context = $context, appWidgetManager = $appWidgetManager, appWidgetId = $appWidgetId, newOptions = $newOptions")}private fun updateAppWidget(context: Context,appWidgetManager: AppWidgetManager,appWidgetId: Int) {val views = RemoteViews(context.packageName, R.layout.layout_eat_app_widget)views.removeAllViews(R.id.fl_container)views.setTextViewText(R.id.tv_last_food, lastFood)val pendingIntent = PendingIntent.getBroadcast(context,UUID.randomUUID().hashCode(),Intent(context, EatAppWidget::class.java).setAction(ACTION_EAT_WHAT_UPDATE),PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)views.setOnClickPendingIntent(R.id.go_btn, pendingIntent)appWidgetManager.updateAppWidget(appWidgetId, views)}private fun doAnimation(context: Context, remoteViews: RemoteViews, shuffled: List<String>) {// 根据layout_eat_app_widget_textview布局里面的TextView的数量来取val foodList = shuffled.subList(0, 11)remoteViews.removeAllViews(R.id.fl_container)// 清空lastFood = ""remoteViews.setTextViewText(R.id.tv_last_food, lastFood)// 下标9是动画结束后显示的结果lastFood = foodList[9]val views = RemoteViews(context.packageName, R.layout.layout_eat_app_widget_textview)foodList.forEachIndexed { index: Int, food: String ->val id = context.resources.getIdentifier("text${index + 1}", "id", context.packageName)if (id > 0) {// 如果是第一条的话,将下标9的内容显示在第一条,防止用户长按小部件拖动时会显示第一条数据的问题if (index == 0) {
//                    views.setTextViewText(id, lastFood+index.toString())views.setTextViewText(id, lastFood)} else {
//                    views.setTextViewText(id, food+index.toString())views.setTextViewText(id, food)}}}remoteViews.addView(R.id.fl_container, views)}
}

strings.xml

<resources><string name="app_name">TodayEatWhat</string><string name="appwidget_text">EXAMPLE</string><string name="app_widget_label">今天吃什么</string><string name="app_widget_description">不知道吃什么?别担心,点我帮你选择!</string>
</resources>

res/xml资源目录中创建eat_app_widget_info.xml

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:description="@string/app_widget_description"android:initialKeyguardLayout="@layout/layout_eat_app_widget"android:initialLayout="@layout/layout_eat_app_widget"android:minWidth="110dp"android:minHeight="110dp"android:previewImage="@drawable/eat_appwidget_preview"android:previewLayout="@layout/layout_eat_app_widget"android:targetCellWidth="2"android:targetCellHeight="2"android:updatePeriodMillis="1800000"android:widgetCategory="home_screen"tools:targetApi="s" />

配置AndroidManifest.xml

<receiverandroid:name=".EatAppWidget"android:enabled="true"android:label="@string/app_widget_label"android:description="@string/app_widget_description"android:exported="false"><intent-filter><action android:name="android.appwidget.action.APPWIDGET_UPDATE" /><action android:name="${applicationId}.action.EAT_WHAT_UPDATE" /></intent-filter><meta-dataandroid:name="android.appwidget.provider"android:resource="@xml/eat_app_widget_info" />
</receiver>

在themes.xml中加入

<style name="Theme.TodayEatWhat.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault"><!-- 用于制作圆角的小部件外部边界的半径 --><item name="appWidgetRadius">16dp</item><!--内部视图的小部件边界的半径,以形成圆角。它需要是8dp或小于appWidgetRadius的值--><item name="appWidgetInnerRadius">8dp</item>
</style><style name="Theme.TodayEatWhat.AppWidgetContainer" parent="Theme.TodayEatWhat.AppWidgetContainerParent"><!-- 应用填充以避免小部件的内容与圆角碰撞 --><item name="appWidgetPadding">10dp</item>
</style>

在styles.xml中加入

<style name="Widget.TodayEatWhat.AppWidget.Container" parent="android:Widget"><item name="android:id">@android:id/background</item><item name="android:background">@drawable/app_widget_background</item>
</style><style name="Widget.TodayEatWhat.AppWidget.ContainerInnerView" parent="android:Widget"><item name="android:padding">?attr/appWidgetPadding</item>
</style>


http://www.ppmy.cn/server/146236.html

相关文章

RocketMQ负载均衡机制解析

消费者在消费消息的时候&#xff0c;需要知道从Broker的哪一个消息队列中去获取消息。 ❝ 所以&#xff0c;在消费者端必须要做负载均衡&#xff0c;即Broker端中多个消费队列分配给同一个消费者组中的哪些消费者消费。 在RocketMQ中&#xff0c;在消费者端有一个&#xff1a;R…

IDEA敲Web前端快捷键

1.html基础格式 英文符号TAB键 <!doctype html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport"content"widthdevice-width, user-scalableno, initial-scale1.0, maximum-scale1.0, mini…

docker查询是否运行

您可以通过运行以下命令来检查Docker是否正在运行&#xff1a; docker info 或者&#xff1a; docker ps 如果Docker正在运行&#xff0c;docker info将显示Docker的详细信息&#xff0c;而docker ps将列出当前运行的容器。如果Docker没有运行&#xff0c;这些命令将会返回错误…

上传镜像docker hub登不上和docker desktop的etx4.vhdx占用空间很大等解决办法

平时使用docker一般都在Linux服务器上&#xff0c;但这次需要将镜像上传到docker hub上&#xff0c;但是服务器上一直无法登录本人的账号&#xff0c;&#xff08;这里的问题应该docker 网络配置中没有开代理的问题&#xff0c;因服务器上有其他用户使用&#xff0c;不可能直接…

鸿蒙生态崛起!!!

方向一&#xff1a;阐述对鸿蒙生态的认知和了解&#xff0c;并对鸿蒙生态的崛起进行简要分析 鸿蒙生态是基于OpenHarmony共建共享的生态&#xff0c;是所有基于OpenHarmony系统&#xff08;开源鸿蒙&#xff09;社区版本开发、并通过开放原子开源基金会的开源鸿蒙认证&#xff…

【连接池】.NET开源 ORM 框架 SqlSugar 系列

.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…

【纯原生js】原生实现h5落地页面中的单选组件按钮及功能

h5端的按钮系统自带的一般都很丑&#xff0c;需要我们进行二次美化&#xff0c;比如单选按钮复选框之类的&#xff0c;那怎么对其进行html和css的改造&#xff1f; 实现效果 实现代码 <section id"tags"><h2>给景区添加标题</h2><label><…

第R4周:LSTM-火灾温度预测(TensorFlow版)

>- **&#x1f368; 本文为[&#x1f517;365天深度学习训练营]中的学习记录博客** >- **&#x1f356; 原作者&#xff1a;[K同学啊]** 往期文章可查阅&#xff1a; 深度学习总结 任务说明&#xff1a;数据集中提供了火灾温度&#xff08;Tem1&#xff09;、一氧化碳浓度…