背景

.9图来源于Android。为了设计出一套图,兼容Android和iOS,使用.9图的方式来对图片进行拉伸以适应不同的屏幕。在iOS中没有.9图的概念,只能先了解Android的.9图再进行模拟Android的方法。

什么是.9图片

即图片后缀名前有.9的图片,如pic.9.png、pic1.9.jgp,诸如此类的图片就称为.9图片。且在原始图片四周添加了一个像素,在这一个像素上用黑线标识出相关的区域。

.9图片的作用

.9图片的作用是在图片拉伸的时候特定的区域不会发生图片失真,特定的区域就是由.9图边缘一圈像素中的left和top的黑线所决定。

Android中的.9图介绍

.9图其实是在原始图片的四周添加了一个像素,通俗点说就是图片比原始图片扩大了一圈,多出来的那一圈是透明像素。我们需要绘制黑线的地方正是在那一圈透明像素上进行绘制。

如上图所示,在原始图的四周添加了一个圈的透明像素。其中:四周分别命名为L、T、R、B。

绘制在L的区域:用于拉伸的纵向区域。

绘制在T的区域:用于拉伸的横向区域。

绘制在R的区域:用于显示前景的纵向范围。

绘制在B的区域:用于显示前景的横向范围。

举例说明一下,如下图 :

该图的四周添加了相应的黑线。

拉伸区域,如下图:

红色框区域:表示纵向拉伸的区域,也就是说,当图片需要纵向拉伸的时候它会只指定拉伸红色区域,其他区域在纵向是不会拉伸的。

绿色框区域:表示横向拉伸的区域,也就是说,当图片需要横向拉伸的时候它会只指定拉伸绿色区域,其他区域在横向是不会拉伸的。

显然红色和绿色相交的部分是既会进行横向拉伸也会进行纵向拉伸的。

前景的显示区域,如下图:

蓝色区域:表示前景能显示的纵向范围。即前景的最上面可以显示到什么地方,最下面可以显示的什么地方。

黄色区域:表示前景能显示的横向范围。即前景的最左边可以显示到什么地方,最右边可以显示的什么地方。

蓝色和黄色相交部分:表示整个前景能显示的区域。一个区域是矩形的,蓝色规定了上下边界,黄色规定了左右边界,两者共同当然也就规定了一个矩形区域。

在iOS中图片拉伸:

1.在iOS5之前,使用- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight;这个方法进行图片的拉伸。

2.在iOS5之后,使用- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets;

或- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode;这个方法进行图片的拉伸或平铺。

iOS中有个叫端盖(end cap)的概念,用来指定图片中的哪一部分不用拉伸。比如下图中,黑色代表需要被拉伸的矩形区域,上下左右不需要被拉伸的边缘就称为端盖。

如上所述,在iOS中想要拉伸图片,就得确定要被拉伸的区域,而这个区域是由top、left、bottom、right四个方向的值所决定的区域,这部分的概念与Android中的.9图是不太一样的,但拉伸的区域概念差不太多。

了解了以上概念,我们就可以在iOS中模拟Android处理.9图的拉伸模式。

我们使用了一个第三方库:LVNinePatchImage进行.9图的处理。因为原始图片四周添加了一像素的透明。而只有黑线的alpha值是为1的,其余部分都是透明的则alpha值为0。通过这种逻辑关系就能找到对应的左边和上边的黑线区域位置。然后通过iOS系统提供的拉伸方法进行图片的拉伸操作。

该库主要主要做的事有:

1.通过类方法+ (unsigned char*)getRGBAsFromImage:(UIImage*)image count:(NSInteger)count;来获取图片的所有像素点的RGB值包括Alpha值。

2.通过方法 inline static CGFloat getImageAphaAtPoint(const unsigned char* rawData, NSInteger width, NSInteger height , NSInteger pointX, NSInteger pointY);去找出pointX到pointY之间像素点的Alpha值。

如当pointY始终为0,pointX从1到图片的宽度,就能找出图片顶部一像素的所有alpha值。当pointX始终为0,pointY从1到图片的高度,就能找出图片左边一像素的所有alpha值。

3.然后遍历找到的顶部和左边的alpha数组值,当alpha为1的连续区域就是黑线的所在位置。

4.然后调用方法+ (UIImage*)crop:(CGRect)r image0:(UIImage*)image0;裁剪掉图片四周的一像素区域,只保留中间正确(最原始)的图片。

5.最后再根据黑线的所在位置,算出top、left、bottom、right端盖的值,调用- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets;方法进行图片的拉伸或平铺。

参考链接

http://blog.csdn.net/shimiso/article/details/41079847

http://www.cnblogs.com/mjios/archive/2013/02/26/2934280.html

iOS 中使用.9图的更多相关文章

  1. iOS中 轮播图放哪最合适? 技术分享

    我们知道,轮播图放在cell或collectionViewCell上会影响用户层级交互事件,并且实现起来比较麻烦,现在推出一个技术点:答题思路是:将UIScrollView放在UIView或UICol ...

  2. iOS中 动态启动图GIF的简单设置 韩俊强的博客

    // 设定位置和大小 CGRect frame = CGRectMake(50,340,[UIScreen mainScreen].bounds.size.width / 2,[UIScreen ma ...

  3. 解决iOS中 tabBarItem设置图片(image+title切图在一起)时造成的图片向上偏移

    解决iOS中 tabBarItem设置图片(image+title切图在一起)时造成的图片向上偏移 解决办法1:设置tabBarItem的imageInsets属性 代码示例: childContro ...

  4. iOS中数据库应用基础

    iOS 数据库入门 一.数据库简介 1.什么是数据库? 数据库(Database) 是按照数据结构来组织,存储和管理数据的仓库 数据库可以分为2大种类 关系型数据库(主流) PC端 Oracle My ...

  5. iOS开发——高级篇——iOS中常见的设计模式(MVC/单例/委托/观察者)

    关于设计模式这个问题,在网上也找过一些资料,下面是我自己总结的,分享给大家 如果你刚接触设计模式,我们有好消息告诉你!首先,多亏了Cocoa的构建方式,你已经使用了许多的设计模式以及被鼓励的最佳实践. ...

  6. iOS 图片轮播图(自动滚动)

    iOS 图片轮播图(自动滚动) #import "DDViewController.h" #define DDImageCount 5 @interface DDViewContr ...

  7. (转)如何处理iOS中照片的方向

    如何处理iOS中照片的方向 31 May 2015 • 7 min. read • Comments 使用过iPhone或者iPad的朋友在拍照时不知是否遇到过这样的问题,将设备中的照片导出到Wind ...

  8. iOS中的存储方式

    1.Plist 1.1 了解沙盒 每个iOS应用都有自己的应用沙盒(应用沙盒就是文件系统目录),与其它文件系统隔离.应用必须呆在自己的沙盒里.其它应用不能访问该沙盒. 一个程序中所有的非代码文件都可以 ...

  9. 浅谈iOS中的userAgent

    浅谈iOS中的userAgent   User-Agent(用户代理)字符串是Web浏览器用于声明自身型号版本并随HTTP请求发送给Web服务器的字符串,在Web服务器上可以获取到该字符串. 在公司产 ...

随机推荐

  1. 通过history.pushState无刷新改变url

    通过history.pushState无刷新改变url 背景 在浏览器中改变地址栏url,将会触发页面资源的重新加载,这使得我们可以在不同的页面间进行跳转,得以浏览不同的内容.但随着单页应用的增多,越 ...

  2. Linux(ubuntu)下安装JDK、Tomcat

    一.安装jdk 1)首先以root用户登录进去,在根目录下建立opt的目录,我们将下载的东西都放到该目录下去. 2)下载j2sdk ,如jdk-6u31-linux-i586.bin 下载地址如下ht ...

  3. HDU 5690 All X 暴力循环节

    分析:暴力找循环节就好了 #include <iostream> #include <cstdio> #include <cstdlib> #include < ...

  4. Max Sub-matrix

    Max Sub-matrix 教练找的题目,目前样列过了 题意:找子矩阵的最大周长 思路:先离散每列,再枚举列(n*n),在当前枚举的两列之间求每行的和(n*n*n),但是开两个数组,一个包含两列上的 ...

  5. 【VMware虚拟机】【克隆问题】在VMware 9.0下克隆CentOS6.5虚拟机无法识别eth网卡

    [日期]2014年4月23日 [平台]windows 8 vmware workstation 9.0 centos 6.5 [日志]1)执行ifconfig命令,输出: 2)查看/etc/udev/ ...

  6. HDU-4418 Time travel 概率DP,高斯消元

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4418 题意:简单来说就是给你1个环(n - 1 , n - 2 …… 0 ,1 , 2 , 3 …… ...

  7. iOS CAShapeLayer精讲

    前言 CAShapeLayer继承自CALayer,因此,可使用CALayer的所有属性.但是,CAShapeLayer需要和贝塞尔曲线配合使用才有意义. 关于UIBezierPath,请阅读文章:i ...

  8. SQL Server 2016原生支持JSON

    转载原地址: http://www.cnblogs.com/lyhabc/p/4747694.html SQL Server 2005 开始支持 XML 数据类型,提供原生的 XML数据类型.XML ...

  9. (原创)vagrant up 异常报错,出现 There was an error while executing `VBoxManage` 的解决方法

    最近在使用 vagrant homestead 时,不小心在虚拟机上使用了 exit 命令退出虚拟机,导致再使用 vagrant up 时出现以下错误: Bringing machine 'larav ...

  10. Android的事件处理

    1 android事件处理概述 不论是桌面应用还是手机应用程序,面对最多的就是用户,经常需要处理用户的动作-------也就是需要为用户动作提供响应,这种为用户动作提供响应的机制就是事件处理.andr ...