Android GridView onitemlongclick прослушиватель вызывается после OnItemClick


В основном я хочу показать другое контекстное меню, когда пользователь коротко щелкает или долго щелкает по ячейке в представлении сетки. Проблема заключается в том, что если пользователь коротко щелкает, вызывается прослушиватель OnItemClick, и я вижу, что отладчик достигает кода, который показывает контекстное меню, но вместо того, чтобы перейти оттуда к onCreateContextMenu, он переходит к onItemLongClick.

Я попытался использовать логическое значение, чтобы предотвратить выполнение кода с длинным щелчком, который действительно предотвращает выполнение этого кода, однако даже когда это делается onCreateContextMenu не вызывается вообще.

Если я удаляю прослушиватель onItemLongClick, прослушиватель короткого щелчка работает правильно, и контекстное меню отображается правильно.

Я знаю, что другие люди задавали вопросы, подобные этому, но я до сих пор не смог найти решение, которое работает. Если кто-то может решить эту проблему или указать мне правильное направление, пожалуйста, дайте мне знать, спасибо заранее. Щедрость будет присуждена любому, кто сможет даже указать мне на правильное направление.

Это упрощенная версия кода для слушателей:

        mTGrid.setOnItemClickListener(new OnItemClickListener() {
            //this listener should show the context menu for a short click on the gridview.
            @Override
            public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
                    mRequiredMenu = "standard";
                    parent.showContextMenuForChild(v);      

            }
        });

        mTGrid.setOnItemLongClickListener(new OnItemLongClickListener() {
            //this listener should show the context menu for a long click on the gridview.
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) {
                    mRequiredMenu = "options";
                        parent.showContextMenuForChild(v);      

            }
        });
5 4

5 ответов:

Я понимаю, что вы хотите показать другое контекстное меню для коротких кликов и длинных кликов по элементу GridView.

Во-первых, вам просто нужно установить прослушиватель для короткого щелчка, так как поведение по умолчанию автоматически покажет контекстное меню при длинных щелчках.

Затем установите логический флаг true в OnItemClickListener. Значение по умолчанию-false для длинных кликов.

Наконец, в onCreateContextMenu () проверьте, если его короткий щелчок и показать другое контекстное меню (стандартный) и установить флаг в ложь. В противном случае пусть он покажет контекстное меню по умолчанию (параметры).

Вот некоторый код, чтобы продемонстрировать эту идею.

public class MainActivity extends Activity {

    private static final String[] arr = {"A", "B", "C", "D", "E", "F", "G", "H","I"};

    private GridView mTGrid;
    private boolean isShort;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mTGrid = (GridView) findViewById(R.id.gridView1);
        registerForContextMenu(mTGrid);

        mTGrid.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                isShort = true;
                openContextMenu(view);
            }
        });

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.cell, arr);
        mTGrid.setAdapter(adapter);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;

        if(isShort) {
            getMenuInflater().inflate(R.menu.context_standard, menu);
            menu.setHeaderTitle("Standard Menu for "+arr[info.position]);
            isShort = false;
        }
        else {
            getMenuInflater().inflate(R.menu.context_options, menu);
            menu.setHeaderTitle("Options Menu for "+arr[info.position]);
        }
    }   
}

Пример Приложения : Вы можете скачать пример приложения, чтобы увидеть его поведение. GridExample_eclipse_project

Для отчаянной ситуации отчаянные решения.

1.Попробуйте работать с логическими символами, а не выполнять код внутри слушателей.

 mTGrid.setOnItemClickListener(new OnItemClickListener() {
        //this listener should show the context menu for a short click on the gridview.
        @Override
        public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
                b=true     
        }
    });

    mTGrid.setOnItemLongClickListener(new OnItemLongClickListener() {
        //this listener should show the context menu for a long click on the gridview.
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) {
                b=false      
        }
    });
if(b)
{
     mRequiredMenu = "standard";
     parent.showContextMenuForChild(v);  
}
else
{
    mRequiredMenu = "options";
    parent.showContextMenuForChild(v);
}

2 Проверьте, являются ли оба свойства clickable и longclickable "истинными"в вашем макете.

Вы можете переопределить прослушиватель событий диспетчеризации, который отвечает за обработку длинных щелчков

mTGrid.setOnItemClickListener(new OnItemClickListener() {
            //this listener should show the context menu for a short click on the gridview.
            @Override
            public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
                     clickFlag=true;   
                     mRequiredMenu = "standard";                     

            }
        });

        mTGrid.setOnItemLongClickListener(new OnItemLongClickListener() {
            //this listener should show the context menu for a long click on the gridview.
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) {
                     clickFlag=false;
                     mRequiredMenu = "options";                  
            }
        });

if(clickFlag){        
    if(mRequiredMenu.equals("standard");{
        //just click event
        parent.showContextMenuForChild(v);
    }else{}
}else{
   if(mRequiredMenu.equals("options");{
        //just Long click event
        parent.showContextMenuForChild(v);
    }else{} 

}

OnItemLongClickListener срабатывает, потому что отображение контекстного меню для ListView попытается сделать это через этот прослушиватель. Вот код от AbsListView:

@Override
public boolean showContextMenuForChild(View originalView) {
    final int longPressPosition = getPositionForView(originalView);
    if (longPressPosition >= 0) {
        final long longPressId = mAdapter.getItemId(longPressPosition);
        boolean handled = false;

        if (mOnItemLongClickListener != null) {
            handled = mOnItemLongClickListener.onItemLongClick(AbsListView.this, originalView,
                    longPressPosition, longPressId);
        }
        if (!handled) {
            mContextMenuInfo = createContextMenuInfo(
                    getChildAt(longPressPosition - mFirstPosition),
                    longPressPosition, longPressId);
            handled = super.showContextMenuForChild(originalView);
        }

        return handled;
    }
    return false;
}
Из этого мы можем видеть, что если mOnItemLongClickListener.onItemLongClick возвращает true, то это означает, что вызов был обработан и метод завершается. Если он возвращает false, то он пытается создать контекстное меню.

Поэтому вам нужно изменить оператор return в onItemLongClick (который ваш код не показывает), чтобы вернуть true , если это было действительно долго щелкал, и false если он был просто нажат:

mTGrid.setOnItemClickListener(new OnItemClickListener() {

    @Override
    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {

        mRequiredMenu = "standard";
        mItemClicked = true;
        parent.showContextMenuForChild(v);
    }
});

mTGrid.setOnItemLongClickListener(new OnItemLongClickListener() {

    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) {

        if(mItemClicked) {
            mItemClicked = false;
            return false;
        }

        mRequiredMenu = "options";
        parent.showContextMenuForChild(v);
        return true;
    }
});