EditText 的 onCreateContextMenu() 在真实设备上不起作用

onCreateContextMenu() for EditText doesn#39;t work on real device(EditText 的 onCreateContextMenu() 在真实设备上不起作用)

本文介绍了EditText 的 onCreateContextMenu() 在真实设备上不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

刚刚尝试在真实设备上测试我的应用程序(HTC Desire Z 与 Android 2.2).并发现我的上下文菜单在 EditText 上根本不起作用.否则上下文菜单有效:在 ListViewImageView 等.在模拟器上一切正常...

当我点击 EditText 时,它会显示类似缩放框的内容,然后显示不寻常的(不是标准的 Android 类似的)上下文菜单,内容为:选择文本"、全选".它不显示我的菜单.以下是截图:

  1. 点击前
  2. 点击期间
  3. 点击后(就是普通的选择文字,全选,粘贴)

但没有我在模拟器中的菜单 - 看这里p>

这是我的活动的源代码:

公共类 MyActivity 扩展 Activity{私有静态最终字符串 TAG=MyActivity.class.getName();编辑文本编辑文本;/*** 在第一次创建活动时调用.*/@覆盖public void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);设置内容视图(R.layout.main);editText=(EditText)findViewById(R.id.editText);this.registerForContextMenu(editText);}@覆盖public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo){Log.v(TAG, "为视图创建上下文菜单="+view);menu.add(Menu.NONE, Menu.FIRST+1, Menu.NONE, "测试菜单");super.onCreateContextMenu(menu, view, menuInfo);}@覆盖公共布尔 onContextItemSelected(菜单项项){Log.v(TAG, "上下文项选择为="+item.toString());返回 super.onContextItemSelected(item);}}

我已经彻底调试/记录了我的代码周围的所有内容,但仍然没有调用 Activity.onCreateContextMenu()(尽管它以正确的方式注册).

请帮忙 - 它可能是什么?它与 HTC 的特性有关吗?

解决方案

是的,我想你看到的是 HTC 菜单.

我相信,您看到的图形编辑上下文菜单是较新的 Desire 模型(Desire HD 和 Desire Z)的新功能.我在原始 Desire 上看到(使用您的代码)是一个基于文本的弹出菜单,其中 HeaderTitle 设置为编辑文本"和一个列表,例如全选"、复制"、粘贴"等.但是,我还会看到一个条目说测试菜单".

我突然想到,当为 ListView 和 ImageView 等调用 onCreateContextMenu() 时,默认情况下不会预先填充传入该调用的菜单"对象.然而,在 EditText 的情况下,它被设计为与剪贴板交互,因此系统提供基于 EditText 的内容状态的预填充菜单(例如,如果选择文本,则提供复制"选项;如果剪贴板上有文本,请提供粘贴"选项;...等等).

通过修改代码清除标题和内容,我能够获得没有编辑"选项的上下文菜单...

@Overridepublic void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo){Log.v(TAG, "为视图创建上下文菜单="+view);//清除当前内容menu.clearHeader();menu.clear();menu.setHeaderTitle("测试菜单");menu.add(Menu.NONE, Menu.FIRST+1, Menu.NONE, "测试菜单");super.onCreateContextMenu(menu, view, menuInfo);}

您得到一个图形菜单(可能从 ContextMenu 派生)的事实表明上述技术将不起作用,因此唯一的解决方法是实例化您自己的 ContextMenu 对象,而不是使用传递给 onCreateContextMenu().

<块引用>

我已经彻底调试/记录了我的代码周围的所有内容,但仍然没有调用 Activity.onCreateContextMenu()

这似乎很奇怪 - 显然它是为我调用的,因为我已经能够使用传递给它的 ContextMenu.

编辑 1: 重新考虑这一点,您提到您点击"了 EditText - 这就是您实际在做的事情(短暂触摸然后手指向上)?

要获得我的 ContextMenu,我必须使用长按"/单击(触摸并按住大约 1 秒钟).当我简单地点击/触摸我的 EditText 时,会出现软"键盘,或者,如果键盘已经可见,则光标会简单地移动到 EditText 框中的不同位置.

显然 Desire Z 有一个物理键盘,这可能会导致行为略有不同(以及 Desire Z 的 Sense UI 版本与我的 Desire 不同).

永远不会为您调用 onCreateContextMenu() 这一事实仅意味着一件事,即您所看到的不是 ContextMenu,而是某种其他类型的弹出 UI 元素.至少这是我能理解的唯一合乎逻辑的方式.

您能否确认长按"仍然没有为您创建 ContextMenu,或者您一直在使用长按?

如果您尝试过长按,请尝试修改代码如下...

  1. 实现 OnClickListener

    公共类 MyActivity 扩展 Activity实现 OnLongClickListener {

  2. 在 onCreate 中为 editText 设置监听器...

    @Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);设置内容视图(R.layout.main);editText=(EditText)findViewById(R.id.editText);this.registerForContextMenu(editText);editText.setOnLongClickListener(this);//<-- 添加这个}

  3. 添加监听代码...

    @Override公共布尔 onLongClick(查看 arg0){android.util.Log.v(TAG, "onLongClick() 调用");如果(arg0 == 编辑文本){android.util.Log.v(TAG, "arg0 == editText");Toast.makeText(this, "onLongClick 被拦截", 2000).show();返回真;}别的{android.util.Log.v(TAG, "arg0 != editText");返回假;}}

通过这样做,我能够拦截长按,并且通过从 onLongClick() 返回true",我向系统表明我已经消费"了该事件并且它没有通过开始创建我的 ContextMenu.

如果这对您不起作用并且短按仍然会导致出现该弹出窗口,请尝试实现 OnClickListener 并改写 onClick().

练习的目的是,如果您可以拦截导致创建您所看到的弹出窗口的任何内容,那么您可以手动创建并显示您自己的 ContextMenu.

Just tried to test my app on real device (HTC Desire Z with Android 2.2). And found that my context menus doesn't work at all on EditTexts. Otherwise context menus works: in ListView, ImageView and so on. On emulator everything works fine...

When I tap on EditText it shows something like zoom frame and then shows unusual (not standard Android alike) context menu which reads: "select text", "select all". It doesn't show my menus. Here are screenshots:

  1. Before tap
  2. During tap
  3. After tap (just ordinary select text, select all, paste)

but no my menu like in emulator - look here

Here's source code of my activity:

public class MyActivity extends Activity
{
    private static final String TAG=MyActivity.class.getName();

    EditText editText;
    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        editText=(EditText )findViewById(R.id.editText);
        this.registerForContextMenu(editText);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo)
    {
        Log.v(TAG, "Creating context menu for view="+view);
        menu.add(Menu.NONE, Menu.FIRST+1, Menu.NONE, "Test menu");
        super.onCreateContextMenu(menu, view, menuInfo);
    }

    @Override
    public boolean onContextItemSelected(MenuItem item)
    {
        Log.v(TAG, "Context item selected as="+item.toString());
        return super.onContextItemSelected(item);
    }
}

I have thoroughly debugged/logged everything around my code, but still Activity.onCreateContextMenu() not even called (though it's registered in proper way).

Please help - what it can be? Does it related to HTC peculiarities?

解决方案

Yes, I think what you are seeing there is an HTC menu.

The graphical edit context menu you are seeing is, I believe, new to more recent Desire models (Desire HD and Desire Z). What I see (with your code) on my original Desire is a popup text-based menu with the HeaderTitle set as 'Edit text' and a list such as 'Select all', 'Copy', 'Paste' etc. BUT, I do also see an entry saying 'Test menu'.

It occurs to me that when onCreateContextMenu() is called for things like ListView and ImageView, the 'menu' object passed in to that call isn't pre-populated by default. In the case off an EditText, however, it is designed to interact with the Clipboard and as such the system is providing a pre-populated menu based on the EditText's content state (e.g., if text is selected, provide a 'Copy' option; if there's text on the Clipboard provide a 'Paste' option; ...and so on).

I was able to get a Context menu without the 'edit' options by clearing the header and contents by modifying your code...

@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo)
{
    Log.v(TAG, "Creating context menu for view="+view);

    // Clear current contents
    menu.clearHeader();
    menu.clear();

    menu.setHeaderTitle("TEST MENU");
    menu.add(Menu.NONE, Menu.FIRST+1, Menu.NONE, "Test menu");
    super.onCreateContextMenu(menu, view, menuInfo);
}

The fact you're getting a graphical menu (possibly derived from ContextMenu) suggests the above technique won't work so the only way around it would be to instantiate your own ContextMenu object rather than use the one passed in to onCreateContextMenu().

I have thoroughly debugged/logged everything around my code, but still Activity.onCreateContextMenu() not even called

This seems very odd - obviously it's being called for me as I've been able to play around with the ContextMenu that is being passed to it.

EDIT 1: Re-thinking this, you mention that you 'tap' the EditText - is that what you are actually doing (a short touch down then finger up)?

To get my ContextMenu I have to use a 'long' press/click (touch and hold for about 1 second). When I simply tap/touch my EditText the 'soft' keyboard appears or, if the keyboard is already visible, the cursor is simply moved to a different position in the EditText box.

Obviously the Desire Z has a physical keyboard and that may cause slightly different behaviour (as well as the Desire Z having a different version of the Sense UI to my Desire).

The fact that onCreateContextMenu() is never called for you can mean only one thing and that is, what you are seeing is NOT a ContextMenu and is some other type of popup UI element. At least that is the only logical way I can understand it.

Can you confirm that a 'long' press still doesn't create a ContextMenu for you or have you been using a long press all along?

If you have tried a long press then try modifying the code as follows...

  1. Implement OnClickListener

    public class MyActivity extends Activity
        implements OnLongClickListener {
    

  2. Set the listener for editText in onCreate...

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        editText=(EditText )findViewById(R.id.editText);
        this.registerForContextMenu(editText);
        editText.setOnLongClickListener(this); // <-- ADD THIS
    }
    

  3. Add the listener code...

    @Override
    public boolean onLongClick(View arg0) {
        android.util.Log.v(TAG, "onLongClick() called");
        if (arg0 == editText)
        {
            android.util.Log.v(TAG, "arg0 == editText");
                Toast.makeText(this, "onLongClick intercepted", 2000).show();
            return true;
        }
        else
        {
            android.util.Log.v(TAG, "arg0 != editText");
            return false;
        }
    }
    

By doing this, I'm able to intercept the long press and, by returning 'true' from onLongClick() I'm indicating to the system that I've 'consumed' the event and it doesn't get passed on to cause the creation of my ContextMenu.

If this doesn't work for you and a short tap still causes that popup to appear, then try implementing OnClickListener and overriding onClick() instead.

The object of the exercise is that if you can intercept whatever is causing the creation of the popup you're seeing, you can then manually create and show your own ContextMenu.

这篇关于EditText 的 onCreateContextMenu() 在真实设备上不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:EditText 的 onCreateContextMenu() 在真实设备上不起作用

基础教程推荐