使用多个可拉伸图片创建UIImage

4

我有3个图片,一个左侧帽子,一个右侧帽子和一个中心部分。也许可以使用CGImageRefs(?),基于CGRect构建一个位图,将中心部分居中放置在某个容器中,将左侧帽子拉伸到达中心部分,并对右侧帽子执行相同的操作,然后产生一个UIImage


为什么不使用一张图片呢? - Pfitz
中心部件有一个箭头,无法拉伸。最终图像是一个地图注释气泡,需要具有可伸缩的宽度。 - Chris
没错。我现在正在尝试Gabriele的解决方案,看它是否按照我想的那样工作。 - Chris
@chris 我想我在一本书中有关于这个的代码。但是这本书现在不在这里。如果这个问题还没有解决,我稍后会查找它。 - Pfitz
@Chris,有一件事情让我困扰:既然你不拉伸大写字母和内部图像,那么你想要做什么来实现灵活性呢?在大写字母和箭头图像之间添加一个额外的部分吗? - Pfitz
显示剩余4条评论
3个回答

6

好的,我按照承诺查找了解决方案。以下是解决方案:

基本思路

  • 使用拉伸右侧的左侧帽创建一个UIImage
  • 将其与箭头UIImage“粘合”
  • 现在使用左侧拉伸的右侧来粘合它与右侧帽子

下面是一个小图形,展示了我的想法。

  ______ ........    ________      .........___________
 {______|........|  | arrow  |    |.........|__________)
left cap|lc flex     --------      rc flex  | right cap

代码

// get the images from disk
UIImage *leftCap = [UIImage imageNamed:@"leftCap.png"];
UIImage *arrow = [UIImage imageNamed:@"arrow.png"];
UIImage *rightCap = [UIImage imageNamed:@"rightCap"];

// stretch left and right cap
// calculate the edge insets beforehand !

UIImage *leftCapStretched = [leftCap resizableImageWithCapInsets:UIEdgeInsetsMake(topInset, leftInset, bottomInset, rightInset)];
UIImage *rightCapStretched = [rightCap resizableImageWithCapInsets:UIEdgeInsetsMake(topInset, leftInset, bottomInset, rightInset)];

CGFloat widthOfAllImages = leftCapStretched.size.width + arrow.size.width + rightCapStretched.size.width;

// build the actual glued image

UIGraphicsBeginImageContextWithOptions(CGSizeMake(widthOfAllImages, arrow.size.height), NO, 0);
[leftCapStretched drawAtPoint:CGPointMake(0, 0)];
[arrow drawAtPoint:CGPointMake(leftCap.size.width, 0)];
[rightCapStretched drawAtPoint:CGPointMake(leftCap.size.width + arrow.size.width, 0)];
UIImage* im = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext();

// now you should have a ready to use UIImage ;)

替代方案

受Jonathan Plaketts答案的启发,只需使用UIImageViews并像上面一样拉伸UIImages即可实现相同效果。


太好了!哇,非常感谢你!我一整天都在尝试各种不同的解决方案。 - Chris
似乎这并没有解决主要问题:如果你设置具体的宽度/高度值,程序将如何拉伸这个图像?如果你想说我可以改变硬编码的值,那么如果我在拉伸后仍然必须定义具体的大小区域,为什么我还要使用自动拉伸呢? - user2159978

1

我建议以编程的方式完成,虽然可能会浪费一些 CPU 周期,但会更有趣。

好的,我们开始吧...

让我们在头文件中定义 3 个 UIImageView。

UIImageView *left;
UIImageView *center;
UIImageView *right;

在viewDidLoad中,我们将创建它们。
left = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"left.jpg"]];
center = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"center.jpg"]];
right = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"right.jpg"]];


[self.view addSubview:left];
[self.view addSubview:center];
[self.view addSubview:right];

//set the position of the center piece wherever you like, whatever size is right for your arrow
[self setCenterFrame:CGRectMake(100,100,100,100)]; //we'll make this function below

那么,让我们创建一个方法,您可以使用它来设置中心图像的位置,并使其他图像在其周围晃动到位,将自己拉伸到左右边缘。

-(void)setCenterFrame:(CGRect)rect
{
    center.frame = rect; // this is your arrow

    //set size of left
    left.frame = CGRectMake(0,rect.origin.y, rect.origin.x, rect.size.height);

    //work out how much space there is to the right
    float sizeToTheRight = (self.view.bounds.size.width - rect.size.width) - rect.origin.x ;

    //set size of right
    right.frame = CGRectMake(rect.size.width + rect.origin.x,rect.origin.y, sizeToTheRight, rect.size.height);


}

-1

你的方法有点奇怪 :)

你有三个不同的图片组成一个可拉伸的单一图片,但每次使用时你想以编程的方式构建它。这将浪费 CPU 周期。 iOS 框架允许你像平常一样拉伸图片。在图像编辑器中打开你的文件 (Photoshop 或类似软件)。合成一个包含中心图像和左右帽子的单一图像。

现在你可以像其他图片一样使用这个图片,或者使用 UIImage 方法来拉伸它。

- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets

UIEdgeInsets是一个简单的结构体,用于标识您的边界限制。假设您需要向左拉伸15pt和向右拉伸20pt,则您的插图将如下所示: 顶部:0 底部:0 左侧:15 右侧:20

就是这样。

在这里查看详细信息。该文章讨论了iOS 5.0及以上版本中已弃用的方法,但其背后的理论是相同的。


这种方法的问题在于图像的中心部分会被拉伸。如果您阅读问题下面的评论,他明确指出中心图像是箭头。我认为他不希望它被拉伸 ;) - Pfitz
刚刚尝试了一下,但没有成功。除非有一种方法可以在不影响中心的情况下重复图像中间的两个部分。 - Chris
3
一种干净的方法是使用箭头图像进行分离。按照之前描述的方式拉伸可拉伸的图像,然后使用UIGraphicsBeginImageContextWithOptions组合两个图像到上下文中使用drawAtPoint: UIImage方法,从上下文中获取新图像使用UIGraphicsGetImageFromCurrentImageContext并使用UIGraphicsEndImageContext关闭图形上下文。 - Gabriele
我认为这个答案完全没用。请仔细阅读问题。 - user2159978

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接