我的应用中有两个布局文件。我还有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中
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="5dp">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="5dp">
<ListView
android:id="@+id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</FrameLayout>
</LinearLayout>
</TabHost>
Item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:textSize="15sp"
android:singleLine="true"
android:ellipsize="marquee"
android:scrollHorizontally = "true"
android:maxWidth="200dp"
/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="right"
>
<ImageButton
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:background="@null"
android:paddingRight="10dp"
android:paddingLeft="10dp"
/>
</LinearLayout>
</LinearLayout>
这一切都行不通。也许原因在于LinearLayout?我也找到类似的主题Android: Context menu doesn't show up for ListView with members defined by LinearLayout?,但我有更复杂的列表项。
如何在我的案例中获取上下文菜单?
同样在我的活动中,我有内部类扩展ArrayAdapter。在getView方法的这个类中,我可以在每个View上设置OnCreateContextMenuListener,然后出现上下文菜单,但我不知道如何处理项目点击。如果我试图在方法onContextItemSelected中执行此操作,则item.getMenuInfo()对象始终为null,并且我无法从中获取某些信息。
private class ChannelAdapter extends ArrayAdapter<Channel> {
private List<Channel> channels;
public ChannelAdapter(Context context, int textViewResourceId, List<Channel> 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);
}
});
感谢。希望得到你的帮助。
答案 0 :(得分:33)
我得到了解决方案,我的朋友帮助了我!希望这些信息对某人有所帮助。 这是包含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<ComplexObject> list = new ArrayList<ComplexObject>();
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<ComplexObject> implements View.OnCreateContextMenuListener {
private List<ComplexObject> objects;
public ComplexObjectAdapter(Context context, int textViewResourceId, List<ComplexObject> 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
}
}
}
让我知道是否有人会找到更好的方法。谢谢!
答案 1 :(得分:7)
在Georgy Gobozov的答案中列出了嵌套类ComplexObjectAdapter的代码片段,并不是真的需要:
@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布局文件中设置此属性,例如:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:longClickable="true">
<!-- Child elements -->
</LinearLayout>
答案 2 :(得分:1)
实际上,您只需要通过调用
使View可以长时间点击v.setLongClickable(true);
不需要设置虚拟setOnCreateContextMenuListener
,因为它就是这样 - 设置长项目可点击的项目。
答案 3 :(得分:0)
我认为您不想将上下文菜单附加到特定的listView项目。通过调用registerForContextMenu(getListView()),您应该免费获得该功能。从适配器代码中删除contextMenu挂钩并在onCreateContextMenu()内部设置断点后,我会将应用程序挂钩到调试器。我怀疑是它被调用但是被夸大的布局并不是你所期望的。
答案 4 :(得分:0)
基本问题是第二个item.xml布局正在绘制项目 - 因此根元素(LinearLayout)是长按而不是原始ListView提供的内容。因此,当您扩展item.xml布局时,您需要调用setOnCreateContextMenuListener,就像您在第二个示例中实际完成的那样。这样做的问题是,item.xml(这是一个LinearLayout)的布局无法与选择的位置进行通信。这是因为LinearLayout不会覆盖getContextMenuInfo()方法,该方法在ListView中返回一个AdapterView.AdapterContextMenuInfo(因为每个人似乎强迫他们的ContextMenuInfo)。
理想情况下,你想要创建自己的LinearLayout后代,使getContextMenuInfo公开,如果没有那个就创建一个假的,并且当你的自定义适配器中调用onCreateContextMenu时,它会从你的自定义LinearLayout中获取它将位置/ ID放在那里,您的活动可以将其拉出。
这是我在自己的应用程序中所做的,它非常好用,并且是一个通用的解决方案 - 事实上,只要它实现了ContextMenuInfo接口(它只是一个标记接口),你就可以在那里放任何你喜欢的东西。
答案 5 :(得分:0)
我现在不知道为什么,有必要在每个列表行上设置一个null OnCreateContextMenuListener(除了registerForContextMenu(...)并实现onCreateContextMenu(...)和onContextItemSelected(...)