android - NinePatchDrawable 不从 block 中获取填充

标签 android drawable padding nine-patch

我需要有关 NinePatchDrawable 的帮助:

我的应用可以从网络下载主题。 除了 9-Patch PNG 之外,几乎所有东西都可以正常工作。

final Bitmap bubble = getFromTheme("bubble");
if (bubble == null) return null;

final byte[] chunk = bubble.getNinePatchChunk();
if (!NinePatch.isNinePatchChunk(chunk)) return null;

NinePatchDrawable d = new NinePatchDrawable(getResources(), bubble, chunk, new Rect(), null);
v.setBackgroundDrawable(d);

d = null;
System.gc();

getFromTheme() 从 SD 卡加载位图。 9-Patch PNG 已编译,这意味着它们包含所需的 block 。

我将位图转换为 NinePatchDrawable 对象的方式似乎可行,因为图像和我绘制的一样可拉伸(stretch)。

唯一不起作用的是填充。我已经尝试将填充设置为这样的 View :

final Rect rect = new Rect();   // or just use the new Rect() set
d.getPadding(rect);             // in the constructor
v.setPadding(rect.left, rect.top, rect.right, rect.bottom);

d.getPadding(rect) 应该用从 block 中获得的填充填充变量 rect,不是吗?但事实并非如此。

结果:TextView (v) 不显示 9-Patch 图像内容区域中的文本。每个坐标中的填充都设置为 0。

感谢阅读。

最佳答案

我终于做到了。 Android 没有正确解释 block 数据。可能有bug。所以你必须自己反序列化 block 来获取填充数据。

开始吧:

package com.dragonwork.example;

import android.graphics.Rect;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

class NinePatchChunk {

    public static final int NO_COLOR = 0x00000001;
    public static final int TRANSPARENT_COLOR = 0x00000000;

    public final Rect mPaddings = new Rect();

    public int mDivX[];
    public int mDivY[];
    public int mColor[];

    private static void readIntArray(final int[] data, final ByteBuffer buffer) {
        for (int i = 0, n = data.length; i < n; ++i)
            data[i] = buffer.getInt();
    }

    private static void checkDivCount(final int length) {
        if (length == 0 || (length & 0x01) != 0)
            throw new RuntimeException("invalid nine-patch: " + length);
    }

    public static NinePatchChunk deserialize(final byte[] data) {
        final ByteBuffer byteBuffer =
            ByteBuffer.wrap(data).order(ByteOrder.nativeOrder());

        if (byteBuffer.get() == 0) return null; // is not serialized

        final NinePatchChunk chunk = new NinePatchChunk();
        chunk.mDivX = new int[byteBuffer.get()];
        chunk.mDivY = new int[byteBuffer.get()];
        chunk.mColor = new int[byteBuffer.get()];

        checkDivCount(chunk.mDivX.length);
        checkDivCount(chunk.mDivY.length);

        // skip 8 bytes
        byteBuffer.getInt();
        byteBuffer.getInt();

        chunk.mPaddings.left = byteBuffer.getInt();
        chunk.mPaddings.right = byteBuffer.getInt();
        chunk.mPaddings.top = byteBuffer.getInt();
        chunk.mPaddings.bottom = byteBuffer.getInt();

        // skip 4 bytes
        byteBuffer.getInt();

        readIntArray(chunk.mDivX, byteBuffer);
        readIntArray(chunk.mDivY, byteBuffer);
        readIntArray(chunk.mColor, byteBuffer);

        return chunk;
    }
}

按如下方式使用上面的类:

final byte[] chunk = bitmap.getNinePatchChunk();
if (NinePatch.isNinePatchChunk(chunk)) {
    textView.setBackgroundDrawable(new NinePatchDrawable(getResources(),
          bitmap, chunk, NinePatchChunk.deserialize(chunk).mPaddings, null));
}

它会完美地工作!

关于android - NinePatchDrawable 不从 block 中获取填充,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11065996/

相关文章:

android - 在带有文本的按钮中缩放 drawableLeft

android - Drawable 不将格式应用于我的按钮

android - 有没有办法使用 XML 设置可绘制的 Alpha?

c# - 如何避免 Winforms 中 ToolStrip 左侧出现 3 个像素间隙?

android - 从单独的 myJavaClass.java 完成 Activity()

android - cordova android 应用程序中预填充的 sqlite 数据库问题

html - CSS 侧边栏背景色全宽

css - 图像在边框和填充后悬停时跳转

android - 找不到 Gradle DSL 方法 : 'classpath()'

android - 塑造 Android Material Design