Обнаружение выбранного элемента (в ListView) порождало ContextMenu (Android)
У меня есть ListView, который позволит пользователю долгое нажатие на элемент, чтобы получить контекстное меню. Проблема, с которой я сталкиваюсь, заключается в определении того, какие ListItem
они долгое нажатие. Я пробовал сделать это:
myListView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
@Override public void onCreateContextMenu(ContextMenu menu, final View v, ContextMenuInfo menuInfo) {
menu.add("Make Toast")
.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override public boolean onMenuItemClick(MenuItem item) {
String toastText = "You clicked position " + ((ListView)v).getSelectedItemPosition();
Toast.makeText(DisplayScheduleActivity.this, toastText, Toast.LENGTH_SHORT).show();
return true;
}
});
}
});
но он просто зависает до появления ANR. Я подозреваю, что после создания меню ListItem
больше не будет выбран.
Похоже, вы можете отслеживать клики или длинные клики, а затем записывать нажатый элемент:
mArrivalsList.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) {
// record position/id/whatever here
return false;
}
});
но для меня это очень важно. У кого-нибудь есть лучшие решения для этого?
Ответы
Ответ 1
Я делаю именно это. В моем методе onCreateContextMenu(...)
я отбрасывал ContextMenu.ContextMenuInfo
в AdapterView.AdapterContextMenuInfo
. Оттуда вы можете получить targetView, который вы снова добавите к виджету. Полный код доступен в HomeActivity.java, ищите метод onCreateContextMenu(...)
.
@Override
public void onCreateContextMenu(ContextMenu contextMenu,
View v,
ContextMenu.ContextMenuInfo menuInfo) {
AdapterView.AdapterContextMenuInfo info =
(AdapterView.AdapterContextMenuInfo) menuInfo;
selectedWord = ((TextView) info.targetView).getText().toString();
selectedWordId = info.id;
contextMenu.setHeaderTitle(selectedWord);
contextMenu.add(0, CONTEXT_MENU_EDIT_ITEM, 0, R.string.edit);
contextMenu.add(0, CONTEXT_MENU_DELETE_ITEM, 1, R.string.delete);
}
Обратите внимание, что я сохраняю выделенный текст, а также идентификатор select в частных полях. Поскольку пользовательский интерфейс ограничен потоком, я знаю, что выбранные поляWord и selectedWordId будут корректными для последующих действий.
Ответ 2
Прежде всего, мне интересно, не слишком ли сложно сделать что-то, используя View.setOnCreateContextMenuListener()
. Все будет намного проще, если вы используете Activity.registerForContextMenu()
, потому что тогда вы можете просто использовать Activity.onCreateContextMenu()
и Activity.onContextItemSelected()
для обработки всех ваших событий в меню. Это в основном означает, что вам не нужно определять все эти анонимные внутренние классы для обработки каждого события; вам просто нужно переопределить несколько методов Activity для обработки этих событий контекстного меню.
Во-вторых, есть определенно более простые способы извлечения выбранного элемента. Все, что вам нужно сделать, это сохранить ссылку либо на ListView
, либо на Adapter
, используемые для ее заполнения. Вы можете использовать ContextMenuInfo как AdapterContextMenuInfo для получения позиции элемента; а затем вы можете использовать ListView.getItemAtPosition()
или Adapter.getItem()
для извлечения Object
, специально связанного с тем, что было нажато. Например, предположим, что я использую Activity.onCreateContextMenu()
, я мог бы сделать это:
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
// Get the info on which item was selected
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
// Get the Adapter behind your ListView (this assumes you're using
// a ListActivity; if you're not, you'll have to store the Adapter yourself
// in some way that can be accessed here.)
Adapter adapter = getListAdapter();
// Retrieve the item that was clicked on
Object item = adapter.getItem(info.position);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
// Here how you can get the correct item in onContextItemSelected()
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
Object item = getListAdapter().getItem(info.position);
}
Ответ 3
это еще один способ создания контекстного меню. n Как удалить элемент, выбранный здесь, - это весь код
public class SimpleJokeList extends Activity {
public static final int Upload = Menu.FIRST + 1;
public static final int Delete = Menu.FIRST + 2;
int position;
ListView lv;
EditText jokeBox;
Button addJoke;
MyAdapter adapter;
private ArrayAdapter<String> mAdapter;
private ArrayList<String> mStrings = new ArrayList<String>();
String jokesToBeAdded;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simplejokeui);
lv=(ListView)findViewById(R.id.jokelist);
addJoke=(Button)findViewById(R.id.addjoke);
jokeBox=(EditText)findViewById(R.id.jokebox);
mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mStrings);
registerForContextMenu(lv);
listItemClicked();
addJokes();
private void addJokes() {
// TODO Auto-generated method stub
addJoke.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
jokesToBeAdded=jokeBox.getText().toString();
if(jokesToBeAdded.equals("")){
Toast.makeText(getApplicationContext(), "please enter some joke", Toast.LENGTH_LONG).show();
}
else{
lv.setAdapter(mAdapter);
mAdapter.add(jokesToBeAdded);
jokeBox.setText(null);
}
}
});
}
private void listItemClicked() {
// TODO Auto-generated method stub
lv.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
// TODO Auto-generated method stub
position=arg2;
return false;
}
});
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
// TODO Auto-generated method stub
super.onCreateContextMenu(menu, v, menuInfo);
populateMenu(menu);
menu.setHeaderTitle("Select what you wanna do");
}
private void populateMenu(ContextMenu menu) {
// TODO Auto-generated method stub
menu.add(Menu.NONE, Upload, Menu.NONE, "UPLOAD");
menu.add(Menu.NONE, Delete, Menu.NONE, "DELETE");
}
@Override
public boolean onContextItemSelected(MenuItem item)
{
return (applyMenuChoice(item) || super.onContextItemSelected(item));
}
private boolean applyMenuChoice(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId())
{
case Delete:
String s=mAdapter.getItem(position);
mAdapter.remove(s);
// position--;
Toast.makeText(getApplicationContext(),"Congrats u HAve Deleted IT", Toast.LENGTH_LONG).show();
return (true);
}
return false;
}
Ответ 4
И не забудьте поставить этот
registerForContextMenu(listview);
в вашем методе onCreate
, чтобы отобразить ваше контекстное меню.
Ответ 5
Не является ли аргумент представления фактическим выбранным представлением строк, или я пропущу здесь вопрос?
ListView lv;
private OnItemLongClickListener onLongClick = new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
lv.showContextMenuForChild(arg1);
lv.showContextMenu();
return false;
}
};
Ответ 6
Мы успешно использовали:
@Override
public boolean onContextItemSelected
(
MenuItem item
)
{
if (!AdapterView.AdapterContextMenuInfo.class.isInstance (item.getMenuInfo ()))
return false;
AdapterView.AdapterContextMenuInfo cmi =
(AdapterView.AdapterContextMenuInfo) item.getMenuInfo ();
Object o = getListView ().getItemAtPosition (cmi.position);
return true;
}
Ответ 7
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
View TargetV=(View) info.targetView;
text1 = (String) ((TextView) TargetV.findViewById(R.id.textView1)).getText();
text2 = (String) ((TextView) TargetV.findViewById(R.id.textView2)).getText();
if(List3Ok){
text3 = (String) ((TextView) TargetV.findViewById(R.id.textView3)).getText();
}
selectedWord = text1 + "\n" + text2 + "\n" + text3;
selectedWordId = info.id;
menu.setHeaderTitle(selectedWord);
MenuInflater inflater = this.getActivity().getMenuInflater();
inflater.inflate(R.menu.list_menu, menu);
}
Ответ 8
В случае, если вы используете SimpleCursorAdapder
, вы можете сделать это следующим образом
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
getActivity().getMenuInflater().inflate(R.menu.project_list_item_context, menu);
// Getting long-pressed item position
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
int position = info.position;
// Get all records from adapter
Cursor c = ((SimpleCursorAdapter)getListAdapter()).getCursor();
// Go to required position
c.moveToPosition(position);
// Read database fields values associated with our long-pressed item
Log.d(TAG, "Long-pressed-item with position: " + c.getPosition());
Log.d(TAG, "Long-pressed-item _id: " + c.getString(0));
Log.d(TAG, "Long-pressed-item Name: " + c.getString(1));
Log.d(TAG, "Long-pressed-item Date: " + c.getString(2));
Log.d(TAG, "Long-pressed-item Path: " + c.getString(3));
// Do whatever you need here with received values
}