为什么 item.getMenuInfo() 为 null?

问题描述 投票:0回答:4

在我的 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。

android menuitem
4个回答
3
投票

您需要注册上下文菜单的列表,而不是项目。

// wrong:
activity.registerForContextMenu(vi);

// right:
activity.registerForContextMenu(myList);

0
投票

可能与此无关,但我立即看到的一件明显的事情是:

public Object getItem(int position) {
   return position;
}

public long getItemId(int position) {
   return position;
}

您的 getItem 方法返回对象位置的

int
,而不是其方法声明中所述的实际
Object
本身。


0
投票

getMenuInfo() 适用于 ListAdapter,不适用于视图。

但是,您可以使用视图的标签传递附加数据。

在 getView 中: vi.setTag(位置) Activity.registerForContextMenu(vi);

在 Activity 中声明 私有 int id;

创建上下文菜单: id = (int) v.getTag();

onContextItemSelected: 你可以使用id


0
投票

我不久前也遇到过类似的问题。深入研究文档后,我发现必须使用 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;
    }
}

一切顺利。感谢您的阅读,祝您编码愉快。

© www.soinside.com 2019 - 2024. All rights reserved.