33

I'm using storyboards to layout my view controllers and I would like to use stretchable images for my buttons (so that I don't need to generate several images with different sizes).

Is this possible to do directly in storyboards without writing any code? I'm really liking the possibility to use storyboards for all graphic stuff and keep the code clean from UI stuff, but it seems like I can't get away with it here.

If it is not possible, what would you suggest otherwise?

4

5 に答える 5

75

iOS 7 以降の更新 iOS 7
以降では、アセット カタログを介してネイティブでストレッチ可能な画像がサポートされるようになりました。アセット カタログを使用して、画像のスライス方法とスケーリング方法 (ストレッチまたはタイル) を指定できるようになりました。画像のこれらのアセット カタログ属性は、ストーリーボードにすぐに反映されます。素晴らしい新しい改善。詳細については、アセット カタログの Apple のドキュメントを参照してください。

7 より前の iOS バージョンにデプロイする場合:
あまり知られていない事実ですが、Interface Builder/Storyboard と属性インスペクターのストレッチ プロパティのみを使用して、画像のキャップ インセットを完全に設定できます。元の回答をくれたビクターに感謝します。

a の属性インスペクターでストレッチ プロパティを見るとUIImage、X 値と Y 値は、イメージの幅と高さ全体に対するストレッチ開始点の位置です。0.5 の値は、画像の中央のポイントを意味します。

幅と高さは、画像サイズに対する伸縮可能領域のサイズです。したがって、幅を 1 / imageWidth の値に設定すると、伸縮可能な領域の幅が 1 ピクセルに設定されます。

ほとんどの伸縮可能な画像は中央から伸びるため、X、Y、幅、および高さにこれらの値を使用すると、通常はうまくいきます。

X = 0.5
Y = 0.5
Width = 1/imageWidth
Height = 1/imageHeight

注: 拡大するイメージが非常に小さい場合を除き、幅と高さのプロパティは非常に小さくなり (0.008 など)、代わりに 0.0 を使用できます。したがって、実際には、0.5、0.5、0.0、0.0 が X、Y、幅、高さに対してほぼ常に機能します。

幅と高さに対して 0.0 が機能しない少数のケースでは、電卓を使用して IB でこれらの値を設定する必要があることを意味します。ただし、IB (WYSIWYG) で引き伸ばされた画像を確認できるため、プログラムで設定するよりも一般的には望ましいと思います。

伸縮可能な画像属性

更新:一部の人々は、上記の提案を使用して Storyboard で画像をストレッチすることはできますが、iOS7 の時点でも、ボタンで画像をストレッチすることはまだ壊れていると指摘しています。UIButton心配する必要はありません。これは、コントロール状態のキャップ インセットを設定するカテゴリを作成することで簡単に対処できます。

@implementation UIButton (Stretchable)

/* Automatically set cap insets for the background image. This assumes that
   the image is a standard slice size with a 1 px stretchable interior */
- (void)setBackgroundImageStretchableForState:(UIControlState)controlState
{
    UIImage *image = [self backgroundImageForState:controlState];
    if (image)
    {
       CGFloat capWidth =  floorf(image.size.width / 2);
       CGFloat capHeight =  floorf(image.size.height / 2);
       UIImage *capImage = [image resizableImageWithCapInsets:
                     UIEdgeInsetsMake(capHeight, capWidth, capHeight, capWidth)];

       [self setBackgroundImage:capImage forState:controlState];
    }
}

このカテゴリを使用すると、ストーリーボードを介してボタンの伸縮可能な画像を設定-setBackgroundImageStretchableForState:し、-viewDidLoad. ビュー階層を繰り返し処理すると、ビュー内に多数のボタンがある場合でも簡単に実行できます。

NSPredicate *predicate = 
    [NSPredicate predicateWithFormat:@"self isKindOfClass:%@",[UIButton class]];
NSArray *buttons = [self.view.subviews filteredArrayUsingPredicate:predicate];
for (UIButton *button in buttons)
   [button setBackgroundImageStretchableForState:UIControlStateNormal];

これは、これを自動的に行うサブクラスを持つほど良くはありませUIButtonんが (サブクラス化UIButtonはクラス クラスターであるため実用的ではありません)、viewDidLoad のボイラープレート コードを少しだけ使用して、ほぼ同じ機能を提供します - - すべてのボタン画像をストーリーボードに設定しても、適切に引き伸ばすことができます。

于 2012-11-13T20:02:17.983 に答える
2

私がしたことは次のとおりです。ボタンのコンセントを設定して接続し、viewDidLoadでこれを行いました。

[self.someButton setBackgroundImage:[[self.someButton backgroundImageForState:UIControlStateNormal] resizableImageWithCapInsets:UIEdgeInsetsMake(3, 3, 4, 3)] forState:UIControlStateNormal];

これにより、ストーリーボードに設定した画像が再利用されるため、ある色から別の色に変更しても、挿入図が変更されない限り機能します。

これらの多くを持っているビューのために、私はこれをしました:

for (UIView * subview in self.view.subviews) {
        if ([subview isKindOfClass:[UIImageView class]] && subview.tag == 10) {
            UIImageView* textFieldImageBackground = (UIImageView*)subview;
            textFieldImageBackground.image = [textFieldImageBackground.image stretchableImageWithLeftCapWidth:7 topCapHeight:5];
        } else if([subview isKindOfClass:[UIButton  class]] && subview.tag == 11) {
            UIButton * button = (UIButton*)subview;
            [button setBackgroundImage:[[button backgroundImageForState:UIControlStateNormal] resizableImageWithCapInsets:UIEdgeInsetsMake(3, 3, 4, 3)] forState:UIControlStateNormal];
        }
    }

伸ばしたいものすべてにタグを設定していることに注意してください。

私はあなたと同じ船に乗っていますが、ストーリーボード自体にこれらの非常にUI中心のものを設定できることを望んでいます。

于 2012-08-07T17:41:09.827 に答える