我正在为应用程序开发Android Widget,问题是我无法在onClickPendingIntent()
的按钮上设置RemoteViewsFactory
。
我向您解释:我创建了一个AppWidgetProvider
,它调用了RemoteViewsService
的扩展,并调用了RemoteViewsFactory
的扩展以在我的小部件中完成一个ListView
。RemoteViewsFactory
必须返回所有项目以进行更新或创建它们并显示在小部件上。但是对于列表视图的每个项目,我有2种类型的按钮:
问题是第二个按钮,我的解决方案不起作用。
这是问题所在:
因此,这是无效的代码:
row.setOnClickPendingIntent(R.id.taskButton, onClickPendingIntent);
// Creating an onclick event for the done button
Intent doneIntent = new Intent(mContext, WidgetProvider.class);
doneIntent.putExtra("DONE_TASK", "DOOOOM");
PendingIntent onDoneIntent = PendingIntent.getActivity(mContext, 0, doneIntent, 0);
row.setOnClickPendingIntent(R.id.doneButton, onDoneIntent);
这是完整的
WidgetFactory
类:import java.util.Collections;
import java.util.Comparator;
import java.util.GregorianCalendar;
import java.util.Vector;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.view.View;
import android.widget.RemoteViews;
import android.widget.RemoteViewsService;
public class WidgetFactory implements RemoteViewsService.RemoteViewsFactory {
private Vector<EventInfo> mAllEvents;
private Context mContext;
public WidgetFactory(Context ctxt, Intent intent) {
// Creating member vars
mContext = ctxt;
updateAllEventsVector();
}
private void updateAllEventsVector() {
SharedInstances sharedInstances = SharedInstances.get();
mAllEvents = new Vector<EventInfo>();
if (sharedInstances != null) {
TaskRequestManager taskManager = sharedInstances
.getTaskRequestManager();
CalendarRequestManager calManager = sharedInstances
.getCalendarRequestManager();
Vector<TaskEvent> tasks = null;
Vector<CalendarEvent> events = null;
if (taskManager != null)
tasks = taskManager.readTasksToday(mContext);
if (calManager != null)
events = calManager.readCalendarEventsToday(mContext);
if (!tasks.isEmpty())
mAllEvents.addAll(tasks);
if (!events.isEmpty())
mAllEvents.addAll(events);
mAllEvents = sortByDate(mAllEvents);
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public Vector<EventInfo> sortByDate(Vector<EventInfo> events)
{
Vector<EventInfo> sortedEvents = new Vector<EventInfo>();
for(EventInfo event : events)
{
if ((event.getStartTime()+event.getEventDuration()) > GregorianCalendar.getInstance().getTimeInMillis())
sortedEvents.add(event);
}
Collections.sort(events, new Comparator() {
public int compare(Object arg0, Object arg1)
{
EventInfo event0 = (EventInfo)arg0;
EventInfo event1 = (EventInfo)arg1;
if (event0.getStartTime()+event0.getEventDuration() > event1.getStartTime()+event1.getEventDuration())
return 1;
else if (event0.getStartTime()+event0.getEventDuration() == event1.getStartTime()+event1.getEventDuration())
return 0;
else if (event0.getStartTime()+event0.getEventDuration() < event1.getStartTime()+event1.getEventDuration())
return -1;
return 0;
}
});
return sortedEvents;
}
@Override
public int getCount() {
return mAllEvents.size();
}
@Override
public long getItemId(int arg0) {
return (arg0);
}
@Override
public RemoteViews getLoadingView() {
return null;
}
@Override
public RemoteViews getViewAt(int position) {
// Getting item view
RemoteViews row = new RemoteViews(mContext.getPackageName(),
R.layout.done_task_item);
EventInfo eventInfo = mAllEvents.get(position);
row.setInt(R.id.item_event, "setBackgroundColor", Color.argb(60, Color.red(eventInfo.getColor()), Color.green(eventInfo.getColor()), Color.blue(eventInfo.getColor())));
// Converts startTime and endTime in string
String startTime = TimeCursor.getAdaptativeTime(eventInfo.getStartTime());
String endTime = TimeCursor.getAdaptativeTime((eventInfo
.getEventDuration() + eventInfo.getStartTime()));
//Get title
String title = eventInfo.getTitle();
// Setting data in the view
row.setTextViewText(R.id.titleTask, title);
row.setTextViewText(R.id.periodTask, startTime + " to " + endTime);
//Check type of event
if (eventInfo.isTask()) {
//endDate > GregorianCalendar.getInstance().getTimeInMillis() ) {
//Check if action exists
if (eventInfo.getAction() != null) {
//Get the action title
String action = eventInfo.getAction()
.getTitleText();
//Create a onClickPendingIntent for taskButton
PendingIntent onClickPendingIntent = null;
//Add related button
if (action.equals("Call"))
{
//Set call icon to taskButton
row.setImageViewResource(R.id.taskButton, R.drawable.ic_call_white );
//Get numbers from the contact
Vector<TelOrEmailItem> tel = eventInfo.getContact().getAllPhoneNumbers(mContext.getResources() , mContext, eventInfo.getAction());
// Creating an onclick event for call somebody
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:"+tel.get(0).getMainText()));
onClickPendingIntent = PendingIntent.getActivity(
mContext, 0, callIntent, 0);
}
else if (action.equals("SMS"))
{
//Set sms icon to taskButton
row.setImageViewResource(R.id.taskButton, R.drawable.ic_sms_white);
//Get numbers from the contact
Vector<TelOrEmailItem> tel = eventInfo.getContact().getAllPhoneNumbers(mContext.getResources() , mContext, eventInfo.getAction());
// Creating an onclick event for call somebody
Intent smsIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:"+tel.get(0).getMainText()));
onClickPendingIntent = PendingIntent.getActivity(
mContext, 0, smsIntent, 0);
}
/*else if (action.equals("Chat with"))
row.setImageViewResource(R.id.taskButton, R.drawable.ic_chat_white);*/
else if (action.equals("eMail") || action.equals("Mail") || action.equals("Write to"))
{
//Set email icon to taskButton
row.setImageViewResource(R.id.taskButton, R.drawable.ic_email_white);
//Get numbers from the contact
Vector<TelOrEmailItem> tel = eventInfo.getContact().getAllEMails(mContext, eventInfo.getAction());
//Creating an onclick event for email somebody
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setType("plain/text");
emailIntent.putExtra(Intent.EXTRA_EMAIL,
new String[]{tel.get(0).getMainText()});
onClickPendingIntent = PendingIntent.getActivity(
mContext, 0, emailIntent, 0);
}
/*else if (action.equals("Skype"))
row.setImageViewResource(R.id.taskButton, R.drawable.ic_skype_white);*/
//Assign the intent to the taskButton
row.setOnClickPendingIntent(R.id.taskButton, onClickPendingIntent);
// Creating an onclick event for the done button
Intent doneIntent = new Intent(mContext, WidgetProvider.class);
doneIntent.putExtra("DONE_TASK", "DOOOOM");
PendingIntent onDoneIntent = PendingIntent.getActivity(mContext, 0, doneIntent, 0);
row.setOnClickPendingIntent(R.id.doneButton, onDoneIntent);
}
else
row.setViewVisibility(R.id.taskButton, View.GONE); //hidde the taskButton
return row;
}
//Check if it's an event
else if(eventInfo.isEvent()) {
//hidde task button (Done)
row.setViewVisibility(R.id.doneButton, View.GONE);
CalendarEvent ev = eventInfo.getCalendarEvent();
String location = ev.getEventLocation();
if (location != null && !location.isEmpty())
{
//Set the locate icon on the taskButton
row.setImageViewResource(R.id.taskButton, R.drawable.ic_locate_white);
//Define the place to open the map
Intent mapIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q="+location));
PendingIntent onMapIntent = PendingIntent.getActivity(
mContext, 0, mapIntent, 0);
row.setOnClickPendingIntent(R.id.taskButton, onMapIntent);
}
else
row.setViewVisibility(R.id.taskButton, View.GONE);
return row;
}
return null;
}
@Override
public int getViewTypeCount() {
return 1;
}
@Override
public boolean hasStableIds() {
return (true);
}
@Override
public void onCreate() {
}
@Override
public void onDataSetChanged() {
// On data changes, update mTasks
updateAllEventsVector();
}
@Override
public void onDestroy() {
mAllEvents = null;
}
}
谢谢你:)
编辑:
耶!
问题是否解决...
方法
onClickPendingIntent()
现在可以使用,下面是代码:// Creating an onclick event for the done button
Intent onClickDone = new Intent(mContext, DoneTaskActivity.class);
onClickDone.putExtra("TASK_ID", eventInfo.getTaskEvent().getTaskId());
PendingIntent onClickPendingDone = PendingIntent.getActivity(mContext, 0, onClickDone, 0);
row.setOnClickPendingIntent(R.id.doneButton, onClickPendingDone);
但是存在另一个问题:
DoneTaskActivity
没有收到额外的声明为TASK_ID
的消息。在onCreate()
的DoneTaskActivity
方法中,参数Bundle
var保留为null
。救命 :(
最佳答案
在小部件中使用列表视图时,您需要使用setOnClickFillInIntent侦听器。来自官方文档;
在小部件中使用集合(例如ListView,StackView等)时,它会
在各个项目上设置PendingIntents的成本很高,并且
因此不允许。相反,可以将一个PendingIntent模板
集合上
在RemoteViewsFactory内部,您可以像这样使用它;
public RemoteViews getViewAt(int position) {
// position will always range from 0 to getCount() - 1.
// Construct a RemoteViews item based on the app widget item XML file, and set the
// text based on the position.
RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text);
// Next, set a fill-intent, which will be used to fill in the pending intent template
// that is set on the collection view in StackWidgetProvider.
Bundle extras = new Bundle();
extras.putInt(StackWidgetProvider.EXTRA_ITEM, position);
Intent fillInIntent = new Intent();
fillInIntent.putExtras(extras);
// Make it possible to distinguish the individual on-click
// action of a given item
rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent);
...
// Return the RemoteViews object.
return rv;
}
您还需要使用标准的PendingIntent,因为单个列表项无法设置PendingIntent,请参阅AppWidgets上的文档。