小部件双击

时间:2011-02-21 19:38:00

标签: android

我有一个小部件(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()之外还有其他一些点击句柄吗?

7 个答案:

答案 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);
    }

}