如何为AppWidget中RemoteViews的日期TextView动态设ID及区分点击?
Android AppWidget日历日期点击问题解答
代码片段
for (week in 0 until 6) { val rowRv = RemoteViews(context.packageName, R.layout.w_calendar_row_week_wrapper) for (day in 0..6) { ... // Set date into cell // I need to distinguish textviews later - to choose the date by the click dateTextCellRv.setTextViewText( android.R.id.text1, cal.get(Calendar.DAY_OF_MONTH).toString() ) // For click on the chosen date val getDateNumber = cal.get(Calendar.DAY_OF_MONTH).toString().toInt() val clickOnChosenDate: PendingIntent = Intent(context, WidgetCalendarProvider::class.java).let { intent -> intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) intent.putExtra("passedDate$appWidgetId", getDateNumber) intent.action = ACTION_CHOSEN_DATE_CLICK_CALENDAR PendingIntent.getBroadcast( context, appWidgetId, intent, PendingIntent.FLAG_IMMUTABLE ) } dateTextCellRv.setOnClickPendingIntent( android.R.id.text1, clickOnChosenDate ) rowRv.addView(R.id.row_week_wrapper_w_calendar, cellRv) cal.add(Calendar.DAY_OF_MONTH, 1) } rViews.addView(R.id.calendar_view_w_calendar, rowRv) }
问题解答
1. 如何为所有显示日期的TextView动态设置ID?
RemoteViews是跨进程的视图容器,不支持直接调用View的setId()方法动态设置ID——它只能执行预定义的有限操作,无法直接修改View的底层属性。
实际开发中完全不需要给每个TextView设置唯一ID,建议通过点击事件的参数传递来关联对应的日期。如果一定要做标识,可以在循环中用week和day的组合生成唯一标记(比如val uniqueTag = "date_${week}_${day}"),但这个标记无法直接绑定到RemoteViews的TextView上,因此还是优先用Intent传递参数的方案更可靠。
2. 使用android.R.id.text1时,能否区分每个TextView的点击以获取对应文本值?
不能直接通过ID区分(所有单元格共用同一个android.R.id.text1),而且RemoteViews不允许跨进程直接获取TextView的文本内容。但可以通过以下方式实现点击区分:
- 修改PendingIntent的requestCode:你当前用
appWidgetId作为requestCode,会导致所有日期的PendingIntent被复用,点击时只会拿到最后一个日期的参数。需要给每个日期生成唯一的requestCode,比如appWidgetId * 100 + week *7 + day,确保每个PendingIntent都是独立的。 - 传递完整日期参数:不要只传递日(
DAY_OF_MONTH),建议把年、月、日都放到Intent的extra里,避免跨月日期混淆(比如上月最后几天和下月开头几天)。修改后的示例代码:
val year = cal.get(Calendar.YEAR) val month = cal.get(Calendar.MONTH) val dayOfMonth = cal.get(Calendar.DAY_OF_MONTH) val intent = Intent(context, WidgetCalendarProvider::class.java).apply { putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) putExtra("DATE_YEAR", year) putExtra("DATE_MONTH", month) putExtra("DATE_DAY", dayOfMonth) action = ACTION_CHOSEN_DATE_CLICK_CALENDAR } val clickOnChosenDate = PendingIntent.getBroadcast( context, appWidgetId * 100 + week *7 + day, // 唯一requestCode intent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT )
- 在广播接收器中解析参数:在
WidgetCalendarProvider的onReceive方法里,直接从Intent的extra中取出年、月、日,就能明确知道点击的是哪个日期,完全不需要获取TextView的文本。
内容的提问来源于stack exchange,提问作者bic55
相关产品推荐
相关产品推荐

