Определение представления, выбранного в ContextMenu (Android) - PullRequest
11 голосов
/ 28 мая 2010

В Android onContextItemSelected имеет один аргумент MenuItem, поэтому неясно, как определить выбранный вид. MenuItem.getMenuInfo обеспечивает доступ к Contextmenu.ContextMenuInfo , но хотя оба известных подкласса предоставляют доступ к целевому представлению, на интерфейсе, по-видимому, нет средства доступа.

Одной из альтернатив является сохранение View, предоставленного в onCreateContextMenu, в частной переменной класса, которая полагается на onCreateContextMenu, которая больше не вызывается в действии до onContextItemSelected.Другой способ - использовать идентификатор View для аргумента itemId ContextMenu.add .Если мы сделаем это, нам нужно будет определить опцию, выбранную из контекстного меню, используя ее (возможно, интернационализированный) заголовок.

Каков наилучший метод для идентификации View, выбранного в onContextSelected?

Ответы [ 7 ]

8 голосов
/ 28 мая 2010

Не существует такого понятия, как «определение выбранного вида» для меню параметров или контекстных меню в Android. Следовательно, довольно сложно ответить на ваш вопрос. Итак, я возьму некоторые догадки.

Если под «идентификацией выбранного вида» вы подразумеваете, какой пункт меню был выбран, то есть getItemId() на MenuItem, который передается на onOptionsItemSelected() или onContextItemSelected().

Если под "идентификацией выбранного вида" вы подразумеваете, какая строка в ListView была той, на которую долго нажимали для вызова контекстного меню, приведите getMenuInfo() (вызывается на MenuItem) к AdapterView.AdapterContextMenuInfo затем используйте значения id или position в зависимости от вашего адаптера. Смотрите здесь пример проекта , который использует эту технику.

Если под "идентификацией выбранного вида" вы имеете в виду, что у вас есть более одного не ListView контекстного меню в деятельности, я бы не использовал эту технику пользовательского интерфейса.

7 голосов
/ 03 марта 2011

Весь смысл контекстного меню заключается в том, что оно связано с отдельным базовым представлением, и в Android явно заложено ограничение дизайна, так как ассоциация теряется при обратном вызове onContextItemSelected. Включение долгого касания в любом представлении достаточного размера кажется вполне разумным в качестве альтернативы щелчку правой кнопкой мыши.

Как рекомендовали другие посты, для некоторых контекстов:

AdapterView.AdapterContextMenuInfo menuInfo = 
(AdapterView.AdapterContextMenuInfo)item.getMenuInfo();

подходят и targetView является полезной точкой отсчета.

Другим способом является создание подкласса представления и переопределение getContextMenuInfo для предоставления ссылки на представление. Например, простой TextView:

package ...;

public class TextViewWithContext extends TextView {
    TextViewContextMenuInfo _contextMenuInfo = null;

    public TextViewWithContext(Context context) {
        super(context);
        _contextMenuInfo = new TextViewContextMenuInfo(this);
    }

    public TextViewWithContext(Context context, AttributeSet attrs) {
        super(context, attrs);
        _contextMenuInfo = new TextViewContextMenuInfo(this);
    }   

    protected ContextMenuInfo getContextMenuInfo() {
        return _contextMenuInfo;
    }

    public boolean isContextView(ContextMenuInfo menuInfo) {
        return menuInfo == (ContextMenuInfo)_contextMenuInfo;
    }

    protected class TextViewContextMenuInfo implements ContextMenuInfo {
        protected TextView  _textView = null;

        protected TextViewContextMenuInfo(TextView textView) {
            _textView = textView;
        }
    }
}

...
    @Override
    public boolean onContextItemSelected(MenuItem item) {   

        ContextMenuInfo menuInfo = item.getMenuInfo();

        if (textViewWithContext.isContextView(menuInfo) {
            ...
        }
    }

Наконец, было бы более полезно, если бы базовый класс View назначил объект ContextInfo с обратной ссылкой на представление, а не ноль, как в настоящее время.

3 голосов
/ 15 июня 2011

Класс TestActivity расширяет Activity {

// create temp item here

private ImageView tmpImageView = null;

...

public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo){
    super.onCreateContextMenu(menu, v, menuInfo);
    // initialize temp item
    mCurrentStatusImage = (ImageView) v.findViewById(R.id.rule_status);
}

public boolean onContextItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case ENABLE_ID:
            // use temp item
            tmpImageView.setImageResource(android.R.drawable.presence_online);
            return super.onContextItemSelected(item);
        case DISABLE_ID:
            // use temp item
            tmpImageView.setImageResource(android.R.drawable.presence_invisible);
            return super.onContextItemSelected(item);
        default:    
            return super.onContextItemSelected(item);
 }
2 голосов
/ 28 октября 2013

В случае, если вы присоединяете ContextMenus к нескольким представлениям, которых нет в ListView (т. Е. Нет адаптера, лежащего в основе представлений), и вы хотите определить, какое представление было долго нажато для доступа к ContextMenu, следующий «хак» может быть реализованным. (Было бы лучше, если бы Android предоставил слушателя, который может быть связан с каждым элементом).

«Хак» заключается в том, что в классе создается личный член View mLastViewTouched, а затем присоединяется следующий onTouchListener ко всем представлениям, которые могут генерировать ContextMenu:

 private View.OnTouchListener onTouchListener = new View.OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent)
    {
        mLastViewTouched = view;        // Store a handle on the last view touched. This will be used to identify the view on which the Context Menu was launched

        return false;       // We return false since this indicates that the touch was not handled and so it is passed down the stack to be handled appropriately
    }
};

Таким образом, при каждом касании просмотра mLastViewTouched обновляется. Теперь в onContextItemSelected у вас будет доступ к представлению, которое инициировало ContextMenu.

1 голос
/ 31 января 2017

При создании меню в реализации OnCreateContextMenuListener или public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) вы можете установить пользовательский MenuItem.OnMenuItemClickListener для каждого элемента:

    addPhotosBtn.setOnCreateContextMenuListener((menu, v, menuInfo) -> {
        getMenuInflater().inflate(R.menu.upload_image_menu, menu);
        int itemCount = menu.size();
        for(int i = 0; i < itemCount; i++) {
            menu.getItem(i).setOnMenuItemClickListener(addPhotosBtnMenuItemClickListener);
        }
    });

Поскольку в настоящее время у вас есть доступ к представлению, для которого вы создаете контекстное меню, вы можете тесно связать слушателя с этим представлением.

1 голос
/ 07 мая 2013

Я исправил аналогичную проблему, установив groupID для MenuItem на основе того, какой элемент отправил его, например:

    textview.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
        @Override
        public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) {
                menu.setHeaderTitle("Context Menu");
                menu.add(R.id.whateverviewclicked, RENAME_MENU_ITEM, 0, "Rename");
                menu.add(R.id.whateverviewclicked, DELETE_MENU_ITEM, 1, "Delete");
             }
         });

Это позволит вам получить groupID в onContextItemSelected:

public boolean onContextItemSelected(MenuItem aItem) {
        int selectedViewID = aItem.getGroupId();
        int selectedItem = aItem.getItemId();
};

вам не нужно использовать идентификатор ресурса - вы можете использовать любой int, который хотите. У меня работает!

0 голосов
/ 07 апреля 2018

Вот что я сделал, чтобы различить 2 списка: lstA и lstB MenuItem

    @Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    int startid = (v.getId() == R.id.lstA) ? 0 : 2; //0-1 will be lstA and 2-3 will be lstB
    menu.setHeaderTitle("some title");
    menu.add(Menu.NONE, startid, Menu.NONE, "Item 1");
    menu.add(Menu.NONE, startid+1, Menu.NONE, "Item 2");
}

@Override
public boolean onContextItemSelected(MenuItem item) {
    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
    int menuItemIndex = info.position;
    switch(item.getItemId()) {
        case 0:
            break;
        case 1:
            break;
        case 2:
            break;
        case 3:
            break;
    }
    return true;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...