如何为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
相关产品推荐
相关产品推荐

