Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/201.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android NinePatchDrawable无法从区块中获取填充_Android_Drawable_Padding_Nine Patch - Fatal编程技术网

Android NinePatchDrawable无法从区块中获取填充

Android NinePatchDrawable无法从区块中获取填充,android,drawable,padding,nine-patch,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

我需要有关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已经编译,这意味着它们包含所需的块

我将位图转换为NinePatchDrawable对象的方式似乎很有效,因为图像和我绘制的一样可以拉伸

唯一不起作用的是填充物。我已尝试将填充设置为视图,如下所示:

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)应该用从块中得到的填充填充变量rect,不是吗?但事实并非如此

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


感谢阅读。

我从来没有见过这样一个例子:9-patch中没有包含
填充

要做到这一点,您应该首先构造一个图形,然后创建一个可从中绘制的图形:

NinePatch ninePatch = new NinePatch(bitmap, chunk, srcName);
NinePatchDrawable d = new NinePatchDrawable(res, ninePatch);
但是,您似乎正在使用一个空矩形来构建可绘制图形:

NinePatchDrawable d = new NinePatchDrawable(getResources(), bubble, chunk, new Rect(), null);
如果要以编程方式指定填充,请尝试以下操作:

Rect paddingRectangle = new Rect(left, top, right, bottom);
NinePatchDrawable d = new NinePatchDrawable(getResources(), bubble, chunk, paddingRectangle, null);

最后,我做到了。Android没有正确解释区块数据。可能有虫子。因此,您必须自己反序列化块以获取填充数据

我们开始:

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;
    }
}
它将完美地工作

实际上比这稍微复杂一点,但归结起来很简单:

padding rect由返回。没有任何版本的
decodeByteArray()
可以返回padding rect

整个九个补丁API有点傻:

  • decodeByteArray()
    调用
    nativeDecodeByteArray()
    ,这可能比
    ByteArrayInputStream上的
    nativeDecodeStream()
    更有效,但显然,开发人员从未期望您要从内存中解码九个补丁
  • padding rect仅由九个补丁使用,因此将其作为
    NinePatch
    的一部分而不是
    BitmapFactory
    更有意义。遗憾的是,它只不过是一个将位图和九个补丁块传递给绘图方法的包装器(而且由于调用
    mRect.set(location)
    ,大多数
    NinePatch.draw()
    调用都不是线程安全的)
  • 不提供获取
    NinePatch
    和padding rect的方法,这使得
    NinePatch
    在应用程序代码中有些无用(除非您想自己填充)。没有
    NinePatchDrawable.getNinePatch()
    NinePatch.getBitmap()
总结得很好:

啊。我们已经分配了
decodeStream
合同 pad rect,但如果位图没有ninepatch块, 然后,pad将被忽略。如果我们能把它改成懒洋洋的 alloc/分配rect,我们可以避免生成新的
Rect
s只能将它们扔到地板上

我的解决方法相当简单:

public final class NinePatchWrapper {
  private final Bitmap mBitmap;
  private final Rect mPadding;
  /**
  * The caller must ensure that that bitmap and padding are not modified after
  * this method returns. We could copy them, but Bitmap.createBitmap(Bitmap)
  * does not copy the nine-patch chunk on some Android versions.
  */
  public NinePatchWrapper(Bitmap bitmap, Rect padding) {
    mBitmap = bitmap;
    mPadding = padding;
  }
  public NinePatchDrawable newDrawable(Resources resources) {
    return new NinePatchDrawable(mBitmap, mBitmap.getNinePatchChunk(), mPadding, null);
  }
}

...

public NinePatchWrapper decodeNinePatch(byte[] byteArray, int density) {
  Rect padding = new Rect();
  ByteArrayInputStream stream = new ByteArrayInputStream(byteArray);
  Bitmap bitmap = BitmapFactory.decodeStream(stream, padding, null);
  bitmap.setDensity(density);
  return new NinePatchWrapper(bitmap, padding);
}

未经测试,因为它大大简化了。特别是,您可能需要检查“九块补丁”是否有效。

参加聚会有点晚,但以下是我解决问题的方法:

我使用
NinePatchDrawable
提供的解码器方法,它正确读取填充:

     var myDrawable = NinePatchDrawable.createFromStream(sr, null);

但我的问题是:如何从图像本身获取左、上、右和下变量?第一个示例演示如何正确填充NinePatchDrawable以在块中包含填充。一旦构造完成,您就可以执行getPadding(rect),第一个示例应该执行该操作。构造NinePatch,然后从该NinePatch绘制NinePatch
getPadding()
然后应该返回正确的值。您可以发布视图的9修补程序和xml吗?视图没有xml。这是一个通过编程创建的文本视图,作为表格行附加到表格中。在b.android.com上提出问题,同时提及使用的设备和android版本。对不起,看到答案我太兴奋了,我忘了投票。接受你自己的答案也是完全可以接受的:)我从来没有想到这个bug在API中。谢谢这是最简单的方法,我试过了,效果很好~
     var myDrawable = NinePatchDrawable.createFromStream(sr, null);