如何为AppWidgetHostView创建长按单击侦听器

时间:2017-08-09 23:58:45

标签: java android widget onlongclicklistener

我正在制作一个启动器,我不得不为这些小部件制作一个长时间点击监听器。我创建了一个扩展AppWidgetHost的类和另一个扩展AppWidgetHostView的类。他们拦截触摸事件,如果它动作起来,它会看起来并看到动作下降持续400L。除非小部件上没有按钮,否则它可以正常工作。例如,无法长按时钟小部件。

以下是主机视图上longClickListener的实现:

hostView.setOnLongClickListener(new View.OnLongClickListener() {
    @Override
    public boolean onLongClick(View view) {
        new AlertDialog.Builder(WidgetEdge.this)
            .setTitle("Options")
            .setMessage("Do you want to delete or resize widget?")
            .setIcon(android.R.drawable.sym_def_app_icon)
            .setNegativeButton("Delete", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int whichButton) {
                    removeWidget(hostView);
                    Toast.makeText(WidgetEdge.this, "Widget Deleted", Toast.LENGTH_SHORT).show();
                }
            })
            .setPositiveButton("Resize", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    resizeView(hostView);
                }
            }).show();
        return false;
    }
});

以下是AppWidgetHostView类:

public class LauncherAppWidgetHostView extends AppWidgetHostView{
    private LayoutInflater mInflater;
    WidgetEdge context;
    private OnLongClickListener longClick;
    private long down;

    public LauncherAppWidgetHostView(Context context) {
        super(context);
        this.context = (WidgetEdge) context;
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public void setOnLongClickListener(OnLongClickListener l) {
        this.longClick = l;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean trueOrFalse = false;
        switch(ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                down = System.currentTimeMillis();
                this.getParent().requestDisallowInterceptTouchEvent(true);
                trueOrFalse = false;
                break;
            case MotionEvent.ACTION_UP:
                boolean upVal = System.currentTimeMillis() - down > 400L;
                if( upVal ) {
                    longClick.onLongClick(LauncherAppWidgetHostView.this);
                    trueOrFalse = true;
                }
                break;
        }
        return trueOrFalse;
    }

    @Override
    protected View getErrorView() {
        return mInflater.inflate(R.layout.appwidget_error, this, false);
    }
} 

以下是AppWidgetHost

import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;

class LauncherAppWidgetHost extends AppWidgetHost {
    LauncherAppWidgetHost(Context context, int hostId) {
        super(context, hostId);
    }

    @Override
    protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
                                             AppWidgetProviderInfo appWidget) {
        return new LauncherAppWidgetHostView(context);
    }

    @Override
    public void stopListening() {
        super.stopListening();
        clearViews();
    }
}

我尝试使用this link中的代码,但是当我在时钟小部件上进行测试时,它会启动onLongClickListener两次。此外,当滚动窗口小部件时,如果没有长按,它也会启动onLongClick。谢谢你的帮助。

- UPDATE-- 我正在使用调试器并发现当使用时钟小部件时,拦截的唯一事件是第一个ACTION_DOWN。之后它从未接受过ACTION_UP。

1 个答案:

答案 0 :(得分:0)

如果小部件的行为不像按钮(因此,当无法单击它时),则需要执行更高级的操作来检测长按。

您可以看看https://github.com/willli666/Android-Trebuchet-Launcher-Standalone/blob/master/src/com/cyanogenmod/trebuchet/LauncherAppWidgetHostView.java 如果Apache许可适用于您的项目,则可以复制粘贴整个文件,只需删除getErrorView()和充气机即可。

这个想法是在检测到初始ACTION_DOWN事件时开始超时,并且当超时触发时,如果视图仍然具有焦点,则可以performLongClick()

要实现这一目标要比想象中的难得多,但是至少这对所有小部件都有效,即使那些无法单击的小部件也是如此。