有什么规定限制了 ShapeDrawables 在 ActionBar 上的渲染吗?
没有这样的规定。只是事情就是这样。以下是你看到这种情况的原因:
Layer/ShapeDrawables 没有默认大小。换句话说,一个 ShapeDrawable 宽度和高度都为零是完全可以的。边框宽度参数也无法影响任何内容。
当我将此代码作为 Button 或 ImageButton 的背景时,代码可以正常工作,但当我将其作为 ActionBar 项的图标添加时,该项目不会显示。
当然可以。ImageButtons/Buttons 有填充、最小宽度和最小高度的概念。这些允许 ShapeDrawable 有一些空间来呼吸。例如,使用 Widget.Holo.Button 样式的按钮将设置 minWidth 和 minHeight:
<item name="android:minHeight">48dip</item>
<item name="android:minWidth">64dip</item>
一个有效的测试如下:
定义一个如下所示的ImageView:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/add" />
</RelativeLayout>
ImageView
在上面的定义中没有尺寸指导,我们使用
wrap_content
。什么也不会显示。另一方面,如果您使用png drawable,则它本身定义了大小。在上面的示例中,使用显式大小(例如50dp)将使
ShapeDrawable
visible
。
这是
ActionMenuItemView
设置drawable的方式:
public void setIcon(Drawable icon) {
mIcon = icon;
if (icon != null) {
int width = icon.getIntrinsicWidth();
int height = icon.getIntrinsicHeight();
if (width > mMaxIconSize) {
final float scale = (float) mMaxIconSize / width;
width = mMaxIconSize;
height *= scale;
}
if (height > mMaxIconSize) {
final float scale = (float) mMaxIconSize / height;
height = mMaxIconSize;
width *= scale;
}
icon.setBounds(0, 0, width, height);
}
setCompoundDrawables(icon, null, null, null);
updateTextButtonVisibility();
}
ShapeDrawable#inflate(...)
方法的片段:
setIntrinsicWidth((int)
a.getDimension(com.android.internal.R.styleable.ShapeDrawable_width, 0f));
setIntrinsicHeight((int)
a.getDimension(com.android.internal.R.styleable.ShapeDrawable_height, 0f));
没有定义
ShapeDrawable_width
和
ShapeDrawable_height
,就会使固有宽度和高度设置为零。这意味着从
setIcon(Drawable)
方法中的语句
icon.setBounds(0, 0, width, height);
实际上是
icon.setBounds(0, 0, 0, 0);
。
因此,看起来我们确实要处理没有大小信息的
ShapeDrawables
。
一种可能的解决方法:
<shape android:shape="line">
<size android:width="?android:attr/actionBarSize"
android:height="?android:attr/actionBarSize"/>
<stroke android:color="#000"
android:width="3dp"/>
</shape>
但这样做行不通 - 出于某种原因,
?android:attr/actionBarSize
不被视为尺寸。这很奇怪,因为在布局的情况下,
?android:attr/actionBarSize
在提供给
android:layout_width
时可以正常工作。
解决方法是定义一个新的尺寸,比如
actionBarSizeDp
并设置它:
在
res/values/dimens.xml
中:
<dimen name="actionBarSizeDp">48dp</dimen>
在
res/values-land/dimens.xml
文件中:
<dimen name="actionBarSizeDp">40dp</dimen>
这些值是在Android自己的res/values-XX/dimens.xml中定义的默认操作栏大小值。
最后,在plus_icon_drawable.xml中使用actionBarSizeDp:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="line">
<size android:width="@dimen/actionBarSizeDp"
android:height="@dimen/actionBarSizeDp"/>
<stroke android:color="#000"
android:width="3dp"/>
</shape>
</item>
<item>
<rotate
android:fromDegrees="90"
android:toDegrees="90">
<size android:width="@dimen/actionBarSizeDp"
android:height="@dimen/actionBarSizeDp"/>
<shape android:shape="line">
<stroke android:color="#000"
android:width="3dp"/>
</shape>
</rotate>
</item>
</layer-list>
事实上,只需在其中一个LayerDrawables中定义size即可。其他图层会相应地进行绘制。