精华内容
下载资源
问答
  • 点九图制作软件

    2018-08-14 23:05:45
    非常好的一款点九图制作工具,简单实用,可视化,欢迎下载。
  • 仿聊天点九图两个发送和收到一个是白色的一个是绿色的,自己用过的
  • 点九图切图工具

    2013-12-09 18:11:59
    点九的切图工具可以很快的制作点九图
  • 这一块是对点九图的简单介绍,如果对这块已经有了解的话,可以直接跳到2,看看聊天气泡中如何使用点九图。首先简单介绍下点九图出现的原因吧,Android为了使用同一张图作为不同数量文字的背景,设计了一种可以指定...
  • 文章目录RecyclerView布局 – 根据不同类型加载布局Ⅰ.创建底部输入框、按钮、RecyclerView可复用组件,Ⅱ.新建RecyclerView模板,用于存储数据1. 在res-layout中新建一个布局资源文件 `item_receive.xml`2....
  • 点九图Demo

    2016-05-06 11:46:07
    Android点九图的简单分析
  • 点九图简介 Android为了使用同一张图作为不同数量文字的背景,设计了一种可以指定区域拉伸的图片格式“.9.png”,这种图片格式就是点九图。 注意:这种图片格式只能被使用于Android开发。在ios开发中,可以在代码中...

    点九图简介

    Android为了使用同一张图作为不同数量文字的背景,设计了一种可以指定区域拉伸的图片格式“.9.png”,这种图片格式就是点九图。

    注意:这种图片格式只能被使用于Android开发。在ios开发中,可以在代码中指定某个点进行拉伸,而在Android中不行,所以在Android中想要达到这个效果,只能使用点九图(下文会啪啪打脸,其实是可以的,只是很少人这样使用,兼容性不知道怎么样,点击跳转

    点九图实质

    点九图的本质实际上是在图片的四周各增加了1px的像素,并使用纯黑(#FF000000)的线进行标记,其它的与原图没有任何区别。可以参考以下图片:

    标记位置含义
    左-黑点纵向拉伸区域
    上-黑点横向拉伸区域
    右-黑线纵向显示区域
    下-黑线横向显示区域

    点九图在 Android 中的应用

    点九图在 Android 中主要有三种应用方式

    1. 直接放在 res 目录中的 drawable 或者 mipmap 目录中
    2. 放在 assert 目录中
    3. 从网络下载

    第一种方式是我们最常用的,直接调用 setBackgroundResource 或者 setImageResource 方法,这样的话图片及可以做到自动拉伸。

    而对于第二种或者第三种方式,如果我们直接去加载 .9.png,你会发现图片或者图片背景根本无法拉伸。纳尼,这是为甚么呢。下面,且听老衲慢慢道来。

    Android 并不是直接使用点九图,而是在编译时将其转换为另外一种格式,这种格式是将其四周的黑色像素保存至Bitmap类中的一个名为 mNinePatchChunk 的 byte[] 中,并抹除掉四周的这一个像素的宽度;接着在使用时,如果 Bitmap 的这个 mNinePatchChunk 不为空,且为 9patch chunk,则将其构造为 NinePatchDrawable,否则将会被构造为 BitmapDrawable,最终设置给 view。

    因此,在 Android 中,我们如果想动态使用网络下载的点九图,一般需要经过以下步骤:

    1. 使用 sdk 目录下的 aapt 工具将点九图转化为 png 图片
    2. 解析图片的时候,判断是否含有 NinePatchChunk,有的话,转化为 NinePatchDrawable
    public static void setNineImagePatch(View view, File file, String url) {
        if (file.exists()) {
            Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
            byte[] chunk = bitmap.getNinePatchChunk();
            if (NinePatch.isNinePatchChunk(chunk)) {
                NinePatchDrawable patchy = new NinePatchDrawable(view.getResources(), bitmap, chunk, new Rect(), null);
                view.setBackground(patchy);
            }
            
        }
    }
    

    点九图上传服务器流程


    aapt 转换命令

    单个图片文件转换

    ./aapt s -i xxx.9.png -o xxx.png
    

    批量转换

    # 批量转换
    ./aapt c -S inputDir -C outputDir
    # inputDir 为原始.9图文件夹,outputDir 为输出文件夹
    

    执行成功实例

    jundeMacBook-Pro:一期气泡 junxu$ ./aapt c -S /Users/junxu/Desktop/一期气泡/气泡需求整理 -C /Users/junxu/Desktop/一期气泡/output 
    Crunching PNG Files in source dir: /Users/junxu/Desktop/一期气泡/气泡需求整理
    To destination dir: /Users/junxu/Desktop/一期气泡/output
    

    注意:

    若不是标准的点九图,在转换的过程会报错,这时候请设计重新提供新的点九图


    实际开发当中遇到的问题

    小屏手机适配问题

    刚开始,我们的切图是按照 2 倍图切的,这样在小屏幕手机上会手机气泡高度过大的问题。

    原因分析:

    该现象的本质是点九图图片的高度大于单行文本消息的高度。

    解决方案一(暂时不可取):

    1. 我尝试去压缩点九图,但最终再部分手机上面显示错乱,不知道是不是压缩点九图的方法错了。

    解决方案二

    对于低分辨率的手机和高分辨的手机分别下发不同的图片 url,我们尝试过得方案是当 density < 2 的时候,采用一倍图图片,density >= 2 采用二倍图图片。

    解决方案三

    可能有人会有这样的疑问呢,为什么要采用一倍图,两倍图的解决方案呢?直接让 UI 设计师给一套图,点九图图片的高度适中不就解决了。是啊,我们也是这样想得,但他们说对于有一些装饰的点九图,如果缩小高度,一些装饰图案他们不太好切。比如下面图片中的星星。

    小结

    说到底,方案二,方案三其实都是折中的一种方案,如果直接能够做到点九图缩放,那就完美解决了。而 Android 中 res 目录中的 drawable 或者 mipmap 的点九图确实能做到,去看了相关的代码,目前也没有发现什么好的解决方案,如果你有好的解决方案话,欢迎留言交流。

    点九图的 padding 在部分手机上面失效

    这个是部分 Android 手机的 bug,解决方法见:https://stackoverflow.com/questions/11065996/ninepatchdrawable-does-not-get-padding-from-chunk

    public class NinePatchChunk {
    
        private static final String TAG = "NinePatchChunk";
    
        public final Rect mPaddings = new Rect();
    
        public int mDivX[];
        public int mDivY[];
        public int mColor[];
    
        private static float density = IMO.getInstance().getResources().getDisplayMetrics().density;
    
        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 IllegalStateException("invalid nine-patch: " + length);
        }
    
        public static Rect getPaddingRect(final byte[] data) {
            NinePatchChunk deserialize = deserialize(data);
            if (deserialize == null) {
                return new Rect();
            }
        }
    
        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()];
    
            try {
                checkDivCount(chunk.mDivX.length);
                checkDivCount(chunk.mDivY.length);
            } catch (Exception e) {
                return null;
            }
    
    
            // 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;
        }
    }
    
    NinePatchDrawable patchy = new NinePatchDrawable(view.getResources(), bitmap, chunk, NinePatchChunk.getPaddingRect(chunk), null);
    view.setBackground(patchy);
    
    
    

    动态下载点九图会导致聊天气泡闪烁

    1. 这里我们采取的方案是预下载(预下载 10 个)
    2. 聊天气泡采用内存缓存,磁盘缓存,确保 RecyclerView 快速滑动的时候不会闪烁

    理解点九图

    以下内容参考腾讯音乐的 Android动态布局入门及NinePatchChunk解密

    回顾NinePatchDrawable的构造方法第三个参数bitmap.getNinePatchChunk(),作者猜想,aapt命令其实就是在bitmap图片中,加入了NinePatchChunk的信息,那么我们是不是只要能自己构造出这个东西,就可以让任何图片按照我们想要的方式拉升了呢?

    可是查了一堆官方文档,似乎并找不到相应的方法来获得这个byte[]类型的chunk参数。

    既然无法知道这个chunk如何生成,那么能不能从解析的角度逆向得出这个NinePatchChunk的生成方法呢?

    下面就需要从源码入手了。

    NinePatchChunk.java

    public static NinePatchChunk deserialize(byte[] data) {
        ByteBuffer byteBuffer =
                ByteBuffer.wrap(data).order(ByteOrder.nativeOrder());
        byte wasSerialized = byteBuffer.get();
        if (wasSerialized == 0) return null;
        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;
    }
    

    其实从这部分解析byte[] chunk的源码,我们已经可以反推出来大概的结构了。如下图,

    按照上图中的猜想以及对.9.png的认识,直觉感受到,mDivX,mDivY,mColor这三个数组是最关键的,但是具体是什么,就要继续看源码了。

    ResourceTypes.h

    /**
     * This chunk specifies how to split an image into segments for
     * scaling.
     *
     * There are J horizontal and K vertical segments.  These segments divide
     * the image into J*K regions as follows (where J=4 and K=3):
     *
     *      F0   S0    F1     S1
     *   +-----+----+------+-------+
     * S2|  0  |  1 |  2   |   3   |
     *   +-----+----+------+-------+
     *   |     |    |      |       |
     *   |     |    |      |       |
     * F2|  4  |  5 |  6   |   7   |
     *   |     |    |      |       |
     *   |     |    |      |       |
     *   +-----+----+------+-------+
     * S3|  8  |  9 |  10  |   11  |
     *   +-----+----+------+-------+
     *
     * Each horizontal and vertical segment is considered to by either
     * stretchable (marked by the Sx labels) or fixed (marked by the Fy
     * labels), in the horizontal or vertical axis, respectively. In the
     * above example, the first is horizontal segment (F0) is fixed, the
     * next is stretchable and then they continue to alternate. Note that
     * the segment list for each axis can begin or end with a stretchable
     * or fixed segment.
     * /
    

    正如源码中,注释的一样,这个NinePatch Chunk把图片从x轴和y轴分成若干个区域,F区域代表了固定,S区域代表了拉伸。mDivX,mDivY描述了所有S区域的位置起始,而mColor描述了,各个Segment的颜色,通常情况下,赋值为源码中定义的NO_COLOR = 0x00000001就行了。就以源码注释中的例子来说,mDivX,mDivY,mColor如下:

    mDivX = [ S0.start, S0.end, S1.start, S1.end];
    mDivY = [ S2.start, S2.end, S3.start, S3.end];
    mColor = [c[0],c[1],...,c[11]]
    

    对于mColor这个数组,长度等于划分的区域数,是用来描述各个区域的颜色的,而如果我们这个只是描述了一个bitmap的拉伸方式的话,是不需要颜色的,即源码中NO_COLOR = 0x00000001

    说了这么多,我们还是通过一个简单例子来说明如何构造一个按中心点拉伸的 NinePatchDrawable 吧,

    Bitmap bitmap = BitmapFactory.decodeFile(filepath);
    int[] xRegions = new int[]{bitmap.getWidth() / 2, bitmap.getWidth() / 2 + 1};
    int[] yRegions = new int[]{bitmap.getWidth() / 2, bitmap.getWidth() / 2 + 1};
    int NO_COLOR = 0x00000001;
    int colorSize = 9;
    int bufferSize = xRegions.length * 4 + yRegions.length * 4 + colorSize * 4 + 32;
    
    ByteBuffer byteBuffer = ByteBuffer.allocate(bufferSize).order(ByteOrder.nativeOrder());
    // 第一个byte,要不等于0
    byteBuffer.put((byte) 1);
    
    //mDivX length
    byteBuffer.put((byte) 2);
    //mDivY length
    byteBuffer.put((byte) 2);
    //mColors length
    byteBuffer.put((byte) colorSize);
    
    //skip
    byteBuffer.putInt(0);
    byteBuffer.putInt(0);
    
    //padding 先设为0
    byteBuffer.putInt(0);
    byteBuffer.putInt(0);
    byteBuffer.putInt(0);
    byteBuffer.putInt(0);
    
    //skip
    byteBuffer.putInt(0);
    
    // mDivX
    byteBuffer.putInt(xRegions[0]);
    byteBuffer.putInt(xRegions[1]);
    
    // mDivY
    byteBuffer.putInt(yRegions[0]);
    byteBuffer.putInt(yRegions[1]);
    
    // mColors
    for (int i = 0; i < colorSize; i++) {
        byteBuffer.putInt(NO_COLOR);
    }
    
    return byteBuffer.array();
    

    create-a-ninepatch-ninepatchdrawable-in-runtime

    在 stackoverflow 上面也找到牛逼的类,可以动态创建点九图,并拉伸图片,啪啪打脸,刚开始说到 android 中无法想 ios 一样动态指定图片拉伸区域。

    public class NinePatchBuilder {
        int width, height;
        Bitmap bitmap;
        Resources resources;
        private ArrayList<Integer> xRegions = new ArrayList<Integer>();
        private ArrayList<Integer> yRegions = new ArrayList<Integer>();
    
        public NinePatchBuilder(Resources resources, Bitmap bitmap) {
            width = bitmap.getWidth();
            height = bitmap.getHeight();
            this.bitmap = bitmap;
            this.resources = resources;
        }
    
        public NinePatchBuilder(int width, int height) {
            this.width = width;
            this.height = height;
        }
    
        public NinePatchBuilder addXRegion(int x, int width) {
            xRegions.add(x);
            xRegions.add(x + width);
            return this;
        }
    
        public NinePatchBuilder addXRegionPoints(int x1, int x2) {
            xRegions.add(x1);
            xRegions.add(x2);
            return this;
        }
    
        public NinePatchBuilder addXRegion(float xPercent, float widthPercent) {
            int xtmp = (int) (xPercent * this.width);
            xRegions.add(xtmp);
            xRegions.add(xtmp + (int) (widthPercent * this.width));
            return this;
        }
    
        public NinePatchBuilder addXRegionPoints(float x1Percent, float x2Percent) {
            xRegions.add((int) (x1Percent * this.width));
            xRegions.add((int) (x2Percent * this.width));
            return this;
        }
    
        public NinePatchBuilder addXCenteredRegion(int width) {
            int x = (int) ((this.width - width) / 2);
            xRegions.add(x);
            xRegions.add(x + width);
            return this;
        }
    
        public NinePatchBuilder addXCenteredRegion(float widthPercent) {
            int width = (int) (widthPercent * this.width);
            int x = (int) ((this.width - width) / 2);
            xRegions.add(x);
            xRegions.add(x + width);
            return this;
        }
    
        public NinePatchBuilder addYRegion(int y, int height) {
            yRegions.add(y);
            yRegions.add(y + height);
            return this;
        }
    
        public NinePatchBuilder addYRegionPoints(int y1, int y2) {
            yRegions.add(y1);
            yRegions.add(y2);
            return this;
        }
    
        public NinePatchBuilder addYRegion(float yPercent, float heightPercent) {
            int ytmp = (int) (yPercent * this.height);
            yRegions.add(ytmp);
            yRegions.add(ytmp + (int) (heightPercent * this.height));
            return this;
        }
    
        public NinePatchBuilder addYRegionPoints(float y1Percent, float y2Percent) {
            yRegions.add((int) (y1Percent * this.height));
            yRegions.add((int) (y2Percent * this.height));
            return this;
        }
    
        public NinePatchBuilder addYCenteredRegion(int height) {
            int y = (int) ((this.height - height) / 2);
            yRegions.add(y);
            yRegions.add(y + height);
            return this;
        }
    
        public NinePatchBuilder addYCenteredRegion(float heightPercent) {
            int height = (int) (heightPercent * this.height);
            int y = (int) ((this.height - height) / 2);
            yRegions.add(y);
            yRegions.add(y + height);
            return this;
        }
    
        public byte[] buildChunk() {
            if (xRegions.size() == 0) {
                xRegions.add(0);
                xRegions.add(width);
            }
            if (yRegions.size() == 0) {
                yRegions.add(0);
                yRegions.add(height);
            }
         
            int NO_COLOR = 1;//0x00000001;
            int COLOR_SIZE = 9;//could change, may be 2 or 6 or 15 - but has no effect on output
            int arraySize = 1 + 2 + 4 + 1 + xRegions.size() + yRegions.size() + COLOR_SIZE;
            ByteBuffer byteBuffer = ByteBuffer.allocate(arraySize * 4).order(ByteOrder.nativeOrder());
            byteBuffer.put((byte) 1);//was translated
            byteBuffer.put((byte) xRegions.size());//divisions x
            byteBuffer.put((byte) yRegions.size());//divisions y
            byteBuffer.put((byte) COLOR_SIZE);//color size
    
            //skip
            byteBuffer.putInt(0);
            byteBuffer.putInt(0);
    
            //padding -- always 0 -- left right top bottom
            byteBuffer.putInt(0);
            byteBuffer.putInt(0);
            byteBuffer.putInt(0);
            byteBuffer.putInt(0);
    
            //skip
            byteBuffer.putInt(0);
    
            for (int rx : xRegions)
                byteBuffer.putInt(rx); // regions left right left right ...
            for (int ry : yRegions)
                byteBuffer.putInt(ry);// regions top bottom top bottom ...
    
            for (int i = 0; i < COLOR_SIZE; i++)
                byteBuffer.putInt(NO_COLOR);
    
            return byteBuffer.array();
        }
    
        public NinePatch buildNinePatch() {
            byte[] chunk = buildChunk();
            if (bitmap != null)
                return new NinePatch(bitmap, chunk, null);
            return null;
        }
    
        public NinePatchDrawable build() {
            NinePatch ninePatch = buildNinePatch();
            if (ninePatch != null)
                return new NinePatchDrawable(resources, ninePatch);
            return null;
        }
    }
    
    

    运行一下测试代码

    mLlRoot = findViewById(R.id.ll_root);
    try {
        InputStream is = getAssets().open("sea.png");
        Bitmap bitmap = BitmapFactory.decodeStream(is);
        for (int i = 0; i < 5; i++) {
            NinePatchDrawable ninePatchDrawable = NinePatchHelper.buildMulti(this, bitmap);
            TextView textView = new TextView(this);
            textView.setTextSize(25);
            textView.setPadding(20, 10, 20, 10);
            textView.setText(strArray[i]);
            textView.setGravity(Gravity.CENTER_VERTICAL);
            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            layoutParams.leftMargin = 20;
            layoutParams.rightMargin = 20;
            textView.setLayoutParams(layoutParams);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                textView.setBackground(ninePatchDrawable);
            }
            mLlRoot.addView(textView);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    
    
    

    可以看到,我们的图片完美拉伸


    参考文章

    1. https://cloud.tencent.com/developer/article/1168755?
    2. https://mp.weixin.qq.com/s?__biz=MzI1NjEwMTM4OA==&mid=2651232105&idx=1&sn=fcc4fa956f329f839f2a04793e7dd3b9&mpshare=1&scene=21&srcid=0719Nyt7J8hsr4iYwOjVPXQE#wechat_redirect

    推荐阅读

    责任链模式以及在 Android 中的应用

    观察者设计模式 Vs 事件委托(java)

    装饰者模式及其应用

    建造者模式(Builder)及其应用

    二次封装图片第三方框架——简单工厂模式的运用

    Android 二次封装网络加载框架

    java 代理模式详解

    Rxjava 2.x 源码系列 - 基础框架分析

    Rxjava 2.x 源码系列 - 线程切换 (上)

    Rxjava 2.x 源码系列 - 线程切换 (下)

    Rxjava 2.x 源码系列 - 变换操作符 Map(上)

    butterknife 源码分析

    一步步拆解 LeakCanary

    java 源码系列 - 带你读懂 Reference 和 ReferenceQueue

    扫一扫,欢迎关注我的微信公众号 stormjun94(徐公码字), 目前是一名程序员,不仅分享 Android开发相关知识,同时还分享技术人成长历程,包括个人总结,职场经验,面试经验等,希望能让你少走一点弯路。

    展开全文
  • 搞懂点九图看这一篇就够了。 内容简介 你真的了解android的点九图吗?读完这一篇,再来回答这个问题,废话少说,先看看本文要讲的主要内容: 点九图简介 下图是一张android系统中的典型点九...

    搞懂点九图看这一篇就够了。

     

    Image title

     

    内容简介

     

    你真的了解android的点九图吗?读完这一篇,再来回答这个问题,废话少说,先看看本文要讲的主要内容:

     

    Image title

     

     

    点九图简介

     

    下图是一张android系统中的典型点九切图,先来了解下点九图的结构,文章接下来

    还会对每个结构做详细的介绍。

     

    Image title

     

    制作点九图有四个硬性要求,只要满足这四点,点九图就可以被正确识别。

    要求一:
    名称格式必须为:文件名称.9.png。

    要求二:
    上下左右各留有1px的标识线区,此区内不能有半透明像素(特别注意:切图若有投影,不要泄漏到标识线区)。

    要求三:
    伸缩标识线与内间距标识线为不透明的纯黑色(#000000),光学标识线为不透明的纯红色(#ff0000)。

    要求四:
    点九图的特殊结构会导致其4个顶角处成为“绝对禁区”,这4个1像素×1像素的区域内不能有任何内容。

     

    Image title

     

     

    伸缩线详解

     

    伸缩线标注了切图内的拉伸区域/收缩区域。一般来说点九图越小越好,因此通常切图尺寸都要小于控件尺寸,但这并不意味着不会出现切图尺寸大于控件尺寸的情况,在这种情况下,切图会根据伸缩线来进行缩小。

    下图中,左侧为测试所用的三色点九图,右侧为测试程序的展示效果,从实验的结果得到三个结论:

    1.切图拉伸时,仅伸缩区会被拉伸。
    2.切图收缩时,首先伸缩区会被收缩。
    3.当伸缩区缩小到0之后,切图整体继续收缩
    (Android 4.3之前表现不同,谷歌公布的Android系统9月份的月度版本分布图数据显示4.3之前的机型占比不足7%,所以可忽略此情况)

     

    Image title

     

    伸缩线支持多段标注,可以同时拉伸/缩放切图中的多个不相邻区域。从下图的实验结果可以得出一个结论:

     

    每个区域的拉伸/放缩长度与本区的伸缩标识线长度成正比。

     

    Image title

     

    纵向的伸缩标识线原理和横向伸缩标识线的原理一致,就不再赘述。

     

     

    内间距线详解

     

    关于内间距线,很多人有所误解。因为内间距线所标注的是控件的内间距,而不是点九图的内间距,所以,内间距线跟点九图本身并没有直接的联系。

    观察下面的点九图,这个点九图的横向伸缩线与横向内间距线没有重叠。那么,这张图可以正常显示吗?

     

    Image title

     

    如下图所示,将点九图设置为TextView的背景,首先,切图的拉伸区是正确的,再观察右侧的标注图,可以得出如下结论:

    1.横向内间距线的左端到切图左端的距离为控件的左侧内间距值;
    2.横向内间距线的右端到切图右端的距离为控件的右侧内间距值。

    (纵向内间距线原理同上)

     

    Image title

     

    虽然内间距线也可以画为多段,但是系统只关心最左端和最右端的位置,所以多段内间距线是没有任何意义的。

     

    点九图中的内间距线,仅在代码中没有指定Padding属性的时候才会生效,但这不代表可以忽略点九图中的内间距线。切图都会被多次复用,很可能因为开发的疏忽在某些布局中忘记指定Padding属性,点九图中的内间距线是切图被正确显示的最后一道保障。

     

    Image title

     

     

    光学边界线详解

     

    Optical bounds layout(光学边界布局)是在Android 4.3(Api level 18)中引入的一种新的布局对齐方式。

    光学边界也叫做视觉边界,下图是一个带有投影的蓝色按钮切图。在视觉上,此图形的外轮廓是蓝色按钮所占区域,而不是切图实际所占区域。光学边界线标注的位置为投影的位置,表示此区域在视觉上不可察觉。

     

    Image title

     

    光学边界会导致布局结构复杂化,而且可以实现的视觉效果也有限,大家稍作了解就好,技术成熟的时候再深究不迟。

    下图中,左侧是开启光学边界的效果,右侧是未开启光学边界的效果。

     

    Image title

     

     

    官方工具:draw9patch

     

    为了方便大家检测点九图是否正确,我将谷歌在开发平台中提供的draw9patch工具进行了打包:

    1.包括Mac和Win两个版本。
    2.绿色软件,无需安装。
    3.自带Java环境,双击直接运行。
    4.无广告、无病毒、永久免费。

    draw9patch工具使用很简单,就不多做讲解了。

     

    UI设计科学派公众号中回复“点九图”获得最软件新版本的下载链接。

     

    Image title

    展开全文
  • UI给我的设计图(关键词:点九图) 4个顶角的尺寸是58px*58px,目前中间的那部分尺寸也是58px,其实中间尺寸>1px就可以了,最好留点安全距离,以便拉伸的时候不会影响到4个角。 我使用css border-image属性...

    前提

    UI做的一个页面的设计图,主体内容背景是一个八边形,加四个不规则顶角边框。

    实现思路

    宽、高固定,那就简单了,直接让UI给出一个固定宽高的背景.png就好了。

    宽、高不固定,可以参考聊天气泡框实现原理,4个顶角是固定的,将中间的纯背景进行拉伸。

    UI给我的设计图(关键词:点九图)

    4个顶角的尺寸是58px*58px,目前中间的那部分尺寸也是58px,其实中间尺寸>1px就可以了,最好留点安全距离,以便拉伸的时候不会影响到4个角。 

    我使用css border-image属性完成拉伸效果,实现效果图如下:

    局部代码

    <template>
      <div class="content-box"></div>
    </template>
    
    <style lang="scss" scoped>
    .content-box {
      width: 1024px;
      min-height: 600px;
      border: 58px solid transparent;
      box-sizing: border-box;
      -moz-border-image: url("~@/assets/install/biankuang.png") 58 58 stretch; /* Old Firefox */
      -webkit-border-image: url("~@/assets/install/biankuang.png") 58 58 stretch; /* Safari and Chrome */
      -o-border-image: url("~@/assets/install/biankuang.png") 58 58 stretch; /* Opera */
      border-image: url("~@/assets/install/biankuang.png") 58 58 fill repeat stretch;
    }
    </style>

    参考博客:

    border-image 的正确用法_凹凸实验室-CSDN博客

    展开全文
  • 在线制作点九图

    2020-08-12 21:05:31
    制作地址:http://romannurik.github.io/AndroidAssetStudio/nine-patches.html#&sourceDensity=320&name=example
    展开全文
  • 【Android】点九图

    2019-08-19 12:20:33
    注意,对话框图片边缘至少要保留1PX空白间距,留给画黑线()。 1.拉伸区域(左上):拉伸图片的宽高 当指定了对话框的宽高的数值时,横向拉伸区域和纵向拉伸区域就会被拉伸成指定的高和宽。 当没有指定对话框的宽高...
  • Android点九图的简单分析.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
  • 点九图

    2017-03-17 19:38:00
    9图:以.9.png为后缀名命名的图片,其中 上边界和左边界的划线 是负责拉伸扩展, 下边界和右边界划线 则控制内容区域。所以 .9 图不允许右侧和下边界有两条划线,而左边界和上边界则没有问题。 上述问题是由于...
  • 点九图的制作方法

    千次阅读 2017-09-12 21:34:33
    首先,我们来了解一下什么是9图? 9图就是安卓系统或ios系统内的一种可拉抻而不失真的图, 9图是把图中某些部分进行拉伸,而不想拉伸的部分,比如圆角等部分不做变化。 下面就我就以聊天气泡为例: 首先来...
  • 我们都知道点九图的作用,这里就不多说了,反正就是各种好各种美如画,这次我们把点九图用到自定义控件中。我们用drawBitmap来绘制点九图,然而似乎有点问题。
  • 点九图的制作

    2021-10-18 09:39:39
    1、参考资源 https://www.sohu.com/a/208634499_505826 ... 2、有关注意事项 1、左边和上边的黑线画的越长就拉伸的越长,在android studio 中制作时,只能描点,不然会提示错误区域。 /2、ps制作的点九图
  • 答案是:使用 点九图(xxx.9.png) 代替那些随着分辨率需要拉伸改变、或者随着程序运行需要改变的图片,可以避免变形、模糊失真等不良效果! 使用点九图的优势: 拉伸效果:在Android平台下使用点九PNG技术,可以将...
  • 制作点九图

    千次阅读 2018-09-04 11:21:40
    安卓UI设计基础教程: 什么是点九图,怎么切点九图 【Android】9-patch图片以及例子说明 看完你就懂了!超详细解说点9切图的制作方法(内附神器) http://www.ui.cn/detail/161745.html  编辑工具:draw9patch....
  • 今天项目中有用到点九图,就是背景同一张图片,不同情况拉伸时,背景图片均不会变形,类似于微信聊天的背景,先看看成品图 好了,首先制作一张九图片,顺序即图片(我用eclipse软件敲代码) 第一步:打开SDK...
  • 建议写成UIImage的分类,如下 .h //保证图片拉伸不变形 - (UIImage *)resizingImageState; .m //保证图片拉伸不变形 - (UIImage *)resizingImageState { CGFloat imageW = self... CGFloat imageH = ...
  • 点九图简单介绍 什么是点九图 点九图是安卓系统中特有的一种图片格式,件名以”.9.png“结尾。 点九图的作用 这种图片能告诉程序,图像哪一部分可以被拉升,哪一部分不能被拉升需要保持原有比例。运用点九图...
  • 安卓开发之点九图

    2021-06-01 09:34:33
    Nine-Patch图 xxx.9.png 口诀:左上进行拉伸,右下进行显示。
  • 点九图学习与制作

    2020-10-29 19:10:56
    项目中一直有使用点九图,但是没咋接触,现在跟着大佬的blog来学习一下点九图的制作。 1. 点九图概述 1.1 点九图是什么? Android平台里有一种特殊的图片形式,文件扩展名 xxx.9.png,为了方便记忆,所以称其为...
  • 点九图简单介绍及制作教程

    千次阅读 2016-06-30 23:20:56
    Android开发中用到的一种特殊格式的图片,文件名以”.9.png...运用点九图可以保证图片在不模糊变形的前提下做到自适应。点九图常用于对话框背景图片中。 这是截屏自手机QQ一组聊天对话框,可以看
  • 点九图制作方法

    2019-09-24 06:20:18
    点九图,是Android开发中用到的一种特殊格式的图片,文件名以”.9.png“结尾。这种图片能告诉程序,图像哪一部分可以被拉升,哪一部分不能被拉升需要保持原有比列。运用点九图可以保证图片在不模糊变形的前提下做到...
  • Android studio生成点九图与webp图

    千次阅读 2018-09-10 20:07:20
    在弹出菜单的倒数第二个选项可以看到生成点九图的选项。 点击确定之后即生成了点九图 在弹出菜单的最后一项是生成webp图片的选项,可以点击生成webp格式的图片。 webp格式的图片的优势在:...
  • 点九图介绍点九图,是Android开发中用到的一种特殊格式的图片,文件名以”.9.png“结尾。这种图片能告诉程序,图像哪一部分可以被拉升,哪一部分不能被拉升需要保持原有比列。运用点九图可以保证图片在不模糊变形的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 796
精华内容 318
关键字:

点九图