我有一个小部件(AppWidgetProvider),我想知道是否有办法支持多次点击。例如:
1)如果是第一次点击窗口小部件,则窗口小部件的ImageButton会发生变化(例如,更改颜色)。
2)如果是第二次,则打开一个活动。
- 有一些方法可以处理AppWidgetProvider中的点击事件吗?
我的代码:
public class MyWidgetProvider extends AppWidgetProvider
{
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
Intent intent = new Intent(context, MyActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.control_widget);
views.setOnClickPendingIntent(R.id.asdf, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}
我的小部件工作正常。当我单击ImageButton(R.id.asdf)时,它将转到活动MyActivity。
我想知道如何处理我的小部件上的点击事件以进行不同的操作(例如:更改ImageButton的颜色)而不是去某些活动。除了setOnClickPendingIntent()之外还有其他一些点击句柄吗?
答案 0 :(得分:5)
也许这可能会有所帮助。它对我有用:
public class WidgetProvider extends AppWidgetProvider {
private static final int DOUBLE_CLICK_DELAY = 500;
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
Intent intent = new Intent(context, getClass());
intent.setAction("Click");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.image, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, views);
context.getSharedPreferences("widget", 0).edit().putInt("clicks", 0).commit();
}
@Override
public void onReceive(final Context context, Intent intent) {
if (intent.getAction().equals("Click")) {
int clickCount = context.getSharedPreferences("widget", Context.MODE_PRIVATE).getInt("clicks", 0);
context.getSharedPreferences("widget", Context.MODE_PRIVATE).edit().putInt("clicks", ++clickCount).commit();
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
int clickCount = context.getSharedPreferences("widget", Context.MODE_PRIVATE).getInt("clicks", 0);
if (clickCount > 1) Toast.makeText(context, "doubleClick", Toast.LENGTH_SHORT).show();
else Toast.makeText(context, "singleClick", Toast.LENGTH_SHORT).show();
context.getSharedPreferences("widget", Context.MODE_PRIVATE).edit().putInt("clicks", 0).commit();
}
};
if (clickCount == 1) new Thread() {
@Override
public void run(){
try {
synchronized(this) { wait(DOUBLE_CLICK_DELAY); }
handler.sendEmptyMessage(0);
} catch(InterruptedException ex) {}
}
}.start();
}
super.onReceive(context, intent);
}
}
答案 1 :(得分:2)
我是这样做的:
1)如果是第一次点击窗口小部件,则窗口小部件的ImageButton会更改
2)如果是第二次,则打开一个Activity并返回到inicial ImageButton状态。
我使用setOnClickPendingIntent:
处理点击事件private int[] RESOURCES = {R.drawable.button1,R.drawable.button2};
@Override
public void onUpdate(Context context, AppWidgetManager mgr, int[] appWidgetIds) {
ComponentName me = new ComponentName(context, MyWidgetProvider.class);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.my_widget);
Intent widgetIntent = new Intent(context, MyWidgetProvider.class);
Intent myIntent= new Intent(context, MyOtherActivity.class);
widgetIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
widgetIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
PendingIntent pendingIntent;
if(clicks == 0)
{
clicks = 1;
remoteViews.setImageViewResource(R.id.my_image_button, RESOURCES[0]);
pendingIntent = PendingIntent.getBroadcast(context, 0, widgetIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
else if(clicks == 1)
{
clicks = 2;
remoteViews.setImageViewResource(R.id.my_image_button, RESOURCES[1]);
pendingIntent = PendingIntent.getActivity(context, 0, myIntent,0);
}
else //clicks == 2
{
clicks = 0;
remoteViews.setImageViewResource(R.id.my_image_button, RESOURCES[0]);
pendingIntent = PendingIntent.getBroadcast(context, 0, widgetIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
remoteViews.setOnClickPendingIntent(R.id.my_image_button, pendingIntent);
mgr.updateAppWidget(me, remoteViews);
}
@Override
public void onEnabled(Context context) {
clicks = 0;
super.onEnabled(context);
}
答案 2 :(得分:1)
与Button
及其子类不同,AppWidget
没有onClickListener
的概念。 AppWidget
必须为托管它们的应用程序提供PendingIntent
,以便在单击窗口小部件时触发它们。如果您想跟踪多次点击,则需要有一个接收器,用于过滤特定于您的小部件的意图,并跟踪它接收到的次数。
略微不那么相关:您可能会重新考虑您的行为模式。 Android是一键点击操作环境,没有像Windows中那样的“点击一次选择”概念。通过模拟该行为,您的窗口小部件将不会像所有其他UI元素一样,并可能导致混淆。此外,如果屏幕上有两个小部件,并且用户点击一个然后点击另一个,则两者都将显示为“已选中”,这可能不是您想要的。
答案 3 :(得分:0)
为什么不自己计算点击次数?
private class MyAwesomeClickListener implements OnClickListener {
private int clicks = 0;
@Override
public void onClick(View v) {
++clicks;
//do some cool stuff
}
}
答案 4 :(得分:0)
不要在听众中计算它(这很荒谬,你不知道什么时候你的小部件将从内存中回收,你将失去int点击的价值)
保持点击次数(每次点击时加+1,当点击“周期”结束时重新开始为0,不同点击行为结束)。
您可以将它们保存在数据库,序列化或共享首选项中(我猜偏好是最简单的方法)
答案 5 :(得分:0)
这就是我正在做的事情。工作得很漂亮=]
public class MyWidgetProvider extends AppWidgetProvider {
//Length of allowed time in between clicks in milliseconds
private static final long DOUBLE_CLICK_WINDOW = 400;
private static volatile long firstClickTimeReference;
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
long currentSystemTime = System.currentTimeMillis();
if(currentSystemTime - firstClickTimeReference <= DOUBLE_CLICK_WINDOW) {
//double click happened in less than 400 miliseconds
//so let's start our activity
Intent intent = new Intent(context, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity( intent );
} else {
firstClickTimeReference = currentSystemTime;
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.control_widget);
Intent intent = new Intent(context, WidgetProvider.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.actionButton, pendingIntent);
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}
}
}
}
答案 6 :(得分:0)
almisoft的解决方案提供了双击的感觉,而不是简单的连续单击。而且有效。不幸的是,您还会收到一条短消息,告诉您'handler类应该是静态的,否则可能会发生泄漏'。解决方案是使用弱引用和静态处理程序-通用版本为here。转换almisoft的代码可以得到:
public class WidgetProvider extends AppWidgetProvider {
private static final int DOUBLE_CLICK_DELAY = 500;
private static Context mContext;
private static int mClickCount;
private static class MyHandler extends Handler {
//Using a weak reference means you won't prevent garbage collection
private final WeakReference<WidgetProvider> myClassWeakReference;
public MyHandler(WidgetProvider myClassInstance) {
myClassWeakReference = new WeakReference<WidgetProvider>(myClassInstance);
}
@Override
public void handleMessage(Message msg) {
WidgetProvider myWidget = myClassWeakReference.get();
if (myWidget != null) {
//...do work here as in almisoft original...
int clickCount = mContext.getSharedPreferences("widget", Context.MODE_PRIVATE).getInt("clicks", 0);
if (clickCount > 1) {
Toast.makeText(mContext, "doubleClick", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(mContext, "singleClick", Toast.LENGTH_SHORT).show();
}
mContext.getSharedPreferences("widget", Context.MODE_PRIVATE).edit().putInt("clicks", 0).commit();
}
}
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
Intent intent = new Intent(context, getClass());
intent.setAction("Click");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.image, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, views);
context.getSharedPreferences("widget", 0).edit().putInt("clicks", 0).commit();
}
@Override
public void onReceive(final Context context, Intent intent) {
mContext=context;
mIntent=intent;
if (intent.getAction().equals("Click")) {
int clickCount = context.getSharedPreferences("widget", Context.MODE_PRIVATE).getInt("clicks", 0);
context.getSharedPreferences("widget", Context.MODE_PRIVATE).edit().putInt("clicks", ++clickCount).commit();
final Handler handler=new MyHandler(this);
if (clickCount == 1) new Thread() {
@Override
public void run(){
try {
synchronized(this) { wait(DOUBLE_CLICK_DELAY); }
handler.sendEmptyMessage(0);
} catch(InterruptedException ex) {}
}
}.start();
}
super.onReceive(context, intent);
}
}