android - 如何在 Android 中设置按钮内可绘制矢量的大小?

标签 android xml button vector drawable

对于 Lollipop 之前的设备,Android Studio Vector Assets 工具将矢量可绘制对象转换为 PNG-s,但我得到的 PNG-s 质量非常差,您可以在此处看到:

Converted Vector to PNG

此外,按钮的背景纯色应该是您在左侧看到的浅绿色,但可绘制对象会覆盖它:

<item android:state_checked="true"
    android:drawable="@drawable/show">
    <shape android:shape="rectangle">
        <corners android:bottomRightRadius="8dp"/>
        <solid android:color="@color/waveComponentGreen"/>
    </shape>
</item>

<item android:state_checked="false"
    android:drawable="@drawable/hide">
    <shape android:shape="rectangle">
        <corners android:bottomRightRadius="8dp"/>
        <solid android:color="@color/waveComponentGreen"/>
    </shape>
</item>

drawable 的 xml 是( Material 图标的默认值):

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
<path
    android:fillColor="#FF000000"
    android:pathData="M8.59,16.34l4.58,-4.59 -4.58,-4.59L10,5.75l6,6 -6,6z"/>

我还想通过调整值使图标看起来小一点,我注意到增加视口(viewport)尺寸会减小图标,但我不确定我是否理解原因。

那么:如何使图标和生成的 PNG 看起来更小、更不模糊,并使用资源文件中设置的背景颜色?谢谢。

编辑:我设法通过将它们组合在一个单独的带有图层列表的 xml 文件中来获得带有图标的纯色背景:

<layer-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
    <shape android:shape="rectangle">
        <corners android:bottomRightRadius="10dp"/>
        <solid android:color="@color/waveComponentGreen"/>
    </shape>
</item>
<item android:drawable="@drawable/show"
    android:top="10dp"
    android:bottom="10dp"
    android:left="10dp"
    android:right="10dp"
    />

结果是:

The result of some tweaking

我设法通过增加矢量可绘制对象的宽度和高度来减少模糊。然而,如果没有 android:top|bottom|left|right 标签,drawable 将被拉伸(stretch)到按钮的整个区域。第二个按钮不需要背景纯色,所以我没有使用图层列表标签 => 无法为可绘制对象设置 top|bottom|left|right 边距。
如果我减小按钮尺寸,我所做的就是减小按钮的可点击区域。

我更新的问题是如何在不减小按钮本身大小的情况下设置按钮/切换按钮/单选按钮内可绘制矢量的大小?

更新
我找不到在 API 21 之前的设备上调整矢量可绘制对象大小的方法。因此,我将按钮本身做得更小,并增加了每个按钮的触摸区域。

最佳答案

缩放任何可绘制对象的正确方法是使用 vectorDrawable.setBounds(left,top,right,bottom) , 但不幸的是,这不适用于矢量绘图(为什么是 Google?)。

作为一种解决方法,我加载了我的矢量可绘制对象,将它们转换为位图可绘制对象,这将允许我们在位图可绘制对象上使用 setBounds 方法。请注意,您在此处缩放位图,因此可能会损失一些图像的清晰度。例如,当我需要将我的可绘制对象用作 TextView 或按钮的复合可绘制对象时,我主要使用这些方法。

我最终编写了一个辅助类,它将加载一个矢量可绘制对象并为其设置色调,并返回一个位图可绘制对象,您可以根据需要实际缩放和着色。我已经针对 API 级别 19 到 23 对其进行了测试,它可以正常工作。

不要忘记在您的 build.gradle 中使用 vectorDrawables.useSupportLibrary = true

public class VectorDrawableUtils {

/**
 * Gets a Bitmap from provided Vector Drawable image
 *
 * @param vd VectorDrawable
 * @return Bitmap
 */
public static Optional<Bitmap> createBitmapFromVectorDrawable(final @NonNull Drawable vd) {
    try {
        Bitmap bitmap;
        bitmap = Bitmap.createBitmap(vd.getIntrinsicWidth(), vd.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        vd.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        vd.draw(canvas);
        return Optional.of(bitmap);
    } catch (OutOfMemoryError e) {
        Injector.getDependency(getContext(), IEventTracker.class).logHandledException(e);
        return Optional.empty();
    }
}

/**
 * Loads vector drawable and apply tint color on it.
 */
public static Drawable loadVectorDrawableWithTintColor(final @DrawableRes int vdRes,
                                                       final @ColorRes int clrRes,final Context context) {
    Drawable drawable = ContextCompat.getDrawable(context, vdRes);
    DrawableCompat.setTint(drawable, getContext().getResources().getColor(clrRes));
    return drawable;
}

/**
 * Converts given vector drawable to Bitmap drawable
 */
public static BitmapDrawable convertVectorDrawableToBitmapDrawable(final @NonNull Drawable vd) {
    //it is safe to create empty bitmap drawable from null source
    return new BitmapDrawable(createBitmapFromVectorDrawable(vd).get());
}

/**
 * Loads vector drawable , aplys tint on it and returns a wrapped bitmap drawable.
 * Bitmap drawable can be resized using setBounds method (unlike the VectorDrawable)
 * @param context Requires view context !
 */
public static Drawable loadVectorDrawableWithTint(
        final @DrawableRes int vectorDrawableRes, final @ColorRes int colorRes,final Context context) {
    Drawable vd = VectorDrawableUtils.loadVectorDrawableWithTintColor(vectorDrawableRes,
            colorRes, context);
    final BitmapDrawable bitmapDrawable = VectorDrawableUtils.convertVectorDrawableToBitmapDrawable(vd);
    ColorStateList tint = ContextCompat.getColorStateList(context,colorRes);
    final Drawable wrappedDrawable = DrawableCompat.wrap(bitmapDrawable);
    DrawableCompat.setTintList(wrappedDrawable,tint);
    return wrappedDrawable;
    }
}

现在我会像这样使用这个辅助类:

    Drawable bd = VectorDrawableUtils.loadVectorDrawableWithTint(
                R.drawable.ic_dropdown, R.color.black,getContext());
        bd.setBounds(0, 0, textView.getMeasuredHeight(), textView.getMeasuredHeight());
        textView.setCompoundDrawablesWithIntrinsicBounds(null, null, bd, null);

重要的是使用 View 或 Activity 的上下文,而不是应用程序上下文! 希望它能解决您的问题,或帮助其他人。如果有人有更好更清洁的解决方案,我也很想知道。

关于android - 如何在 Android 中设置按钮内可绘制矢量的大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33691077/

相关文章:

PHP XML 验证在传递错误 XML 时抛出致命异常

android - 删除安卓 : prefix for every attribute

android - 如何知道我的应用程序是否在 Bluestacks 上运行?

android - 如何在 ListView 中添加原生广告?

java - Box2D Android Studio 绘制倒置形状

java - 双击 Android 按钮

java - 多个 if 语句

Android:如何将密码/安全添加到手机的时间/日期设置以防止用户更改它

java - 为什么 hibernate 状态不创建这个我的表?

excel - 在 Excel 中使用 VBA 对运行时添加的命令按钮的引用