将弹出菜单对齐到 RecyclerView 项目的右侧

Align Popup Menu to the right side in RecyclerView Item

我在 RecyclerView 中的每个列表项上使用 Popup Menu,每当我单击 RecyclerView 中任何项目的溢出图标(3 个点)时,弹出菜单出现在我布局的最左侧。

我试过使用 setGravity 方法施加重力,但它根本不起作用。

但我注意到一件事,当我实际使用 ListView 而不是 RecyclerView 时它工作得很好。

MyAdapter 代码示例:

public class RecyclerAssetsAdapter extends RecyclerView.Adapter<RecyclerAssetsAdapter.ViewHolder> {

    List<AssetsBean> assetsBeanList;
    Context context;

    public RecyclerAssetsAdapter(List<AssetsBean> assetsBeanList, Context context) {
        this.assetsBeanList = assetsBeanList;
        this.context = context;
    }

    public void filter(List<AssetsBean> newList){
        assetsBeanList = newList;
        notifyDataSetChanged();
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_list,viewGroup,false);
        ViewHolder vh = new ViewHolder(view);
        return vh;
    }

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder viewHolder, final int i) {
        viewHolder.type.setText(assetsBeanList.get(i).getassetName());
        viewHolder.desc.setText(assetsBeanList.get(i).getassetDesc());
        viewHolder.building.setText(assetsBeanList.get(i).getCreatedAt());

        final ViewHolder finalViewHolder = viewHolder;
        viewHolder.overflowIcon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                PopupMenu popupMenu = new PopupMenu(context, viewHolder.building);
                popupMenu.getMenuInflater().inflate(R.menu.assets_popup_menu,popupMenu.getMenu());
                popupMenu.setGravity(Gravity.END);
                popupMenu.setGravity(Gravity.RIGHT);
                popupMenu.show();
                popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                    @Override
                    public boolean onMenuItemClick(MenuItem item) {
                        switch (item.getItemId()){
                            case R.id.view: //view
                                Fragment detailsFragment = new DetailsFragment();
                                Bundle args1 = new Bundle();
                                args1.putString("objectId",assetsBeanList.get(i).getObjectId());
//                                args.putString("assetType",mb.getassetName());
                                args1.putString("qrcode",assetsBeanList.get(i).getQrcode());
                                detailsFragment.setArguments(args1);
                                ((AppCompatActivity) context).getSupportFragmentManager().beginTransaction().addToBackStack(null).replace(R.id.my_fragment,detailsFragment).commit();
                                break;
                            case R.id.edit:
                                Fragment formFragment = new FormFragment();
                                Bundle args2 = new Bundle();
                                args2.putString("objectId",assetsBeanList.get(i).getObjectId());
                                formFragment.setArguments(args2);
                                ((AppCompatActivity) context).getSupportFragmentManager().beginTransaction().addToBackStack(null).replace(R.id.my_fragment,formFragment).commit();
                                break;
                            case R.id.see_logs: //see logs
                                Fragment assetsLogFragment = new AssetLogFragment();
                                Bundle args = new Bundle();
                                args.putString("objectId",assetsBeanList.get(i).getObjectId());
                                args.putString("assetType",assetsBeanList.get(i).getassetName());
                                args.putString("assetDesc",assetsBeanList.get(i).getassetDesc());
                                assetsLogFragment.setArguments(args);
                                ((AppCompatActivity) context).getSupportFragmentManager().beginTransaction().addToBackStack(null).replace(R.id.my_fragment,assetsLogFragment).commit();
                                break;
                            case R.id.move:
                                //move to new organisation
                                AlertDialog.Builder builder1 = new AlertDialog.Builder(context);
                                builder1.setTitle("Move To Department");
                                EditText editText = new EditText(context);
                                editText.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
                                builder1.setView(editText);
                                builder1.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {

                                    }
                                });
//                                ParseQuery<ParseObject> assetQuery = new ParseQuery<ParseObject>("assets");
//                                assetQuery.whereEqualTo("objectId",mb.getObjectId());
//                                assetQuery.include("organization");
//                                assetQuery.findInBackground(new FindCallback<ParseObject>() {
//                                    @Override
//                                    public void done(List<ParseObject> objects, ParseException e) {
//
//                                    }
//                                });
                                break;
                            case R.id.delete: //delete assest
                                AlertDialog.Builder builder = new AlertDialog.Builder(context);
                                builder.setTitle("Delete");
                                builder.setMessage("Are you sure you want to delete this Asset and its associated log?");
                                builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("assets");
                                        query.whereEqualTo("objectId",assetsBeanList.get(i).getObjectId());
                                        ParseQuery<ParseObject> logQuery = new ParseQuery<ParseObject>("logs");
                                        query.findInBackground(new FindCallback<ParseObject>() {
                                            @Override
                                            public void done(List<ParseObject> objects, ParseException e) {
                                                for(ParseObject object: objects){
                                                    object.deleteEventually();

                                                }
                                            }
                                        });
                                        logQuery.whereMatchesQuery("asset",query);
                                        logQuery.findInBackground(new FindCallback<ParseObject>() {
                                            @Override
                                            public void done(List<ParseObject> objects, ParseException e) {
                                                for(ParseObject object: objects){
                                                    object.deleteEventually();
                                                }
                                            }
                                        });

                                        assetsBeanList.remove(assetsBeanList.get(i));
                                        notifyDataSetChanged();
                                    }
                                });
                                builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {

                                    }
                                });
                                builder.show();
                                break;
                            default:break;
                        }
                        return true;
                    }
                });
            }
        });

    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {

        TextView type,desc,building;
        ImageView overflowIcon;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            type = itemView.findViewById(R.id.session_name);
            desc = itemView.findViewById(R.id.session_desc);
            building = itemView.findViewById(R.id.created_at);
            overflowIcon = itemView.findViewById(R.id.overflow_icon);
        }
    }
}

According to docs PopupMenucontextanchor view 作为其构造函数参数。我想您希望弹出菜单在单击时显示在溢出图标附近。

在您的代码中,您将错误的视图作为锚传递给 PopupMenu 构造函数:

PopupMenu popupMenu = new PopupMenu(context, viewHolder.building);

尝试将 viewHolder.building 替换为 viewHolder.overflowIcon:

PopupMenu popupMenu = new PopupMenu(context, viewHolder.overflowIcon);
PopupMenu popupMenu = new PopupMenu(context, viewHolder.overflowIcon);

popupMenu.showAsDropDown(id);//id是你要显示的视图id