【问题标题】:Building a 9 patch drawable at runtime在运行时构建 9 个可绘制的补丁
【发布时间】:2013-05-06 17:46:08
【问题描述】:

我使用 Brian Griffey 提供的优秀 gist(发现 here)成功地在 Android 3.0+ 上运行时构建了一个 9patch 可绘制对象。

基本上我从网络加载原始(无补丁)图形文件,文件名包含我需要使用的 cap 插图,以便相应地缩放图像。然后我将这些值与上面找到的类一起使用,并将图像作为背景应用于各种元素(例如TextViewImageButtonButtonViewGroup 等)。

正如您在此处看到的那样,这非常有效:

但是,在 Android 2.3.x 上运行相同的代码会产生结果:

我查看了 Android 中用于解析 9patch 图像的源代码(herehere),但没有找到让它正常工作的方法。我已经尝试了几乎所有可以尝试的方法,但都无济于事。

据记录,9patch 由每个轴上的三列组成,一列固定,一列可拉伸,一列固定。

希望其他人以前解决过这个问题。

提前致谢。

编辑我只对在 Android 2.3 及更高版本(我最初有 2.x)上复制此行为感兴趣。

EDIT #2 这个要点描述了exactly what I'm trying to do + 源图片:

EDIT #3 图片尺寸为 22px/58px(宽/高),插图为 14/6/14/6(上/左/下/右)。 p>

【问题讨论】:

  • 如何应用生成的9patch?
  • @mr_archano 我使用上面要点中的类,并将匹配我想要显示的图像的可缩放部分的 cap insets 传递给它。这会生成一个NinePatchDrawable,然后我将其设置为TextView 的背景。
  • 好的,我明白了。我只是想知道Drawable.setBounds() 是否与此问题有关。
  • 遗憾的是,情况似乎并非如此。不过感谢您的意见。
  • 也许这个好人知道问题所在:@Brian Griffey。我不知道如何直接向某人提问,但你可以找出答案。

标签: android graphics bytearray nine-patch android-drawable


【解决方案1】:

把我到目前为止发现的所有东西放在一起,然后稍微磨练一下:

  • android 版本之间的Res_png_9patch 结构(字节块进入)似乎没有区别(请参阅http://code.metager.de/source/xref/android),所以这看起来不是原因。

  • 关于九个补丁可绘制对象的其他答案表明,每个区域(尤其是可拉伸区域)至少应为 2x2 像素(如果不是 3x3),但在此范围之外越小越好。

  • 但是,某些字节块的分配方式看起来可以更新。尝试将第 4 个字节设置为 9(我认为是补丁的数量),在末尾再添加 7 个 NO_COLORs 并将其大小移动到 56 + (7 x 4) = 84 字节

    李>

【讨论】:

  • 我已经尝试了几乎所有我想到的组合。该解释的问题在于它没有定义如何标记可拉伸和固定部分(即使我知道它们将始终是 SFSxSFS)。我还比较了通过普通 .9.png 文件加载的同一图像的字节数据和我正在生成的图像,将一个复制到另一个(.9.png 块到生成的版本块)会产生相同的效果。
  • 如果我通过 appt/.9png 正常方法加载图像,它可以正常工作。我添加了一个要点,显示了我的源代码和图像。
  • 我已经添加了图片的尺寸和插图。显示的是“加倍”版本,因此插图应该加倍。
  • 谢谢(链接确实解释了如何定义可拉伸部分,但不容易阅读)。但是,如果我了解您的数字,中间的可拉伸部分的大小为零?
  • 也许我误解了你,但左右都是从左边开始测量的,所以我希望你说的是 14/6/44/16(上/左/下/右)给出 10x30 像素 (wxh) 的中间部分。或者我只是看错了你的意思
【解决方案2】:

更新代码后它对我有用。我认为颜色大小出于某种原因使其不愉快(基于 android 源代码中的 cmets,每个补丁都有一个颜色提示,在这种情况下设置少于部分的数量 9 似乎会导致问题)。我还没有用你的图片测试过。

public static NinePatch createFixedNinePatch(Resources res, Bitmap bitmap, int top, int left, int bottom, int right, String srcName){
    ByteBuffer buffer = getByteBufferFixed(top, left, bottom, right);
    NinePatch patch = new NinePatch(bitmap, buffer.array(), srcName);
    return patch;
}

public static ByteBuffer getByteBufferFixed(int top, int left, int bottom, int right) {
    //Docs check the NinePatchChunkFile
    ByteBuffer buffer = ByteBuffer.allocate(84).order(ByteOrder.nativeOrder());
    //was translated
    buffer.put((byte)0x01);
    //divx size
    buffer.put((byte)0x02);
    //divy size
    buffer.put((byte)0x02);
    //color size
    buffer.put(( byte)0x09);

    //skip
    buffer.putInt(0);
    buffer.putInt(0);

    //padding
    buffer.putInt(0);
    buffer.putInt(0);
    buffer.putInt(0);
    buffer.putInt(0);

    //skip 4 bytes
    buffer.putInt(0);

    buffer.putInt(left);
    buffer.putInt(right);
    buffer.putInt(top);
    buffer.putInt(bottom);
    buffer.putInt(NO_COLOR);
    buffer.putInt(NO_COLOR);
    buffer.putInt(NO_COLOR);
    buffer.putInt(NO_COLOR);
    buffer.putInt(NO_COLOR);
    buffer.putInt(NO_COLOR);
    buffer.putInt(NO_COLOR);
    buffer.putInt(NO_COLOR);
    buffer.putInt(NO_COLOR);
    return buffer;
}

【讨论】:

  • 太好了,太完美了!非常感谢。
  • 谢谢,但是top、left、bottom和right的正确值是多少?目前,我使用 top= bitmapWidth/4,left= bitmapHeight/2,bottom = bitmapWidth - left,right = bitmapHeight- left。背景很好,但内容(按钮中的文本)仍然在图像之外。如何使按钮中的内容进入位图的中间?。
【解决方案3】:

这不是问题的真正答案,而是有用的解决方法...

我一直觉得在运行时处理 9-p​​atch 文件很麻烦。我已经成功地使用 FrameLayouts 和自动调整文本大小来实现我想要的效果。如果您的应用将只使用这个 9 补丁,而不是专门允许用户将其作为图像下载(可以说是一个 android 9 补丁图像生成器),我建议您研究一下。

【讨论】:

  • 谢谢,但用户确实下载了图像,并且需要将其应用于任意大小的元素,所以很遗憾,这在这种情况下不起作用。
【解决方案4】:

看起来使用 9patches 已经在 SO 上进行了深入描述 - Create a NinePatch/NinePatchDrawable in runtime

【讨论】:

  • 这并没有回答我的问题,具体与Android 2.3版本有关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多