2

我正在创建这个 IB_Designable 类。它就像一个滑块。见图片。这两个元素都是用很少的可拉伸元素创建的UIImages

在此处输入图像描述

我有这个 66x66 pt 的红色正方形。这个正方形必须在灰色矩形内的 X 中滑动。

我已经创建了这个类:

标题

#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当我在界面生成器上设置值时,该方法不会使拇指移动......有什么想法吗?

4

1 回答 1

1

您不能在情节提要中添加缩略图的组件。在这种情况下,我怀疑您的thumb图像视图出口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指的是什么……您通常不会引用可设计视图的视图层次结构之外的视图)。并且您将顶级视图引用为图像视图,如果您也想要那里的背景图像,您会这样做。

但这些细节与您的更广泛问题无关。希望这说明了这个想法,如果您以编程方式创建子视图,您可以在更改IBInspectable value.


我在这里看到了一些实现,人们想用插座定义可设计视图的所有视图层次结构。但在这种情况下,所有这些子视图都有一个独立的 NIB。如果您在 StackOverflow 中搜索“IBDesignable NIB”,您将看到相关答案的链接。

于 2016-11-07T07:24:28.697 回答