PopupMenu 有时不显示在屏幕上

PopupMenu sometimes does not show on screen

我有一个包含在片段中的视图。该视图包含许多 "buttons"(每个“按钮是一个 ImageView)(见屏幕 1) Screen 1

我的 objective 是,当我单击这些按钮之一时,将出现一个 PopupMenu(见屏幕 2) Screen 2

这在大多数时间都运行良好,但在某些 "buttons" 上,当单击 "button" 时,通常不会显示 PopupMenu(尽管确实会出现 toast 消息,表明 'cick'已注册)。

该问题在左上角的 "button" 和片段底部的按钮上很明显。有时会出现菜单(但通常会在多次 'clicks' 之后出现)

我的工作假设是,出于某种原因,菜单没有显示在屏幕上(我相信它正在显示但 'off screen'/不可见)。

我已经研究过这个问题,但找不到有类似问题的人。

我在创建 PopupMenu 时尝试了不同的重力设置,但没有什么不同。

我用来创建 PopupMenu 的代码看起来很经典。

在此先感谢您提供的任何帮助。

摘自RemoteView.java

// Constructors
public RemoteView(Context context) {
    super(context);
    init(context);
}

public RemoteView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

public RemoteView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context);
}

private void init(Context context) {
    rootview = inflate(context, R.layout.remote, this);

}
public class IconViewOnTouchListener implements View.OnTouchListener {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    if (!edit) {
                        actionDOWN(v);
                    }
                    break;

                case MotionEvent.ACTION_UP:
                    KeyMap keyMap=(KeyMap) v.getTag();
                    if (edit) {
                        if (movingButton) {
                            toIndex=keyMap.AMKeyItem;
                            toKey=keyMap.keyIndex;
                            exchangeButtons();
                        } else {
                            //popup edit options
                            if (keyMap.AMKeyItem  >= 0) showPopup(v);
                        }
                    } else {
                       actionUP(v);
                        performClick();
                    }
                    break;
            }
            return true;
        }
    }

private void showPopup(final View view) {
        //Creating the instance of PopupMenu
        PopupMenu popup = new PopupMenu(context, view, Gravity.RIGHT, R.attr.actionOverflowMenuStyle, 0);
        //Inflating the Popup using xml file
        popup.getMenuInflater()
                .inflate(R.menu.edit_button_menu, popup.getMenu());
        Toast.makeText(context, "Popup Menu is visible",
                Toast.LENGTH_SHORT).show();
        popup.show(); //showing popup menu
    }

remote.xml

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent">
        <com.andy.andymote.CommunicatorView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/remote_communicator">
        </com.andy.andymote.CommunicatorView>

        <GridView xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/buttons"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:numColumns="5"
            android:gravity="center"
            android:stretchMode="spacingWidthUniform"
            >
        </GridView>
    </RelativeLayout>
</merge>

frag_device.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="top"
    android:orientation="vertical"
>

    <com.andy.andymote.RemoteView
        android:layout_width="match_parent"
        android:layout_height="match_parent"

        android:id="@+id/remote">
    </com.andy.andymote.RemoteView>

</LinearLayout>

edit_button_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/moveButton"
        android:title="Move"/>

    <item
        android:id="@+id/editButton"
        android:title="Edit"/>
    <item
        android:id="@+id/insertRow"
        android:title="Insert Row Above"/>

</menu>

摘自DeviceACTIVITY.java

    private void loadFragment(){
        device = new DeviceFRAGMENT();
        device.setDevice(GLOBALS.deviceList.getDevice(deviceName));
        getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
                device).commit();
    }

摘自DeviceFRAGMENT.java

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

            view = inflater.inflate(R.layout.frag_device, container, false);
            //Declare Widgets
            remote = view.findViewById(R.id.remote);
            remote.setKeys(device.getRemote());

        return view;
    }

RemoteKeysAdapter.java

import static com.andy.andymote.GLOBALS.iconSize;

public class RemoteKeysAdapter extends BaseAdapter {

    private final Context mContext;
    private final List<RemoteButton> remoteButtons;
    private _resourceAccess resource;
    private RemoteView.IconViewOnTouchListener iconViewOnTouchListener;
    private Remote remote;

    // 1
    public RemoteKeysAdapter(Context context, Remote remote, List<RemoteButton> remoteButtons,
                             RemoteView.IconViewOnTouchListener iconViewOnTouchListener) {
        this.mContext = context;
        this.remote=remote;
        this.remoteButtons = remoteButtons;
        this.iconViewOnTouchListener=iconViewOnTouchListener;
        resource = new _resourceAccess(context);
    }

    // 2
    @Override
    public int getCount() {
        return remoteButtons.size();
    }

    // 3
    @Override
    public long getItemId(int position) {
        return 0;
    }

    // 4
    @Override
    public Object getItem(int position) {
        return null;
    }

    // 5
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // Find the proper remoteButton for this cell by using the position index
        final RemoteButton remoteButton = remoteButtons.get(position);

        if (convertView == null) {
            final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
            convertView = layoutInflater.inflate(R.layout.remote_button, null);
        }

        // create reference for the image in the XML layout file.
        final AppCompatImageView imageView = convertView.findViewById(R.id.button);


        // Set the image
        int indexOfAndyMoteKeyItem=remoteButton.getFromToIndex();
        if (indexOfAndyMoteKeyItem == -1){
            imageView.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_nobutton));
        } else {
            AndyMoteKeyItem andyMoteKeyItem=remote.getRemoteLayout().get(indexOfAndyMoteKeyItem);
            if (andyMoteKeyItem.getLircKeyItem().getIcon().length() == 0) {
                displayText(imageView, andyMoteKeyItem.getLircKeyItem().getText());
            } else {
                displayIcon(imageView, andyMoteKeyItem.getLircKeyItem().getIcon());
            }
        }
        KeyMap keyMap=new KeyMap();
        keyMap.AMKeyItem=indexOfAndyMoteKeyItem;
        keyMap.keyIndex=position;

        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
        params.gravity= Gravity.CENTER;
        params.width=iconSize;
        params.height=iconSize;
        convertView.setLayoutParams(params);
        convertView.setOnTouchListener(iconViewOnTouchListener);
        convertView.setPadding(16, 0, 0, 16);
        convertView.setVisibility(remoteButton.getVisibility());

        convertView.setTag(keyMap);
        return convertView;
    }
    private void displayIcon(AppCompatImageView imageView, String icon) {
        clIcon newIcon = factory.createIcon(icon);
        imageView.setImageDrawable(resource.getDrawableFromUri(newIcon.getURI(mContext)));
    }

    private void displayText(AppCompatImageView imageView, String text) {
        //https://github.com/amulyakhare/TextDrawable
        TextDrawable drawable = TextDrawable.builder().beginConfig()
                .textColor(Color.WHITE)
                .bold()
                .withBorder(4)
                .useFont(Typeface.DEFAULT)
                .fontSize(30) /* size in px */
                .endConfig()
                .buildRound(text, Color.DKGRAY);

        imageView.setImageDrawable(drawable);
    }
}

我使用 Droppy 而不是 PopupMenu 解决了这个问题。不需要其他魔法

 private void showPopup(final View view) {
    DroppyMenuPopup.Builder popup = new DroppyMenuPopup.Builder(context, view);
    popup.addMenuItem(new DroppyMenuItem("Move").setId(R.id.moveButton));
    popup.addMenuItem(new DroppyMenuItem("Edit").setId(R.id.editButton));
    popup.addMenuItem(new DroppyMenuItem("Insert Row Above").setId(R.id.insertRow));
    // Set Callback handler
    popup.setOnClick(new DroppyClickCallbackInterface() {
        @Override
        public void call(View v, int id) {
            switch (id) {
                case R.id.editButton:
                    //code for editButton
                    break;
                case R.id.moveButton:
                    //code for moveButton
                    break;
                case R.id.insertRow:
                    //code for insertRow
                    break;
                default:
            }
        }
    });

    DroppyMenuPopup droppyMenu = popup.build();
    droppyMenu.show();
}