自定义ListView和上下文菜单。 怎么弄呢?

我的应用程序中有两个布局文件。 我还有Activity扩展ListActivity。 此活动的每个项目都会考虑item.xml布局文件。 我在长按项目时尝试获取上下文菜单,但我没有看到它。

在我的活动中,我尝试registerForContextMenu(getListView())并覆盖两个方法

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle bundle = this.getIntent().getExtras(); registerForContextMenu(getListView()); new PopulateAdapterTask().execute(ACTION_SELECT); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.context_menu, menu); } @Override public boolean onContextItemSelected(MenuItem item) { AdapterView.AdapterContextMenuInfo info; try { info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); } catch (ClassCastException e) { return false; } long id = getListAdapter().getItemId(info.position); Log.d(TAG, "id = " + id); return true; } 

main.xml中

           

Item.xml

         

这一切都行不通。 也许原因在于LinearLayout? 我也发现类似的主题Android:上下文菜单没有显示ListView与LinearLayout定义的成员? 但我有更复杂的列表项。

如何在我的情况下获取上下文菜单?

同样在我的活动中,我有内部类扩展ArrayAdapter。 在getView方法的这个类中,我可以在每个View上设置OnCreateContextMenuListener,然后出现上下文菜单,但我不知道如何处理项目点击。 如果我在方法onContextItemSelected中尝试执行此操作,则item.getMenuInfo()对象始终为null,并且我无法从中获取某些信息。

 private class ChannelAdapter extends ArrayAdapter { private List channels; public ChannelAdapter(Context context, int textViewResourceId, List objects) { super(context, textViewResourceId, objects); this.channels = objects; } @Override public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; if (v == null) { LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.station_item, null); } v.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() { public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.context_menu, menu); } }); 

谢谢。 希望得到你的帮助。

Solutions Collecting From Web of "自定义ListView和上下文菜单。 怎么弄呢?"

我得到了解决方案,我的朋友帮助了我! 希望这些信息对某人有所帮助。 这是带有ArrayAdapter和复杂列表布局和上下文菜单的完整类代码。

  public class ComplexListActivity extends ListActivity { /** * Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setListAdapter(new ComplexObjectAdapter(this, R.layout.item, getComplexObjects())); registerForContextMenu(getListView()); } private List getComplexObjects() { List list = new ArrayList(); list.add(new ComplexObject("1", "1", getResources().getDrawable(R.drawable.icon))); list.add(new ComplexObject("2", "2", getResources().getDrawable(R.drawable.icon))); list.add(new ComplexObject("3", "3", getResources().getDrawable(R.drawable.icon))); list.add(new ComplexObject("4", "4", getResources().getDrawable(R.drawable.icon))); list.add(new ComplexObject("5", "5", getResources().getDrawable(R.drawable.icon))); list.add(new ComplexObject("6", "6", getResources().getDrawable(R.drawable.icon))); list.add(new ComplexObject("7", "7", getResources().getDrawable(R.drawable.icon))); list.add(new ComplexObject("8", "8", getResources().getDrawable(R.drawable.icon))); list.add(new ComplexObject("9", "9", getResources().getDrawable(R.drawable.icon))); return list; } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.context_menu, menu); } @Override public boolean onContextItemSelected(MenuItem item) { AdapterView.AdapterContextMenuInfo info; try { info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); } catch (ClassCastException e) { Log.e("", "bad menuInfo", e); return false; } long id = getListAdapter().getItemId(info.position); Log.d("", "id = " + id); Toast.makeText(this, "id = " + id, Toast.LENGTH_SHORT).show(); return true; } private class ComplexObjectAdapter extends ArrayAdapter implements View.OnCreateContextMenuListener { private List objects; public ComplexObjectAdapter(Context context, int textViewResourceId, List objects) { super(context, textViewResourceId, objects); this.objects = objects; } @Override public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; if (v == null) { LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.item, null); } final ComplexObject o = objects.get(position); if (o != null) { TextView textlInfo = (TextView) v.findViewById(R.id.info); textlInfo.setText(o.getName()); ImageView channelIcon = (ImageView) v.findViewById(R.id.icon); channelIcon.setAdjustViewBounds(true); channelIcon.setMaxHeight(30); channelIcon.setMaxWidth(30); channelIcon.setImageDrawable(o.getLogo()); ImageButton button = (ImageButton) v.findViewById(R.id.button); button.setImageResource(R.drawable.icon); v.setOnCreateContextMenuListener(this); } return v; } public void onCreateContextMenu(ContextMenu contextMenu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) { // empty implementation } } } 

让我知道是否有人会find更好的方法。 谢谢!

以下是嵌套类ComplexObjectAdapter的代码片段,列在Georgy Gobozov的答案中,并不是真正需要的:

  @Override public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; if (v == null) { LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.item, null); } final ComplexObject o = objects.get(position); if (o != null) { TextView textlInfo = (TextView) v.findViewById(R.id.info); textlInfo.setText(o.getName()); ImageView channelIcon = (ImageView) v.findViewById(R.id.icon); channelIcon.setAdjustViewBounds(true); channelIcon.setMaxHeight(30); channelIcon.setMaxWidth(30); channelIcon.setImageDrawable(o.getLogo()); ImageButton button = (ImageButton) v.findViewById(R.id.button); button.setImageResource(R.drawable.icon); // NOT NEEDED v.setOnCreateContextMenuListener(this); } return v; } // NOT NEEDED public void onCreateContextMenu(ContextMenu contextMenu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) { // empty implementation } 

它只是工作,因为在类View中的函数setOnCreateContextMenuListener()内部,它调用函数setLongClickable(true):

 /** * Register a callback to be invoked when the context menu for this view is * being built. If this view is not long clickable, it becomes long clickable. * * @param l The callback that will run * */ public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) { if (!isLongClickable()) { setLongClickable(true); } mOnCreateContextMenuListener = l; } 

这意味着可以解决问题,在创建每个子项后为每个子项设置Long Clickable属性:

  @Override public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; if (v == null) { LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.item, null); // SET LONG CLICKABLE PROPERTY v.setLongClickable(true); } final ComplexObject o = objects.get(position); if (o != null) { TextView textlInfo = (TextView) v.findViewById(R.id.info); textlInfo.setText(o.getName()); ImageView channelIcon = (ImageView) v.findViewById(R.id.icon); channelIcon.setAdjustViewBounds(true); channelIcon.setMaxHeight(30); channelIcon.setMaxWidth(30); channelIcon.setImageDrawable(o.getLogo()); ImageButton button = (ImageButton) v.findViewById(R.id.button); button.setImageResource(R.drawable.icon); // NOT NEEDED // v.setOnCreateContextMenuListener(this); } return v; } 

或者也可以解决在列表视图子元素的XML布局文件中设置此属性,例如:

    

实际上,您只需要通过调用使View可以长时间点击

 v.setLongClickable(true); 

不需要设置虚拟setOnCreateContextMenuListener ,因为它就是这样 – 设置长项目可点击的项目。

我不认为您想要将上下文菜单附加到特定的listView项目。 通过调用registerForContextMenu(getListView()),您应该免费获得该function。 从适配器代码中删除contextMenu挂钩并在onCreateContextMenu()中设置断点后,我会将应用程序挂钩到调试器。 我怀疑是它被调用但是被夸大的布局并不是你所期望的。

基本问题是第二个item.xml布局正在绘制项目 – 因此根元素(LinearLayout)是长按而不是原始ListView提供的内容。 因此,当您扩展item.xml布局时,您需要调用setOnCreateContextMenuListener,就像您在第二个示例中实际完成的那样。 这样做的问题是,item.xml(这是一个LinearLayout)的布局无法与选择的位置进行通信。 这是因为LinearLayout没有覆盖getContextMenuInfo()方法,该方法在ListView中返回一个AdapterView.AdapterContextMenuInfo(因为每个人似乎强迫他们的ContextMenuInfo)。

理想情况下,您希望创建自己的LinearLayout后代,使getContextMenuInfo公开,如果没有那个就创建一个假的,并且当您的自定义适配器中调用onCreateContextMenu时,它会从您的自定义LinearLayout中获取它并放置位置/ id在那里,你的活动可以拉出来。

这就是我在自己的应用程序中所做的,它非常好用,并且是一个通用的解决方案 – 事实上,只要它实现了ContextMenuInfo接口(它只是一个标记接口),你就可以在其中放置任何你喜欢的东西。

我现在不知道为什么,有必要在每个列表行上设置一个null OnCreateContextMenuListener(除了registerForContextMenu(…)并实现onCreateContextMenu(…)和onContextItemSelected(…)