访问Drawable资源的宽和高

本文介绍了一种通过BitmapFactory从资源中加载Drawable,并获取其宽度和高度的方法。在Android应用中,利用Bitmap对象的getHeight()和getWidth()方法可以轻松地读取图片资源的实际尺寸。
/*
 * 访问Drawable资源的宽和高
 * 程序通过Bitmap对象的BitmapFactoryResource()方法来取得Import和
 * Drawable的图片文件,在通过Bitmap的对象的getHeight()和getWidth()
 * 取得Drawable的宽高。
 */
import 略;
public class Ex07_01Activity extends Activity {
	private TextView mTextView;
	private ImageView mImageView;

	protected static final int CONTEXT_ITEM1 = Menu.FIRST;
	protected static final int CONTEXT_ITEM2 = Menu.FIRST + 1;
	protected static final int CONTEXT_ITEM3 = Menu.FIRST + 2;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		mTextView = (TextView) findViewById(R.id.myTextView1);
		mImageView = (ImageView) findViewById(R.id.myImageView1);

		mImageView
				.setImageDrawable(getResources().getDrawable(R.drawable.baby));
		mImageView
				.setOnCreateContextMenuListener(new ListView.OnCreateContextMenuListener() {

					@Override
					public void onCreateContextMenu(ContextMenu menu, View v,
							ContextMenuInfo menuInfo) {
						// TODO Auto-generated method stub
						menu.add(Menu.NONE, CONTEXT_ITEM1, 0,
								R.string.str_context1);
						menu.add(Menu.NONE, CONTEXT_ITEM2, 0,
								R.string.str_context2);
						menu.add(Menu.NONE, CONTEXT_ITEM3, 0,
								R.string.str_context3);
					}
				});
	}

	// 重写OnContextItemSeldcted来定义用户单击后的动作
	public boolean onContextItemSelected(MenuItem item) {
		Bitmap myBitmap = BitmapFactory.decodeResource(getResources(),
				R.drawable.baby);
		int intHeight = myBitmap.getHeight();
		int intWidth = myBitmap.getWidth();

		try {
			switch (item.getItemId()) {
			case CONTEXT_ITEM1:
				String strOpt = getResources().getString(R.string.str_width)
						+ "=" + Integer.toString(intWidth);
				mTextView.setText(strOpt);
				break;
			case CONTEXT_ITEM2:
				String strOpt2 = getResources().getString(R.string.str_height)
						+ "=" + Integer.toString(intHeight);
				mTextView.setText(strOpt2);
				break;
			case CONTEXT_ITEM3:
				String strOpt3 = getResources().getString(R.string.str_width)
						+ "=" + Integer.toString(intWidth) + "\n"
						+ getResources().getString(R.string.str_height) + "="
						+ Integer.toString(intHeight);
				mTextView.setText(strOpt3);
				break;
			default:
				break;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return super.onContextItemSelected(item);
	}
}

布局文件很简单,在这里我就不再详述了,下面我们来看看程序的运行结果:
<think> 我们正在处理一个Android开发问题:如何设置PopupMenu的固定宽。 根据引用[1]:用户尝试通过修改style.xml中的minWidth和dropDownWidth属性来更改PopupMenu宽度,但没有成功。用户怀疑可能是由于ListMenuItemView的硬编码属性导致。 引用[2]:提供了Android菜单类型的概述,并指出PopupMenu在Android3.0之后才有支持。 引用[3]:提到了overlapAnchor属性可以改变菜单弹出的位置,但用户提到修改距离时遇到了问题。 目标:设定PopupMenu的固定宽。 分析: 1. PopupMenu的宽度默认是包裹内容(wrap_content),度是自适应。但有时内容过长会导致宽度过大,或者我们希望固定一个宽度。 2. 由于PopupMenu内部使用ListView来显示菜单项,因此我们可以尝试通过设置ListView的宽度来调整PopupMenu的宽度。但是,PopupMenu并没有直接提供设置宽的方法。 解决方案思路: 方案一:使用反射来修改PopupMenu的内部ListView的宽度(不推荐,因为反射可能在不同版本上失效,且不安全)。 方案二:自定义PopupMenu,通过继承PopupMenu并重写某些方法,或者通过获取其内部的ListView并设置宽。 方案三:使用PopupWindow替代PopupMenu,因为PopupWindow可以更自由地控制宽。 但是,用户明确要求使用PopupMenu,因此我们重点考虑如何修改PopupMenu的宽。 步骤: 1. 创建PopupMenu。 2. 通过反射获取PopupMenu内部的ListView(因为PopupMenu内部使用ListView来显示菜单项)。 3. 设置ListView的宽。 然而,设置度可能会出现问题,因为菜单项的度由每个菜单项的度和数量决定。通常,我们更关注宽度。 代码示例(设置宽度): ```java // 创建PopupMenu PopupMenu popupMenu = new PopupMenu(context, anchorView); // 设置菜单(例如通过菜单资源) popupMenu.getMenuInflater().inflate(R.menu.popup_menu, popupMenu.getMenu()); // 显示PopupMenu popupMenu.show(); try { // 获取PopupMenu的内部变量mPopup Field field = popupMenu.getClass().getDeclaredField("mPopup"); field.setAccessible(true); Object menuPopupHelper = field.get(popupMenu); // 获取mPopup的内部变量mPopup Class<?> classPopupHelper = Class.forName("com.android.internal.view.menu.MenuPopupHelper"); Field mPopupField = classPopupHelper.getDeclaredField("mPopup"); mPopupField.setAccessible(true); Object menuPopup = mPopupField.get(menuPopupHelper); // 检查menuPopup的类型,应该是com.android.internal.view.menu.MenuPopup Class<?> menuPopupClass = menuPopup.getClass().getSuperclass().getSuperclass(); // 设置弹出窗口的宽度(这里设置为固定值300px) Field widthField = menuPopupClass.getDeclaredField("mDropDownWidth"); widthField.setAccessible(true); widthField.set(menuPopup, 300); // 设置宽度 } catch (Exception e) { e.printStackTrace(); } ``` 注意:这个方法使用了反射,并且访问了内部类,这在不同Android版本上可能会有变化,因此需要谨慎使用。 另一种方法(设置度): 度通常由菜单项数量决定,如果一定要固定度,可能还需要设置ListView的度。但这样可能会导致显示不全,所以通常不建议固定度,而是通过控制菜单项数量来间接控制度。 另外,引用[3]提到了overlapAnchor属性,这个属性可以调整弹出位置,但不能直接改变宽。 由于PopupMenu本身设计上并不支持直接设置宽,所以如果需求是固定宽,建议使用PopupWindow自定义视图,这样更灵活。 但是,如果坚持使用PopupMenu,上述反射方法可以设置宽度,但度设置可能比较复杂(因为需要调整ListView的度,而ListView的度由其内容决定)。 因此,我们给出两种方案: 方案一:使用反射设置PopupMenu的宽度(度不建议设置,因为菜单项的度是自适应的)。 方案二:使用PopupWindow自定义视图,这样可以完全控制宽。 下面给出PopupWindow的示例: 步骤: 1. 创建一个布局(例如popup_layout.xml)用于显示菜单项。 2. 创建PopupWindow,设置宽和视图。 3. 设置菜单项的点击事件。 代码示例(PopupWindow): ```java // 创建布局 LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View popupView = inflater.inflate(R.layout.popup_layout, null); // 设置宽 int width = 300; // 固定宽度 int height = 400; // 固定度 PopupWindow popupWindow = new PopupWindow(popupView, width, height, true); // 设置背景等 popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); popupWindow.setOutsideTouchable(true); // 显示PopupWindow popupWindow.showAsDropDown(anchorView); // 在popupView中设置菜单项点击事件 popupView.findViewById(R.id.menu_item1).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 处理点击 popupWindow.dismiss(); } }); // ...其他菜单项 ``` 总结: 如果必须使用PopupMenu且只需要设置宽度,可以尝试反射方法(注意版本兼容性)。 如果需要同时设置宽,建议使用PopupWindow。 §§相关问题§§ 1. 除了反射,还有其他方法可以修改PopupMenu的宽度吗? 2. 如何自定义PopupMenu的样式(比如背景、文字颜色等)? 3. PopupMenu和PopupWindow有什么区别?各自适用什么场景? </think> 在 Android 中设置 `PopupMenu` 的固定宽需要特殊处理,因为其默认行为是自适应内容尺寸且不直接提供宽度/度属性。以下是两种可靠方法: --- ### 方法 1:通过反射强制修改宽度(推荐) 使用反射访问 `PopupMenu` 内部类 `MenuPopupHelper` 来设置宽度: ```java // 创建 PopupMenu PopupMenu popupMenu = new PopupMenu(context, anchorView); popupMenu.getMenuInflater().inflate(R.menu.popup_menu, popupMenu.getMenu()); try { // 获取 MenuPopupHelper 实例 Field mPopupField = PopupMenu.class.getDeclaredField("mPopup"); mPopupField.setAccessible(true); Object menuPopupHelper = mPopupField.get(popupMenu); // 设置固定宽度 (单位: px) int fixedWidth = 300; Class<?> popupHelperClass = Class.forName("android.widget.MenuPopupHelper"); Field mPopupFieldHelper = popupHelperClass.getDeclaredField("mPopup"); mPopupFieldHelper.setAccessible(true); Object listPopupWindow = mPopupFieldHelper.get(menuPopupHelper); // 修改 ListPopupWindow 的宽度 Method setWidthMethod = listPopupWindow.getClass().getDeclaredMethod("setWidth", int.class); setWidthMethod.invoke(listPopupWindow, fixedWidth); } catch (Exception e) { e.printStackTrace(); } popupMenu.show(); // 显示菜单 ``` > **注意**: > - 反射可能因 Android 版本失效,需测试目标系统兼容性 > - 通过 `dpToPx()` 工具方法将 dp 值转为 px --- ### 方法 2:自定义 PopupWindow 替代方案 若需同时控制宽,建议改用 `PopupWindow`: ```java // 自定义布局 (popup_layout.xml) LayoutInflater inflater = LayoutInflater.from(context); View menuView = inflater.inflate(R.layout.popup_layout, null); // 设置固定宽 int width = ViewGroup.LayoutParams.WRAP_CONTENT; // 或固定值 int height = 400; // 固定度(px) PopupWindow popupWindow = new PopupWindow(menuView, width, height, true); // 显示在锚点视图下方 popupWindow.showAsDropDown(anchorView); ``` 优势: - 完全控制宽和布局 - 避免反射兼容性问题 - 可自定义背景/动画等属性 --- ### 关键说明 1. **宽限制原因** `PopupMenu` 内部使用 `ListPopupWindow` 实现,其宽度由 `MeasureSpec` 动态计算且未开放 API 修改[^1]。 > *"我开始怀疑是否可以覆盖 ListMenuItemView 的这个硬编码属性"* [^1] 2. **样式覆盖限制** 在 `styles.xml` 中设置 `android:dropDownWidth` 或 `minWidth` 对 `PopupMenu` 无效,因其属于系统级 `Menu` 实现[^2]。 3. **版本兼容性** `PopupMenu` 仅支持 Android 3.0+ (API 11+),低版本需使用 `OptionMenu` 或自定义方案[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值