Android桌面小组件仅显示数组最后一项,如何改为列表展示?
Android桌面小组件仅显示数组最后一项的原因及列表化解决方案
问题说明
Android桌面小组件仅展示数组中的最后一项文本,如何将组件内容改为列表形式?
现有代码
XML布局代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="8dp" android:orientation="vertical" android:background="@drawable/widget_background" android:padding="8dp" android:id="@+id/widget_container"> <TextView android:id="@+id/widget_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="15sp" android:textStyle="bold" tools:text="Title" /> <TextView android:id="@+id/widget_message" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="12sp" tools:text="Message" /> </LinearLayout>
Kotlin Provider代码
val cars = arrayOf("Volvo", "BMW", "Ford", "Mazda") for (i in cars){ val message = widgetData.getString("message", null) setTextViewText(R.id.widget_message, message ?: i) val pendingIntentWithData = HomeWidgetLaunchIntent.getActivity( context, MainActivity::class.java, Uri.parse("homeWidgetExample://message?message=$message")) setOnClickPendingIntent(R.id.widget_message, pendingIntentWithData) } appWidgetManager.updateAppWidget(widgetId, views)
问题截图

原因分析
循环中反复给同一个widget_message TextView设置文本,每次循环都会覆盖之前的内容,最终仅保留数组最后一项的文本。
解决方案
方式一:动态添加TextView(适合短列表)
- 修改布局,替换原单个文本框为列表容器:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="8dp" android:orientation="vertical" android:background="@drawable/widget_background" android:padding="8dp"> <TextView android:id="@+id/widget_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="15sp" android:textStyle="bold" tools:text="Title" /> <!-- 列表容器 --> <LinearLayout android:id="@+id/list_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_marginTop="8dp"/> </LinearLayout>
- 更新Provider代码,循环创建列表项并添加到容器:
val cars = arrayOf("Volvo", "BMW", "Ford", "Mazda") val listContainer = RemoteViews(context.packageName, R.id.list_container) // 清空容器避免重复添加 listContainer.removeAllViews(R.id.list_container) for (itemText in cars) { // 创建单个列表项视图 val itemView = RemoteViews(context.packageName, android.R.layout.simple_list_item_1) itemView.setTextViewText(android.R.id.text1, itemText) // 设置点击事件 val pendingIntent = HomeWidgetLaunchIntent.getActivity( context, MainActivity::class.java, Uri.parse("homeWidgetExample://message?message=$itemText") ) itemView.setOnClickPendingIntent(android.R.id.text1, pendingIntent) // 添加到容器 listContainer.addView(R.id.list_container, itemView) } views.addView(R.id.list_container, listContainer) appWidgetManager.updateAppWidget(widgetId, views)
方式二:使用ListView+RemoteViewsService(适合长列表)
这是Android小组件实现长列表的标准方案:
- 修改布局添加ListView:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="8dp" android:orientation="vertical" android:background="@drawable/widget_background" android:padding="8dp"> <TextView android:id="@+id/widget_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="15sp" android:textStyle="bold" tools:text="Title" /> <ListView android:id="@+id/widget_list" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="8dp"/> </LinearLayout>
- 创建RemoteViewsService和Factory:
// RemoteViewsService class WidgetListService : RemoteViewsService() { override fun onGetViewFactory(intent: Intent): RemoteViewsFactory { return WidgetListFactory(applicationContext) } } // RemoteViewsFactory class WidgetListFactory(private val context: Context) : RemoteViewsService.RemoteViewsFactory { private val cars = arrayOf("Volvo", "BMW", "Ford", "Mazda") override fun onCreate() {} override fun onDataSetChanged() {} override fun onDestroy() {} override fun getCount(): Int = cars.size override fun getViewAt(position: Int): RemoteViews { val itemView = RemoteViews(context.packageName, android.R.layout.simple_list_item_1) itemView.setTextViewText(android.R.id.text1, cars[position]) // 设置点击事件 val intent = Intent(context, MainActivity::class.java).apply { data = Uri.parse("homeWidgetExample://message?message=${cars[position]}") } val pendingIntent = PendingIntent.getActivity( context, position, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) itemView.setOnClickPendingIntent(android.R.id.text1, pendingIntent) return itemView } override fun getLoadingView(): RemoteViews? = null override fun getViewTypeCount(): Int = 1 override fun getItemId(position: Int): Long = position.toLong() override fun hasStableIds(): Boolean = true }
- 在Manifest中注册Service:
<service android:name=".WidgetListService" android:permission="android.permission.BIND_REMOTEVIEWS" />
- 更新Provider代码关联ListView:
val intent = Intent(context, WidgetListService::class.java) views.setRemoteAdapter(R.id.widget_list, intent) // 设置点击事件模板 val templateIntent = Intent(context, MainActivity::class.java) val templatePendingIntent = PendingIntent.getActivity( context, 0, templateIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setPendingIntentTemplate(R.id.widget_list, templatePendingIntent) appWidgetManager.updateAppWidget(widgetId, views)
内容的提问来源于stack exchange,提问作者hafidzaini
相关产品推荐
相关产品推荐

