Контекстное меню не работает с двумя фрагментами

У меня есть два фрагмента A и B, оба имеют вид списка и простираются от базового фрагмента C. На самом деле A и B расширяют элемент управления списком от C.

Я зарегистрировал контекстное меню на C, чтобы реализовать функцию длительного нажатия.

Теперь, когда я долго нажимаю на фрагмент A или B, контекстное меню может отображаться так, как ожидается. Также, когда я был во фрагменте A, контекстное меню также может работать как исключение.

Но мы перейдем к фрагменту B, долго нажимаем на список, onContextItemSelected метод никогда не вызывался.

Я сделал это, как показано ниже. Сначала зарегистрируйте контекстное меню в onActivityCreated во фрагменте C.

registerForContextMenu(transferTasksList);

Во-вторых, установите макет и нарисуйте меню во фрагменте С.

@Override
public void onCreateContextMenu(ContextMenu menu, View v,
                                ContextMenu.ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    android.view.MenuInflater inflater = mActivity.getMenuInflater();
    inflater.inflate(R.menu.upload_task_menu, menu);

    ListView listView = (ListView)v;
    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
    TransferTaskInfo taskInfo = (TransferTaskInfo)listView.getItemAtPosition(info.position);

    android.view.MenuItem itemCancel = menu.findItem(R.id.cancel);
    android.view.MenuItem itemRetry = menu.findItem(R.id.retry);
    android.view.MenuItem itemRemove = menu.findItem(R.id.remove);
    android.view.MenuItem itemRemoveAllCancelled = menu.findItem(R.id.remove_all_cancelled);
    android.view.MenuItem itemRemoveAllFinished = menu.findItem(R.id.remove_all_finished);

    itemCancel.setVisible(false);
    itemRetry.setVisible(false);
    itemRemove.setVisible(false);
    itemRemoveAllCancelled.setVisible(false);
    itemRemoveAllFinished.setVisible(false);

    switch (taskInfo.state) {
        case INIT:
            itemCancel.setVisible(true);
            break;
        case TRANSFERRING:
            itemCancel.setVisible(true);
            break;
        case CANCELLED:
            itemRetry.setVisible(true);
            itemRemove.setVisible(true);
            itemRemoveAllCancelled.setVisible(true);
            break;
        case FAILED:
            itemRetry.setVisible(true);
            itemRemove.setVisible(true);
            break;
        case FINISHED:
            itemRemove.setVisible(true);
            itemRemoveAllFinished.setVisible(true);
            break;
    }
}

В-третьих, поймать событие click абстрактным методом doContextItemSelected во фрагменте C.

@Override
    public boolean onContextItemSelected(android.view.MenuItem item) {
        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();

        TransferService txService = mActivity.getTransferService();

        if (txService == null) {
            return false;
        }

        ListView listView = transferTasksList;
        TransferTaskInfo taskInfo = (TransferTaskInfo)listView.getItemAtPosition(info.position);
        TransferManager.TaskState state = taskInfo.state;
        int taskID = taskInfo.taskID;

        boolean needRefresh = doContextItemSelected(item, taskID, state);

        if (needRefresh) {
            refreshView();
        }
        return true;
    }

и я реализовал абстрактный метод A и B, как это.

@Override
boolean doContextItemSelected(MenuItem item, int taskID, TransferManager.TaskState state) {
    switch (item.getItemId()) {
        case R.id.cancel:
            if (state == TransferManager.TaskState.INIT || state == TransferManager.TaskState.TRANSFERRING) {
                mActivity.getTransferService().cancelUploadTask(taskID);
                return true;
            }
            break;
        case R.id.retry:
            if (state == TransferManager.TaskState.FAILED || state == TransferManager.TaskState.CANCELLED) {
                mActivity.getTransferService().retryUploadTask(taskID);
                return true;
            }
            break;
        case R.id.remove:
            if (state == TransferManager.TaskState.FINISHED ||
                    state == TransferManager.TaskState.FAILED ||
                    state == TransferManager.TaskState.CANCELLED) {
                mActivity.getTransferService().removeUploadTask(taskID);
                return true;
            }
            break;
        case R.id.remove_all_cancelled:
            if (state == TransferManager.TaskState.CANCELLED) {
                mActivity.getTransferService().removeAllUploadTasksByState(TransferManager.TaskState.CANCELLED);
                return true;
            }
            break;
        case R.id.remove_all_finished:
            if (state == TransferManager.TaskState.FINISHED) {
                mActivity.getTransferService().removeAllUploadTasksByState(TransferManager.TaskState.FINISHED);
                return true;
            }
            break;
        default:
            return false;
    }
    return false;
}

Он хорошо работает во фрагменте A, когда я долго нажимаю на фрагмент B, он может всплыть в меню, что нормально, но когда я выбираю пункт меню, он падает.

аварийный журнал есть.

java.lang.IndexOutOfBoundsException: Invalid index 1, size is 0
        at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
        at java.util.ArrayList.get(ArrayList.java:308)
        at com.seafile.seadroid2.ui.adapter.TransferTasksAdapter.getItem(TransferTasksAdapter.java:131)
        at com.seafile.seadroid2.ui.adapter.TransferTasksAdapter.getItem(TransferTasksAdapter.java:32)
        at android.widget.AdapterView.getItemAtPosition(AdapterView.java:764)
        at com.seafile.seadroid2.ui.fragment.TransferTaskFragment.onContextItemSelected(TransferTaskFragment.java:186)
        at android.support.v4.app.Fragment.performContextItemSelected(Fragment.java:1593)
        at android.support.v4.app.FragmentManagerImpl.dispatchContextItemSelected(FragmentManager.java:2006)
        at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:370)
        at com.actionbarsherlock.app.SherlockFragmentActivity.onMenuItemSelected(SherlockFragmentActivity.java:210)

ОБНОВИТЬ

Текущее значение видимой пользователем подсказки для этого фрагмента.

Чтобы решить проблему, добавьте условие в один из ваших фрагментов, как показано ниже.

@Override
    public boolean onContextItemSelected(android.view.MenuItem item) {
        if (getUserVisibleHint()) {
            //TODO something when item was selected

            return true;
        } else
            return false;
    }

2 ответа

Я только что столкнулся с той же проблемой. Но я не написал код точно так же, как вы. У меня есть два фрагмента в одном действии (эти два фрагмента не выходят из одного и того же предка), скажем, фрагмент A и фрагмент B. (в main_activity.xml фрагмент A находится над фрагментом B, поэтому в logcat фрагмент A всегда создается раньше фрагмент B, я получил эту информацию от вставки Log.d(...) во все вызываемые функции во фрагменте A и фрагменте B)
Есть фрагмент ListView во фрагменте A, есть GridView во фрагменте B. Я вызвал registerForContextMenu(...) в обратном вызове фрагмента onCreateView(..), я также переопределил onCreateContextMenu(..) и onContextItemSelected во фрагменте A. Я сделал то же самое во фрагменте B. Теперь возникает проблема:
1. Когда я долго щелкаю элемент (в виде сетки) во фрагменте B, вызывается onCreateContextMenu фрагмента B (я получил это из информации журнала), затем я выбираю элемент во всплывающем контекстном меню, что довольно странно, onContextItemSelected фрагмента A называется. (Поскольку пункт контекстного меню во фрагменте B не совпадает с элементом контекстного меню во фрагменте A, иногда происходит сбой всего приложения, иногда ничего не происходит)
2. Когда я долго щелкаю элемент (в виде списка) во фрагменте A, вызывается onCreateContextMenu фрагмента A, затем я выбираю элемент контекста, вызывается onContextItemSelected фрагмента A.
Итак, в общем, фрагмент А работает, фрагмент Б не работает. Я нашел, чтобы решить эту проблему, мы должны сделать больше вещей в onContextItemSelected во фрагменте A

    public boolean onContextItemSelected (MenuItem menuItem) {
        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo ();
        пытаться {
            int position = info.position;
            final EditText et = (EditText) mListView.getChildAt(position).findViewById(R.id.edittext);
            final String name = et.getText().toString();
            Log.d(TAG, "хаха: " + имя);
            Переключатель (menuItem.getItemId()){
                дело R.id.delete:
                    SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(mActivity);
                    SharedPreferences.Editor editor = pref.edit();
                    editor.remove(имя);
                    editor.commit();
                    notifyDataSetChange();
                    перерыв;
            }
        }
        поймать (исключение е) {
            вернуть ложь;
        }
        вернуть истину;
    }

Идея заключается в возврате false из onContextItemSelected из фрагмента A, когда вы обнаружите, что выбранный элемент контекста не нацелен на фрагмент A, тогда будет вызван onContextItemSelected во фрагменте B.

Пожалуйста, сортируйте предмет, используя хитрость

@Override
    public boolean onContextItemSelected(MenuItem item) {


 if(item.getTitle() == "Tittle you given to menu") {

// do somthing

}


}
Другие вопросы по тегам