You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Java中的PopupMenu设置最大高度(附示例)

问题

我在Java代码中实现了一个点击按钮触发的PopupMenu,用于选择语言并调用翻译功能。由于语言选项数量较多,弹窗会延伸至手机屏幕顶部,与顶部无留白。请问能否在不改变原有功能的前提下,将该PopupMenu的最大高度限制为50dp?请提供实现示例。

解决方案

可以通过反射获取PopupMenu内部的ListView组件,设置其最大高度为指定值,同时完全保留原有功能。具体实现逻辑:

  • 将50dp转换为Android控件使用的像素值
  • 在PopupMenu显示后,通过反射拿到内部的ListView
  • 给ListView设置最大高度,超出部分自动变为可滚动状态
修改后的完整代码
private void showTranslateDialog() {
    PopupMenu popupMenu = new PopupMenu(getContext(), translateBtn);
    popupMenu.setGravity(Gravity.BOTTOM);

    // 添加语言选项(原有代码不变)
    popupMenu.getMenu().add(Menu.NONE, 1, 1, "Afrikaans");
    popupMenu.getMenu().add(Menu.NONE, 2, 2, "Arabic");
    popupMenu.getMenu().add(Menu.NONE, 3, 3, "Belarusian");
    popupMenu.getMenu().add(Menu.NONE, 4, 4, "Bulgarian");
    popupMenu.getMenu().add(Menu.NONE, 5, 5, "Bengali");
    popupMenu.getMenu().add(Menu.NONE, 6, 6, "Catalan");
    popupMenu.getMenu().add(Menu.NONE, 7, 7, "Czech");
    popupMenu.getMenu().add(Menu.NONE, 8, 8, "Welsh");
    popupMenu.getMenu().add(Menu.NONE, 9, 9, "Danish");
    popupMenu.getMenu().add(Menu.NONE, 10, 10, "German");
    popupMenu.getMenu().add(Menu.NONE, 11, 11, "Greek");
    popupMenu.getMenu().add(Menu.NONE, 12, 12, "English");
    popupMenu.getMenu().add(Menu.NONE, 13, 13, "Esperanto");
    popupMenu.getMenu().add(Menu.NONE, 14, 14, "Spanish");
    popupMenu.getMenu().add(Menu.NONE, 15, 15, "Estonian");
    popupMenu.getMenu().add(Menu.NONE, 16, 16, "Persian");
    popupMenu.getMenu().add(Menu.NONE, 17, 17, "Finnish");
    popupMenu.getMenu().add(Menu.NONE, 18, 18, "French");
    popupMenu.getMenu().add(Menu.NONE, 19, 19, "Irish");
    popupMenu.getMenu().add(Menu.NONE, 20, 20, "Galician");
    popupMenu.getMenu().add(Menu.NONE, 21, 21, "Gujarati");
    popupMenu.getMenu().add(Menu.NONE, 22, 22, "Hebrew");
    popupMenu.getMenu().add(Menu.NONE, 23, 23, "Hindi");
    popupMenu.getMenu().add(Menu.NONE, 24, 24, "Croatian");
    popupMenu.getMenu().add(Menu.NONE, 25, 25, "Haitian");
    popupMenu.getMenu().add(Menu.NONE, 26, 26, "Hungarian");
    popupMenu.getMenu().add(Menu.NONE, 27, 27, "Indonesian");
    popupMenu.getMenu().add(Menu.NONE, 28, 28, "Icelandic");
    popupMenu.getMenu().add(Menu.NONE, 29, 29, "Italian");
    popupMenu.getMenu().add(Menu.NONE, 30, 30, "Japanese");
    popupMenu.getMenu().add(Menu.NONE, 31, 31, "Georgian");
    popupMenu.getMenu().add(Menu.NONE, 32, 32, "Kannada");
    popupMenu.getMenu().add(Menu.NONE, 33, 33, "Korean");
    popupMenu.getMenu().add(Menu.NONE, 34, 34, "Lithuanian");
    popupMenu.getMenu().add(Menu.NONE, 35, 35, "Latvian");
    popupMenu.getMenu().add(Menu.NONE, 36, 36, "Macedonian");
    popupMenu.getMenu().add(Menu.NONE, 37, 37, "Marathi");
    popupMenu.getMenu().add(Menu.NONE, 38, 38, "Malay");
    popupMenu.getMenu().add(Menu.NONE, 39, 39, "Maltese");
    popupMenu.getMenu().add(Menu.NONE, 40, 40, "Dutch");
    popupMenu.getMenu().add(Menu.NONE, 41, 41, "Norwegian");
    popupMenu.getMenu().add(Menu.NONE, 42, 42, "Polish");
    popupMenu.getMenu().add(Menu.NONE, 43, 43, "Portuguese");
    popupMenu.getMenu().add(Menu.NONE, 44, 44, "Romanian");
    popupMenu.getMenu().add(Menu.NONE, 45, 45, "Russian");
    popupMenu.getMenu().add(Menu.NONE, 46, 46, "Slovak");
    popupMenu.getMenu().add(Menu.NONE, 47, 47, "Slovenian");
    popupMenu.getMenu().add(Menu.NONE, 48, 48, "Albanian");
    popupMenu.getMenu().add(Menu.NONE, 49, 49, "Swedish");
    popupMenu.getMenu().add(Menu.NONE, 50, 50, "Swahili");
    popupMenu.getMenu().add(Menu.NONE, 51, 51, "Tamil");
    popupMenu.getMenu().add(Menu.NONE, 52, 52, "Telugu");
    popupMenu.getMenu().add(Menu.NONE, 53, 53, "Thai");
    popupMenu.getMenu().add(Menu.NONE, 54, 54, "Tagalog");
    popupMenu.getMenu().add(Menu.NONE, 55, 55, "Turkish");
    popupMenu.getMenu().add(Menu.NONE, 56, 56, "Ukrainian");
    popupMenu.getMenu().add(Menu.NONE, 57, 57, "Urdu");
    popupMenu.getMenu().add(Menu.NONE, 58, 58, "Vietnamese");
    popupMenu.getMenu().add(Menu.NONE, 59, 59, "Chinese");

    popupMenu.show();

    // 新增:限制PopupMenu最大高度为50dp
    try {
        // 将50dp转换为像素
        int maxHeightPx = (int) TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP,
                50,
                getContext().getResources().getDisplayMetrics()
        );
        // 通过反射获取PopupMenu的ListView
        Field mPopupField = PopupMenu.class.getDeclaredField("mPopup");
        mPopupField.setAccessible(true);
        Object mPopup = mPopupField.get(popupMenu);
        Field mListViewField = mPopup.getClass().getDeclaredField("mListView");
        mListViewField.setAccessible(true);
        ListView listView = (ListView) mListViewField.get(mPopup);
        // 设置最大高度
        listView.setMaxHeight(maxHeightPx);
    } catch (NoSuchFieldException | IllegalAccessException e) {
        e.printStackTrace();
    }

    // 原有点击事件逻辑不变
    popupMenu.setOnMenuItemClickListener(menuItem -> {
        int id = menuItem.getItemId();

        switch (id) {
            case 1: translateTo = "af"; identifyLanguage(); break; // Afrikaans
            case 2: translateTo = "ar"; identifyLanguage(); break; // Arabic
            case 3: translateTo = "be"; identifyLanguage(); break; // Belarusian
            case 4: translateTo = "bg"; identifyLanguage(); break; // Bulgarian
            case 5: translateTo = "bn"; identifyLanguage(); break; // Bengali
            case 6: translateTo = "ca"; identifyLanguage(); break; // Catalan
            case 7: translateTo = "cs"; identifyLanguage(); break; // Czech
            case 8: translateTo = "cy"; identifyLanguage(); break; // Welsh
            case 9: translateTo = "da"; identifyLanguage(); break; // Danish
            case 10: translateTo = "de"; identifyLanguage(); break; // German
            case 11: translateTo = "el"; identifyLanguage(); break; // Greek
            case 12: translateTo = "en"; identifyLanguage(); break; // English
            case 13: translateTo = "eo"; identifyLanguage(); break; // Esperanto
            case 14: translateTo = "es"; identifyLanguage(); break; // Spanish
            case 15: translateTo = "et"; identifyLanguage(); break; // Estonian
            case 16: translateTo = "fa"; identifyLanguage(); break; // Persian
            case 17: translateTo = "fi"; identifyLanguage(); break; // Finnish
            case 18: translateTo = "fr"; identifyLanguage(); break; // French
            case 19: translateTo = "ga"; identifyLanguage(); break; // Irish
            case 20: translateTo = "gl"; identifyLanguage(); break; // Galician
            case 21: translateTo = "gu"; identifyLanguage(); break; // Gujarati
            case 22: translateTo = "he"; identifyLanguage(); break; // Hebrew
            case 23: translateTo = "hi"; identifyLanguage(); break; // Hindi
            case 24: translateTo = "hr"; identifyLanguage(); break; // Croatian
            case 25: translateTo = "ht"; identifyLanguage(); break; // Haitian
            case 26: translateTo = "hu"; identifyLanguage(); break; // Hungarian
            case 27: translateTo = "id"; identifyLanguage(); break; // Indonesian
            case 28: translateTo = "is"; identifyLanguage(); break; // Icelandic
            case 29: translateTo = "it"; identifyLanguage(); break; // Italian
            case 30: translateTo = "ja"; identifyLanguage(); break; // Japanese
            case 31: translateTo = "ka"; identifyLanguage(); break; // Georgian
            case 32: translateTo = "kn"; identifyLanguage(); break; // Kannada
            case 33: translateTo = "ko"; identifyLanguage(); break; // Korean
            case 34: translateTo = "lt"; identifyLanguage(); break; // Lithuanian
            case 35: translateTo = "lv"; identifyLanguage(); break; // Latvian
            case 36: translateTo = "mk"; identifyLanguage(); break; // Macedonian
            case 37: translateTo = "mr"; identifyLanguage(); break; // Marathi
            case 38: translateTo = "ms"; identifyLanguage(); break; // Malay
            case 39: translateTo = "mt"; identifyLanguage(); break; // Maltese
            case 40: translateTo = "nl"; identifyLanguage(); break; // Dutch
            case 41: translateTo = "no"; identifyLanguage(); break; // Norwegian
            case 42: translateTo = "pl"; identifyLanguage(); break; // Polish
            case 43: translateTo = "pt"; identifyLanguage(); break; // Portuguese
            case 44: translateTo = "ro"; identifyLanguage(); break; // Romanian
            case 45: translateTo = "ru"; identifyLanguage(); break; // Russian
            case 46: translateTo = "sk"; identifyLanguage(); break; // Slovakian
            case 47: translateTo = "sl"; identifyLanguage(); break; // Slovenian
            case 48: translateTo = "sq"; identifyLanguage(); break; // Albanian
            case 49: translateTo = "sv"; identifyLanguage(); break; // Swedish
            case 50: translateTo = "sw"; identifyLanguage(); break; // Swahili
            case 51: translateTo = "ta"; identifyLanguage(); break; // Tamil
            case 52: translateTo = "te"; identifyLanguage(); break; // Telugu
            case 53: translateTo = "th"; identifyLanguage(); break; // Thai
            case 54: translateTo = "tl"; identifyLanguage(); break; // Tagalog
            case 55: translateTo = "tr"; identifyLanguage(); break; // Turkish
            case 56: translateTo = "uk"; identifyLanguage(); break; // Ukrainian
            case 57: translateTo = "ur"; identifyLanguage(); break; // Urdu
            case 58: translateTo = "vi"; identifyLanguage(); break; // Vietnamese
            case 59: translateTo = "zh"; identifyLanguage(); break; // Chinese
        }
        return true;
    });
}

private boolean hasInstallPermission() {
    return ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.REQUEST_INSTALL_PACKAGES) == PackageManager.PERMISSION_GRANTED;
}

注意:反射依赖Android系统内部PopupMenu的实现细节,不同Android版本可能存在字段名差异,建议在目标版本上测试兼容性。

内容的提问来源于stack exchange,提问作者AKD2022

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 05:37:07