menuInfo is null when creating context menu on rec

2019-07-16 14:19发布

问题:

I am trying to display a context menu on clicking item in a recycler view, and the choose to call the person whose name has been clicked. But I am unable to retrieve the phone number because the getMenuInfo() is not working bcoz I am getting a null in contextMenuInfo in onCreateContextMenu(). I have referenced many answers and written my code accordingly but still not able to correct it Here is my code:

menu_actions.xml

    <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
    android:id="@+id/call"
    android:title="Call">
</item>
<item
    android:id="@+id/sms"
    android:title="Send SMS">

</item>
<item
    android:id="@+id/email"
    android:title="Send email">
</item>
<item
    android:id="@+id/viewContact"
    android:title="View Details">

</item>
<item
    android:id="@+id/editContact"
    android:title="Edit Contact">
</item>
<item
    android:id="@+id/deleteContact"
    android:title="Delete">

</item>
</menu>

My fragment which contains the recycler view:

public class MyContacts extends Fragment {
public static RecyclerView recyclerView;
public static Person receivedData;
static Context c;
static int itemIndex;

DatabaseAdapter dbAdapter = new DatabaseAdapter(getContext());
private static RecyclerViewAdapter recyclerViewAdapter;
ArrayList<Person> persons = new ArrayList<>();

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    c = getContext();
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    MainActivity activity = (MainActivity) getActivity();
    receivedData = activity.getData();

    View layout = inflater.inflate(R.layout.fragment_my_contacts, container, false);
    recyclerView = (RecyclerView) layout.findViewById(R.id.myContactsList);
    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setItemAnimator(new DefaultItemAnimator());

    recyclerViewAdapter=new RecyclerViewAdapter(activity, persons);
    recyclerView.setAdapter(recyclerViewAdapter);

    registerForContextMenu(recyclerView);
    retrieve();

    return layout;

}

public void retrieve()
{
    persons.clear();
    DatabaseAdapter databaseAdapter = new DatabaseAdapter(c);
    databaseAdapter.openDB();

    //retrieves the whole table from DB
    Cursor cursor = databaseAdapter.getDataForList();
    // loop and add to array list
    while (cursor.moveToNext())
    {


        int index1 = cursor.getColumnIndex(Constants.PHONE);
        String name = cursor.getString(index1);
           ......
        Person p = new Person(name, phone, address, email, dob, R.id.contactImage);

        persons.add(p);

    }

    //if array list not empty
    if (!(persons.size() <1))
    {
        recyclerViewAdapter.notifyDataSetChanged();
    }
    databaseAdapter.closeDB();

}


@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) // here menuInfo is coming NULL
{
    super.onCreateContextMenu(menu, view, menuInfo);
    getActivity().getMenuInflater().inflate(R.menu.menu_actions, menu);
    menu.setHeaderTitle("Actions");

    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
    itemIndex = info.position;
}

public boolean onContextItemSelected(MenuItem item)
{       

    switch (item.getItemId())
    {
        case R.id.call:
         call();

            Toast.makeText(getContext(), "Calling...", Toast.LENGTH_LONG).show();
            return true;
        case R.id.sms:
            Toast.makeText(getContext(), "SMS", Toast.LENGTH_LONG).show();
            return true;
        case R.id.email:
            Toast.makeText(getContext(), "Email", Toast.LENGTH_LONG).show();
            return true;
        case R.id.editContact:
            Toast.makeText(getContext(), "Editing", Toast.LENGTH_LONG).show();
            return true;
        case R.id.deleteContact:
            Toast.makeText(getContext(), "Deleting", Toast.LENGTH_LONG).show();
            return true;
        default:
            return super.onContextItemSelected(item);

    }
}

private void call() {
    Log.d("PHONE", String.valueOf(itemIndex));
    receivedData = (Person)dbAdapter.getPhone(itemIndex);
    Log.d("PHONE",receivedData.getPhone().toString());

    Intent call = new Intent(Intent.ACTION_CALL);
    call.setData(Uri.parse("tel:" + receivedData.getPhone()));
    startActivity(call);
}

ContextMenuRecyclerView:

public class ContextMenuRecyclerView extends RecyclerView {
private RecyclerContextMenuInfo mContextMenuInfo ;

public ContextMenuRecyclerView(Context context) {
    super(context);
}
public ContextMenuRecyclerView(Context context, AttributeSet attrs)
{
    super(context,attrs);
}
public ContextMenuRecyclerView(Context context, AttributeSet attrs, int defStyle)
{
    super(context,attrs,defStyle);
}

//I think problem is somewhere in this function. I dont think its getting called.
@Override
protected ContextMenu.ContextMenuInfo getContextMenuInfo()
{
    return mContextMenuInfo;
}

@Override
public boolean showContextMenuForChild(View originalView)
{
    final int longPressPosition = getChildAdapterPosition(originalView);
    if (longPressPosition >=0)
    {
        final long longPressId = MyContacts.recyclerView.getAdapter().getItemId(longPressPosition);  //MyContacts.recyclerView.
        mContextMenuInfo = new RecyclerContextMenuInfo(longPressPosition, longPressId);//createContextMenuInfo
        return super.showContextMenuForChild(originalView);
    }
    return false;
}


public static class RecyclerContextMenuInfo implements ContextMenu.ContextMenuInfo
{
    //position in adapter for which context menu is being displayed
    final public int position;

    //row id of the item for which context menu is being displayed
    final public long id;

    public RecyclerContextMenuInfo(int position, long id)
    {
        this.position = position;
        this.id = id;
    }
  }
} 

My RecyclerViewAdapter

   public class RecyclerViewAdapter extends     RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder>{

static Context c;
private LayoutInflater inflater;
List<Person> persons = Collections.emptyList();

public RecyclerViewAdapter(FragmentActivity context, List<Person> persons){
    inflater = LayoutInflater.from(context);
    this.persons = persons;
    this.c = context;
}


//Initializing view holder
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
   View view  = inflater.inflate(R.layout.single_row, parent, false);
    MyViewHolder holder = new MyViewHolder(view);
    return holder;
}

@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {

    Person current = persons.get(position);
    holder.image.setImageResource(R.drawable.contact);
    holder.name.setText(current.getName());
    holder.phone.setText(current.getPhone());

    holder.itemView.setLongClickable(true);
}

@Override
public int getItemCount() {
    return persons.size();
}

@Override
public long getItemId(int position) {
    return super.getItemId(position);
}

public static class MyViewHolder extends RecyclerView.ViewHolder 
{
    ImageView image;
    TextView name;
    TextView phone;
    ItemClickListener itemClickListener;

    ContextMenuRecyclerView recyclerView = new ContextMenuRecyclerView(c);

    public MyViewHolder(View itemView) {

        super(itemView);
        image = (ImageView) itemView.findViewById(R.id.listImage);
        name = (TextView) itemView.findViewById(R.id.listName);
        phone = (TextView) itemView.findViewById(R.id.listPhone);


    }


}

}

Please help me figure out!!

回答1:

I did it like this, declared a field private MyViewHolder holder, instead just making it local and inside the onCreateContextMenu i called it like this

getItem(vh.getAdapterPosition());