You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 01:41:30