2016-11-07 34 views
2

我正在創建此IB_Designable類。它就像一個滑塊。看照片。這兩個元素都創建了很小的伸縮性UIImages使UIImage在@IB_Designable上的新位置重新繪製

enter image description here

我有這個紅色的方塊是66x66角。這個正方形必須在灰色矩形內的X上滑動。

我創建這個類:

HEADER

#import <UIKit/UIKit.h> 

IB_DESIGNABLE 

@interface MyClass : UIView 

// minimum and maximum slider value 
@property (assign, nonatomic) IBInspectable CGFloat minimumValue; 
@property (assign, nonatomic) IBInspectable CGFloat maximumValue; 

@property (assign, nonatomic) IBInspectable CGFloat value; 

@end 

實現

#import "MyClass.h" 

@interface MyClass() { 
    __weak IBOutlet UIView *topContainer; 
    CGFloat minimumThumbCoordinate; 
    CGFloat maximumThumbCoordinate; 
} 

@property (weak, nonatomic) IBOutlet UIImageView *thumb; 

@end 


@implementation MyClass 



- (void)awakeFromNib { 
    [super awakeFromNib]; 

    // topContainer contains everything 
    CGRect topContainerBounds = [topContainer bounds]; 
    CGRect thumbBounds = [self.thumb bounds]; 

    CGFloat topContainerWidth = CGRectGetWidth(topContainerBounds); 
    CGFloat thumbWidth = CGRectGetWidth(thumbBounds); 

    minimumThumbCoordinate = floorf(thumbWidth/2.0f); 
    maximumThumbCoordinate = floorf(topContainerWidth - minimumThumbCoordinate); 

} 

-(void)setValue:(CGFloat)value { 

    if ((value < self.minimumValue) || (value > self.maximumValue)) return; 

    // normalize values 

    CGFloat minimumValueNormalized = self.minimumValue; 
    CGFloat maximumValueNormalized = self.maximumValue; 
    CGFloat desiredValue = value; 

    if ((minimumValueNormalized < 0) && (maximumValueNormalized > 0)) { 
    CGFloat absoluteMinimum = fabsf(self.minimumValue); 
    minimumValueNormalized = 0; 
    maximumValueNormalized += absoluteMinimum; 
    desiredValue += absoluteMinimum; 
    } 

    CGFloat percentage = desiredValue/maximumValueNormalized; 

    // find coordinate 
    CGFloat coordinateRange = maximumThumbCoordinate - minimumThumbCoordinate; 
CGFloat relativeCoordinate = percentage * coordinateRange; 

CGPoint center = CGPointMake(relativeCoordinate, self.thumb.center.y); 

    [self.thumb setCenter: center]; 

} 

的問題是setValue方法不會使拇指移動當我設置界面生成器的價值......任何想法?

+0

對不起,關於setCenter。我已更正了代碼。將代碼複製到此處時出現錯字。不,沒有辦法讓IBOutlet可以檢查。我的IBDesignable具有代碼第一部分顯示的可檢查屬性。 – SpaceDog

回答

1

在故事板中不能添加縮略圖的組件。在這種情況下,我懷疑你的圖像視圖插座是nil,而它正在IB中預覽,因此更改value它可能不會更新任何子視圖。

您通常通過編程添加子視圖來解決這個問題,例如,是這樣的:

// MyClass.h 

#import <UIKit/UIKit.h> 

IB_DESIGNABLE 
@interface MyClass : UIView 

@property (nonatomic, strong) IBInspectable UIImage *thumbnailImage; 

@property (nonatomic) IBInspectable CGFloat minimumValue; 
@property (nonatomic) IBInspectable CGFloat maximumValue; 

@property (nonatomic) IBInspectable CGFloat value; 
@property (nonatomic, readonly) CGFloat percent; 

@end 

而且

// MyClass.m 

#import "MyClass.h" 

@interface MyClass() 

@property (weak, nonatomic) UIImageView *thumbnailView; 
@property (nonatomic) CGFloat thumbWidth; 

@end 

@implementation MyClass 

- (instancetype)initWithFrame:(CGRect)frame { 
    self = [super initWithFrame:frame]; 
    if (self) { 
     [self configureView]; 
    } 
    return self; 
} 

- (instancetype)initWithCoder:(NSCoder *)coder { 
    self = [super initWithCoder:coder]; 
    if (self) { 
     [self configureView]; 
    } 
    return self; 
} 

- (void)configureView { 
    UIImageView *thumb = [[UIImageView alloc] initWithImage:self.thumbnailImage]; 
    [self addSubview:thumb]; 
    thumb.backgroundColor = [UIColor lightGrayColor]; // in case no image has been set 
    thumb.clipsToBounds = true;      // in case you change your `contentMode` 
    thumb.contentMode = UIViewContentModeScaleToFill; 
    _thumbnailView = thumb; 

    _thumbWidth = 44;         // maybe you have another IBInspectable property for this... 

    [self layoutThumbnail]; 
} 

- (void)setThumbnailImage:(UIImage *)image { 
    self.thumbnailView.image = image; 
} 

- (CGFloat)percent { 
    CGFloat range = self.maximumValue - self.minimumValue; 
    return range ? (self.value - self.minimumValue)/range : 0; 
} 

- (void)layoutSubviews { 
    [super layoutSubviews]; 

    [self layoutThumbnail]; 
} 

- (void)layoutThumbnail { 
    CGFloat minX = self.thumbWidth/2; 
    CGFloat maxX = self.bounds.size.width - self.thumbWidth/2; 

    CGRect frame = CGRectMake(self.percent * (maxX - minX) + minX - self.thumbWidth/2, 0, self.thumbWidth, self.bounds.size.height); 

    self.thumbnailView.frame = frame; 
} 

- (void)setValue:(CGFloat)value { 
    if (value < self.minimumValue) 
     _value = self.minimumValue; 
    else if (value > self.maximumValue) { 
     _value = self.maximumValue; 
    } else { 
     _value = value; 
    } 

    [self layoutThumbnail]; 
} 

@end 

注意,我當你改變值不僅有,而且還取決於layoutSubviews更新縮略圖幀。如果控件在運行時更改大小(例如,用戶旋轉設備並且控件更改了大小),則需要確保縮略圖框更新。我還將縮略圖圖像作爲一個屬性,所以如果您想要,也可以在IB中設置它。但是也許你有一些你使用的硬編碼/默認圖像。我還認爲我們用於佈局縮略圖的percent可能會使用該控件的代碼有用,因此我公開了該屬性。

現在,您正在使用圖像視圖,但是如果您想要的只是主控件和縮略圖的圓角,我就不會使用圖像,而只是圍繞layer的角落轉動相應的UIView對象。此外,我不清楚你的某些事情的意圖(例如,我不確定你的topContainer是指什麼......你通常不會引用可視設計視圖的視圖層次之外的視圖)。而且,您引用頂層視圖作爲圖像視圖,如果您還想在其中創建背景圖像,則可以這麼做。

但這些細節與您的更廣泛的問題無關。希望這可以說明這個想法,即如果以編程方式創建子視圖,則可以在更改IBInspectablevalue時看到縮略圖移動。


我在這裏看到了一些實現,人們想要定義設計視圖的所有視圖層次結構。但是在這種情況下,您擁有所有這些子視圖的獨立NIB。如果您在StackOverflow中搜索「IBDesignable NIB」,則會看到相關答案的鏈接。

+1

絕妙的答案!謝謝! – SpaceDog