web-dev-qa-db-ja.com

コーナーを維持しながらUIImageをストレッチする

中央を伸ばして両端を固定するために、エッジを保持しながらナビゲーション矢印の画像を伸ばそうとしています。

これが私がストレッチしようとしている画像です:

enter image description here

次のiOS 5コードは、UIEdgeInsetsで定義された画像の中央部分を拡大するようにサイズ変更されたときに画像を許可します。

[[UIImage imageNamed:@"arrow.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(15, 7, 15, 15)];

これにより、次のような画像になります(画像のフレームが70ピクセル幅に設定されている場合)。

enter image description here

これは実際に私が欲しいものですが、 resizableImageWithCapInsets はiOS 5以降でのみサポートされています。

IOS 5より前は、類似したメソッドは stretchableImageWithLeftCapWidth:topCapHeight のみですが、指定できるのは上部と左のインセットのみで、これは画像のエッジが同じ形状でなければならないことを意味します。

IOS 5のresizableImageWithCapInsetsメソッドと同じように画像のサイズを変更するiOS 4の方法、またはこれを行う別の方法はありますか?

27
Camsoft

ここでのあなたの仮定は間違っています:

IOS 5以前は、同様のメソッドは唯一、stretchableImageWithLeftCapWidth:topCapHeightですが、指定できるのは上部と左のインセットのみで、これは画像のエッジの形状が等しい必要があることを意味します。

キャップは次のように計算されます-左のキャップをステップスルーしますが、同じ原理が上部のキャップにも適用されます。

画像の幅が20pxだとします。

  • 左キャップの幅-これは、画像の左側にある、拡大できない部分です。 stretchableImageメソッドでは、このために値10を送信します。
  • 伸縮可能な部分-これは幅が1ピクセルであると想定されているため、よりわかりやすくするために、列「11」のピクセルになります。
  • これは、画像の残りの9ピクセルの暗黙の右キャップがあることを意味します-これも変形されません。

これは documentation から取得されます

leftCapWidth

エンドキャップは、画像が引き伸ばされたときにサイズを変更してはならない画像の部分を指定します。この手法は、ボタンやその他のサイズ変更可能な画像ベースのインターフェース要素を実装するために使用されます。エンドキャップのあるボタンのサイズが変更されると、サイズ変更はボタンの中央、エンドキャップ間の領域でのみ発生します。エンドキャップ自体は元のサイズと外観を維持します。

このプロパティは、左エンドキャップのサイズを指定します。中央(伸縮可能)部分の幅は1ピクセルと想定されています。したがって、右エンドキャップは、左エンドキャップと中央部分のサイズを合計し、その値を画像の幅から差し引くことで計算されます。

rightCapWidth = image.size.width - (image.leftCapWidth + 1);

31
jrturton
UIImage *image = [UIImage imageNamed:@"img_loginButton.png"];
    UIEdgeInsets edgeInsets;
    edgeInsets.left = 0.0f;
    edgeInsets.top = 0.0f;
    edgeInsets.right = 5.0f; //Assume 5px will be the constant portion in your image
    edgeInsets.bottom = 0.0f;
    image = [image resizableImageWithCapInsets:edgeInsets];
//Use this image as your controls image
9
Vicky

あなたの例は、左のキャップを15にしてstretchableImageWithLeftCapWidth:topCapHeight:を使用することで完全に可能です(どうやら、コードの読み取りから)。中央の列を繰り返すことにより、ボタンが水平方向に引き伸ばされます。

5
Steven Kramer

UIImageを拡張して、カスタムEdge保護で画像を引き伸ばすことができます(それにより、画像をタイリングする代わりに、画像の内部を引き伸ばします)。

UIImage + utils.h:

#import <UIKit/UIKit.h>
@interface UIImage(util_extensions)
//extract a portion of an UIImage instance 
-(UIImage *) cutout: (CGRect) coords;
//create a stretchable rendition of an UIImage instance, protecting edges as specified in cornerCaps
-(UIImage *) stretchImageWithCapInsets: (UIEdgeInsets) cornerCaps toSize: (CGSize) size;
@end

UIImage + utils.m:

#import "UIImage+utils.h"
@implementation UIImage(util_extensions)
-(UIImage *) cutout: (CGRect) coords {
    UIGraphicsBeginImageContext(coords.size);
    [self drawAtPoint: CGPointMake(-coords.Origin.x, -coords.Origin.y)];
    UIImage *rslt = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return rslt;
}

-(UIImage *) stretchImageWithCapInsets: (UIEdgeInsets) cornerCaps toSize: (CGSize) size { 
    UIGraphicsBeginImageContext(size);

    [[self cutout: CGRectMake(0,0,cornerCaps.left,cornerCaps.top)] drawAtPoint: CGPointMake(0,0)]; //topleft
    [[self cutout: CGRectMake(self.size.width-cornerCaps.right,0,cornerCaps.right,cornerCaps.top)] drawAtPoint: CGPointMake(size.width-cornerCaps.right,0)]; //topright
    [[self cutout: CGRectMake(0,self.size.height-cornerCaps.bottom,cornerCaps.left,cornerCaps.bottom)] drawAtPoint: CGPointMake(0,size.height-cornerCaps.bottom)]; //bottomleft
    [[self cutout: CGRectMake(self.size.width-cornerCaps.right,self.size.height-cornerCaps.bottom,cornerCaps.right,cornerCaps.bottom)] drawAtPoint: CGPointMake(size.width-cornerCaps.right,size.height-cornerCaps.bottom)]; //bottomright

    [[self cutout: CGRectMake(cornerCaps.left,0,self.size.width-cornerCaps.left-cornerCaps.right,cornerCaps.top)]
 drawInRect: CGRectMake(cornerCaps.left,0,size.width-cornerCaps.left-cornerCaps.right,cornerCaps.top)]; //top

    [[self cutout: CGRectMake(0,cornerCaps.top,cornerCaps.left,self.size.height-cornerCaps.top-cornerCaps.bottom)]
 drawInRect: CGRectMake(0,cornerCaps.top,cornerCaps.left,size.height-cornerCaps.top-cornerCaps.bottom)]; //left

    [[self cutout: CGRectMake(cornerCaps.left,self.size.height-cornerCaps.bottom,self.size.width-cornerCaps.left-cornerCaps.right,cornerCaps.bottom)]
 drawInRect: CGRectMake(cornerCaps.left,size.height-cornerCaps.bottom,size.width-cornerCaps.left-cornerCaps.right,cornerCaps.bottom)]; //bottom

    [[self cutout: CGRectMake(self.size.width-cornerCaps.right,cornerCaps.top,cornerCaps.right,self.size.height-cornerCaps.top-cornerCaps.bottom)]
 drawInRect: CGRectMake(size.width-cornerCaps.right,cornerCaps.top,cornerCaps.right,size.height-cornerCaps.top-cornerCaps.bottom)]; //right

    [[self cutout: CGRectMake(cornerCaps.left,cornerCaps.top,self.size.width-cornerCaps.left-cornerCaps.right,self.size.height-cornerCaps.top-cornerCaps.bottom)]
 drawInRect: CGRectMake(cornerCaps.left,cornerCaps.top,size.width-cornerCaps.left-cornerCaps.right,size.height-cornerCaps.top-cornerCaps.bottom)]; //interior

    UIImage *rslt = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return [rslt resizableImageWithCapInsets: cornerCaps];
}

@end
4
Mark Stasak

Vickyの回答のSwift 3.0バージョン。

var imageInset:UIEdgeInsets = UIEdgeInsets()
        imageInset.left = 10.0
        imageInset.top = 10.0
        imageInset.bottom = 10.0
        imageInset.right = 10.0
        self.myImageView.image = myimage.resizableImage(withCapInsets: imageInset)
2
shesh nath