barmaley barmaley - 2 months ago 18
Android Question

onCreateContextMenu() for EditText doesn't work on real device

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

EditText
s. 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?

Answer

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.