在我的 ListVeiw 项目中,我有 4-8 个 ImageView(其中一些是不可见的,取决于某些值)和 4 个 TextView。
当我长按 Listview 的项目时,(AdapterContextMenuInfo) item.getMenuInfo() 返回 null。
在我的适配器中,我定义了以下方法:
public int getCount() {
return NewList.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public void Remove(int id){
notifyDataSetChanged();
}
public View getView(int position, View convertView, ViewGroup parent){
View vi=convertView;
NewsFeedHolder holder;
News n= NewList.get(position);
List<NewsItem> items = n.getNewsItems();
int ItemsLen = items.size();
if (convertView == null){
vi = inflater.inflate(R.layout.newsfeed_item, null);
holder=new NewsFeedHolder();
holder.txtTitle = (TextView)vi.findViewById(R.id.newsfeed_item_name);
holder.avatar_image = (ImageView)vi.findViewById(R.id.newsfeed_item_icon);
holder.txtUpdate = (TextView)vi.findViewById(R.id.newsfeed_item_update);
holder.txtLike = (TextView)vi.findViewById(R.id.newsfeed_item_like);
holder.txtDisLike = (TextView)vi.findViewById(R.id.newsfeed_item_dislike);
holder.btnLike = (ImageButton)vi.findViewById(R.id.newsfeed_like_button) ;
holder.btntxtDisLike = (ImageButton)vi.findViewById(R.id.newsfeed_dislike_button);
holder.imgItemIcon1 = (ImageView)vi.findViewById(R.id.newsfeed_item_icon1);
holder.imgItemIcon2 = (ImageView)vi.findViewById(R.id.newsfeed_item_icon2);
holder.imgItemIcon3 = (ImageView)vi.findViewById(R.id.newsfeed_item_icon3);
holder.btnLike.setOnClickListener(activity.OnLikeClickListener);
holder.btntxtDisLike.setOnClickListener(activity.OnDisLikeOnClickListener);
vi.setTag(holder);
}
else {
holder=(NewsFeedHolder)vi.getTag();
}
imageLoader.DisplayImage(n.getUserAvatarUrl(), activity, holder.avatar_image);
String url1,url2,url3;
try{
switch(ItemsLen){
case 1:
url1 = n.getNewsItems().get(0).getItemUrl();
imageLoader.DisplayImage(url1, activity, holder.imgItemIcon1);
break;
case 2:
url1 = n.getNewsItems().get(1).getItemUrl();
imageLoader.DisplayImage(url1, activity, holder.imgItemIcon1);
url2 = n.getNewsItems().get(1).getItemUrl();
imageLoader.DisplayImage(url2, activity, holder.imgItemIcon2);
break;
case 3:
url1 = n.getNewsItems().get(2).getItemUrl();
imageLoader.DisplayImage(url1, activity, holder.imgItemIcon1);
url2 = n.getNewsItems().get(2).getItemUrl();
imageLoader.DisplayImage(url2, activity, holder.imgItemIcon2);
url3 = n.getNewsItems().get(2).getItemUrl();
imageLoader.DisplayImage(url3, activity, holder.imgItemIcon3);
break;
default:
}
}
catch(Exception e){
Log.i("adaptex",e.getMessage());
}
holder.txtTitle.setText(n.getNewsTitle());
holder.txtUpdate.setText(n.getUpdate());
holder.txtLike.setText(Integer.toString(n.getLike()));
holder.txtDisLike.setText(Integer.toString(n.getDesLike()));
activity.registerForContextMenu(vi);
vi.setOnClickListener(activity.OnListItemClickListener);
return vi;
}
当我尝试获取
item.getMenuInfo()
时,我收到 null。
您需要注册上下文菜单的列表,而不是项目。
// wrong:
activity.registerForContextMenu(vi);
// right:
activity.registerForContextMenu(myList);
可能与此无关,但我立即看到的一件明显的事情是:
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
您的 getItem 方法返回对象位置的
int
,而不是其方法声明中所述的实际 Object
本身。
getMenuInfo() 适用于 ListAdapter,不适用于视图。
但是,您可以使用视图的标签传递附加数据。
在 getView 中: vi.setTag(位置) Activity.registerForContextMenu(vi);
在 Activity 中声明 私有 int id;
创建上下文菜单: id = (int) v.getTag();
onContextItemSelected: 你可以使用id
我不久前也遇到过类似的问题。深入研究文档后,我发现必须使用 View#setOnCreateContextMenuListener 方法将所选项目的数据传递到视图 View.OnCreateContextMenuListener 内适配器中项目根视图中的 ContextMenu.ContextMenuInfo 对象。但是,没有方法可以执行此操作,并且使用 AdapterView.AdapterContextMenuInfo 构造函数设置对象实际上不会覆盖它的 null 值。因此,我使用自定义对象在 View#setOnCreateContextMenuListener 方法中传递这些值,并在 AppCompatActivity#onContextItemSelected 方法中获取值。这是我的代码......
这是我的项目布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="?recyclerItemBackground">
<TextView android:layout_width="match_parent"
android:id="@+id/name_tv"
android:layout_height="wrap_content"
android:text="anville"
android:textSize="20sp"/>
<TextView android:layout_width="match_parent"
android:id="@+id/number_tv"
android:layout_height="wrap_content"
android:text="anville"
android:textSize="20sp"/>
</LinearLayout>
这是我的适配器,我在 RecyclerView.Adapter#onBindViewHolder 方法中设置了 View#setOnCreateContextMenuListener
package io.github.anville95work.menuexample;
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class Adapter extends RecyclerView.Adapter<ViewHolder> {
private Context context;
private ArrayList<People> peopleList;
private PositionHolder positionHolder;
public Adapter(Context context, ArrayList<People> peopleList, PositionHolder positionHolder) {
this.context = context;
this.peopleList = peopleList;
this.positionHolder = positionHolder;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View itemView = inflater.inflate(R.layout.item_layout, parent, false);
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, @SuppressLint("RecyclerView") int position) {
holder.getNameTV().setText(peopleList.get(position).getName());
holder.getPhoneTV().setText(String.valueOf(peopleList.get(position).getNumber()));
//MUST SET CREATE CONTEXT MENU LISTENER
holder.getItemView().setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
positionHolder.setPosition(position);
}
});
}
@Override
public int getItemCount() {
return peopleList.size();
}
}
class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(@NonNull View itemView) {
super(itemView);
itemView.setLongClickable(true);
//YOU MUST SET_LONG_CLICKABLE TO TRUE FOR CONTEXT MENU TO WORK
}
private TextView nameTV = itemView.findViewById(R.id.name_tv);
private TextView phoneTV = itemView.findViewById(R.id.number_tv);
public TextView getNameTV() {
return nameTV;
}
public TextView getPhoneTV() {
return phoneTV;
}
public View getItemView() {
return itemView;
}
}
这是我的 AppCompatActivity,我创建了一个 PositionHolder 的私有对象,并传递了对适配器对象的引用,以便在创建上下文菜单时进行修改。我在底部添加了 PositionHolder 类。
package io.github.anville95work.menuexample;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Toast;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private PositionHolder positionHolder = new PositionHolder(0);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recycler_view);
LinearLayoutManager manager = new LinearLayoutManager(this);
manager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(manager);
ArrayList<People> peopleArrayList = new ArrayList<People>();
for(int i = 0; i <= 40; i++) {
peopleArrayList.add(new People("anville-" + i, 2547 + i));
}
Adapter adapter = new Adapter(this, peopleArrayList, positionHolder);
recyclerView.setAdapter(adapter);
//CONTEXT MENU
//YOU MUST SET_LONG_CLICKABLE TO TRUE IN VIEW_HOLDER FOR CONTEXT MENU TO WORK
registerForContextMenu(recyclerView);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.option1:
Toast.makeText(this, "You selected the first option", Toast.LENGTH_SHORT).show();
return true;
case R.id.option2:
Toast.makeText(this, "You selected the second option", Toast.LENGTH_SHORT).show();
return true;
case R.id.option3:
Toast.makeText(this, "You selected the third option", Toast.LENGTH_SHORT).show();
return true;
case R.id.option4:
Toast.makeText(this, "You selected the fourth option", Toast.LENGTH_SHORT).show();
return true;
case R.id.option5:
Toast.makeText(this, "You selected the fifth option", Toast.LENGTH_SHORT).show();
return true;
default:
Toast.makeText(this, "How did this come to be?!!", Toast.LENGTH_SHORT).show();
return true;
}
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
//USE THIS METHOD TO MODIFY THE MENU IN RUN_TIME IF NEED BE.
//to update the menu you must call invalidateOptionsMenu() so as to trigger a callBack for this method
return true;
}
@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
System.out.println("Position: " + String.valueOf(positionHolder.getPosition()));
switch(item.getItemId()) {
case R.id.context_option1:
Toast.makeText(this, "You want option1 for " + positionHolder.getPosition(), Toast.LENGTH_LONG).show();
return true;
case R.id.context_option2:
Toast.makeText(this, "You want option2 for " + positionHolder.getPosition(), Toast.LENGTH_LONG).show();
return true;
case R.id.context_option3:
Toast.makeText(this, "You want option3 for " + positionHolder.getPosition(), Toast.LENGTH_LONG).show();
return true;
case R.id.context_option4:
Toast.makeText(this, "You want option4 for " + positionHolder.getPosition(), Toast.LENGTH_LONG).show();
return true;
case R.id.context_option5:
Toast.makeText(this, "You want option5 for " + positionHolder.getPosition(), Toast.LENGTH_LONG).show();
return true;
default:
Toast.makeText(this, "I have no idea what you want for " + positionHolder.getPosition(), Toast.LENGTH_LONG).show();
return super.onContextItemSelected(item);
}
}
}
class PositionHolder {
private int position;
public PositionHolder(int position) {
this.position = position;
}
public void setPosition(int position) {
this.position = position;
}
public int getPosition() {
return position;
}
}
一切顺利。感谢您的阅读,祝您编码愉快。