如何获取Android Drawable中定义的宽高尺寸?
获取GradientDrawable中XML定义的Size尺寸
你可以通过以下几种方式获取shape Drawable中<size>标签定义的宽高:
方法一:利用intrinsicWidth/intrinsicHeight(推荐)
GradientDrawable的intrinsicWidth和intrinsicHeight方法会直接返回<size>标签定义的尺寸(单位为像素),你可以再转换为dp:
val drawable: GradientDrawable = getDrawable(R.drawable.small) as GradientDrawable val widthPx = drawable.intrinsicWidth val heightPx = drawable.intrinsicHeight // 将像素转换为dp val displayMetrics = resources.displayMetrics val widthDp = (widthPx / displayMetrics.density).toInt() val heightDp = (heightPx / displayMetrics.density).toInt()
注意:如果shape没有定义<size>,这两个方法会返回-1,需要做判空处理。
方法二:直接解析原始XML资源文件
如果需要直接获取XML中写的dp数值(不经过像素转换),可以直接解析Drawable的XML资源:
val resId = R.drawable.small val parser = resources.getXml(resId) var widthDp = 0 var heightDp = 0 try { var eventType = parser.eventType while (eventType != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_TAG && parser.name == "size") { // 提取width和height的dp值 widthDp = parser.getAttributeValue(null, "android:width")?.removeSuffix("dp")?.toInt() ?: 0 heightDp = parser.getAttributeValue(null, "android:height")?.removeSuffix("dp")?.toInt() ?: 0 break // 找到size标签后退出循环 } eventType = parser.next() } } catch (e: Exception) { e.printStackTrace() }
方法三:反射获取内部字段(不推荐)
GradientDrawable内部会存储尺寸信息,但不同Android版本的字段名可能有变化,反射方式兼容性较差:
try { val drawable: GradientDrawable = getDrawable(R.drawable.small) as GradientDrawable // 反射获取mWidth和mHeight字段(像素值) val widthField = GradientDrawable::class.java.getDeclaredField("mWidth") widthField.isAccessible = true val widthPx = widthField.getInt(drawable) val heightField = GradientDrawable::class.java.getDeclaredField("mHeight") heightField.isAccessible = true val heightPx = heightField.getInt(drawable) // 转换为dp val displayMetrics = resources.displayMetrics val widthDp = (widthPx / displayMetrics.density).toInt() val heightDp = (heightPx / displayMetrics.density).toInt() } catch (e: NoSuchFieldException) { // 适配不同版本的字段名,比如部分版本用mSize数组 try { val sizeField = GradientDrawable::class.java.getDeclaredField("mSize") sizeField.isAccessible = true val size = sizeField.get(drawable) as IntArray val widthPx = size[0] val heightPx = size[1] val displayMetrics = resources.displayMetrics val widthDp = (widthPx / displayMetrics.density).toInt() val heightDp = (heightPx / displayMetrics.density).toInt() } catch (ex: Exception) { ex.printStackTrace() } } catch (e: IllegalAccessException) { e.printStackTrace() }
内容的提问来源于stack exchange,提问作者user1332148
相关产品推荐
相关产品推荐

