NinePatchDrawable does not get padding from chunk

后端 未结 4 1417
鱼传尺愫
鱼传尺愫 2021-02-06 03:59

I need help with NinePatchDrawable:

My app can download themes from the network. Almost all things work fine, except 9-Patch PNGs.

final Bitmap bubble =          


        
4条回答
  •  伪装坚强ぢ
    2021-02-06 04:49

    Finally, I did it. Android wasn't interpreting the chunk data correctly. There might be bug. So you have to deserialize the chunk yourself to get the padding data.

    Here we go:

    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;
        }
    }
    

    Use the class above as following:

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

    And it will work perfectly!

提交回复
热议问题