2016-11-07 2 views
2

Я создаю этот класс IB_Designable. Это похоже на слайдер. См. Изображение. Оба элемента создаются с небольшим растягиваемостью UIImages.Создание UIImage перерисовки на новое место на @IB_Designable

enter image description here

У меня есть этот красный квадрат, который 66x66 пт. Этот квадрат должен скользить по 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 не делает большой палец шаг, когда я установил значение на построителе интерфейса ... любые идеи?

+0

Извините, что в setCenter. Я исправил код. Это была опечатка при копировании кода здесь. Нет, нет возможности проверить IBOutlet. В моем IBDesignable есть проверенные свойства, показанные в первой части кода. – SpaceDog

ответ

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 ссылается на ... вы вообще не будете ссылаться на представления за пределами иерархии представления условного представления). И вы ссылаетесь на представление верхнего уровня, являющееся представлением изображения, которое вы бы сделали, если бы вы хотели получить фоновое изображение.

Но это детали, которые не имеют отношения к вашему более широкому вопросу. Надеюсь, это иллюстрирует идею о том, что если вы создадите программные подпрограммы, вы можете увидеть движение миниатюр при изменении своего IBInspectablevalue.


Я видел несколько реализаций здесь, где люди хотели, чтобы определить все иерархии зрения на проектируемом зрении с торговыми точками. Но в этом случае у вас есть автономный NIB для всех этих подзонов. Если вы ищете StackOverflow для «IBDesignable NIB», вы увидите ссылки на соответствующие ответы.

+1

Блестящий ответ! БЛАГОДАРЯ! – SpaceDog

Смежные вопросы