Write in front
-
Explain why UIControl is used to encapsulate controls.
a. From the demand point of view, this control is not only to display content, it may need to achieve click events.
b. This control may have various states such as selected state and unselected state.
c. When the size of the control is too large, we may need the content of the control to achieve top, middle, bottom, left, right and so on. -
The advantages of UIControl over UIView.
As we all know, UIButton inherits from UIControl.
A. Looking at the A PI of UIControl, you can find the following:
Content Vertical Alignment and Content Horizontal Alignment are the top, middle, bottom, left and right mentioned in 1.
@property(nonatomic,getter=isSelected) BOOL selected;
@property(nonatomic,getter=isHighlighted) BOOL highlighted;
@property(nonatomic) UIControlContentVerticalAlignment contentVerticalAlignment;
@property(nonatomic) UIControlContentHorizontalAlignment contentHorizontalAlignment;
- (void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
- UIButton class, we want to achieve click events and select a medium state of the style, you can refer to the UIButton API for encapsulation. To put it bluntly, it's a method for the outside world to use.
- (void)setTitle:(nullable NSString *)title forState:(UIControlState)state; // default is nil. title is assumed to be single line
- (void)setTitleColor:(nullable UIColor *)color forState:(UIControlState)state;
- (void)setImage:(nullable UIImage *)image forState:(UIControlState)state;
Through the above content, we should summarize UIControl and UIButton's API methods for encapsulation.
Code and related instructions:
h file
The. h file provides the Label and ImageView properties of the control.
Colleagues implemented UIButton-like methods and quick settings
(void)setImage:(UIImage*)image andTitleLableText:(NSString*)title
#import <UIKit/UIKit.h>
/** Components below */
@interface RjxImageTitleView : UIControl
/// The picture above
@property (nonatomic,strong) UIImageView *topImageView;
/// The following text
@property (nonatomic,strong) UILabel *titleLable;
/// Intermediate interval
@property (nonatomic,assign) CGFloat spaceBetweenTitleAndImage;
/**
* @description Set the values of the following text according to different states
* @param title Text content can be empty
* @Param state UIControlState Enumeration of type status values
*/
- (void)setTitle:(NSString *)title forState:(UIControlState)state;
/**
* @description Set the color of the following text according to different states
* @param title colour
* @Param state UIControlState Enumeration of type status values
*/
- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state;
/**
* @description Setting pictures according to different states
* @param image picture
* @Param state UIControlState Enumeration of type status values
*/
- (void)setImage:(UIImage *)image forState:(UIControlState)state;
/**
* @description Quickly set the values of the image above and the text below by default UIControlStateNormal
* @param image picture
* @Param title Value of text
*/
- (void)setImage:(UIImage*)image andTitleLableText:(NSString*)title;
@end
/// Used to record some properties when the control is in different states
@interface RjxImageTitleModel : NSObject
@property (nonatomic,strong) NSString *strTitle;
@property (nonatomic,strong) UIColor *color;
@property (nonatomic,strong) UIImage *image;
@end
m file
The. m file contains a lot of content. Look at it carefully.
[NSLayout Constraint Active Constraints: Active Constraints]; Activate certain constraints
[NSLayout Constraint deactivate Constraints: active Constraints]; Close some constraints
#import "RjxImageTitleView.h"
@interface RjxImageTitleView()
//The dictionary records the corresponding attributes and corresponding value values should be key @ (UIControl State) value: RjxImageTitleModel
@property (nonatomic,strong) NSMutableDictionary *dicProperty;
//Height of the bottom title from the above image
@property (nonatomic,strong) NSLayoutConstraint *titleLableTopConstraint;
@property (nonatomic,strong) NSDictionary *contentViewHorizontalConstraints;
@property (nonatomic,strong) NSDictionary *contentViewVerticalConstraints;
@end
@implementation RjxImageTitleView
- (instancetype)init
{
self = [super init];
if (self) {
[self initView];
}
return self;
}
- (void)setSpaceBetweenTitleAndImage:(CGFloat)spaceBetweenTitleAndImage
{
if (spaceBetweenTitleAndImage == _spaceBetweenTitleAndImage) {
return;
}
_spaceBetweenTitleAndImage = spaceBetweenTitleAndImage;
self.titleLableTopConstraint.constant = _spaceBetweenTitleAndImage;
}
//Initialization control
- (void)initView
{
//
_spaceBetweenTitleAndImage = 2.;
UIView *contentView = [[UIView alloc] init];
[self addSubview:contentView];
contentView.backgroundColor = [UIColor yellowColor];
//Adding constraints using NSLayout Constraint
NSLayoutConstraint *constraint_top_greater = [NSLayoutConstraint constraintWithItem:contentView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1 constant:0];
NSLayoutConstraint *constraint_left_greater = [NSLayoutConstraint constraintWithItem:contentView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1 constant:0];
NSLayoutConstraint *constraint_bottom_less = [NSLayoutConstraint constraintWithItem:contentView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationLessThanOrEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
NSLayoutConstraint *constraint_right_less = [NSLayoutConstraint constraintWithItem:contentView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationLessThanOrEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1 constant:0];
// Some location constraints here are constraints for content Vertical Alignment and content Horizontal Alignment to control location
NSLayoutConstraint *contentView_constraint_centerX = [contentView addCenterX:0 toView:self];
NSLayoutConstraint *contentView_constraint_centerY = [contentView addCenterY:0 toView:self];
NSLayoutConstraint *contentView_constraint_left = [contentView leftToView:self withSpace:0];
NSLayoutConstraint *contentView_constraint_right = [contentView rightToView:self withSpace:0];
NSLayoutConstraint *contentView_constraint_top = [contentView topToView:self withSpace:0];
NSLayoutConstraint *contentView_constraint_bottom = [contentView bottomToView:self withSpace:0];
// Here it is divided into horizontal and vertical, and the values used are saved separately.
self.contentViewHorizontalConstraints = @{
@(UIControlContentHorizontalAlignmentCenter):contentView_constraint_centerX,
@(UIControlContentHorizontalAlignmentLeft):contentView_constraint_left,
@(UIControlContentHorizontalAlignmentRight):contentView_constraint_right,
};
self.contentViewVerticalConstraints = @{
@(UIControlContentVerticalAlignmentCenter):contentView_constraint_centerY,
@(UIControlContentVerticalAlignmentTop):contentView_constraint_top,
@(UIControlContentVerticalAlignmentBottom):contentView_constraint_bottom,
};
[self addConstraints:@[
constraint_top_greater,
constraint_left_greater,
constraint_bottom_less,
constraint_right_less,
]];
//
[contentView addSubview:self.topImageView];
[self.topImageView topToView:contentView withSpace:0];
[self.topImageView addCenterX:0 toView:contentView];
[contentView addConstraints:@[
[NSLayoutConstraint constraintWithItem:self.topImageView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:contentView attribute:NSLayoutAttributeLeft multiplier:1 constant:0],
[NSLayoutConstraint constraintWithItem:self.topImageView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationLessThanOrEqual toItem:contentView attribute:NSLayoutAttributeRight multiplier:1 constant:0]
]];
//Normal constraints
[contentView addSubview:self.titleLable];
[self.titleLable bottomToView:contentView withSpace:0];
[self.titleLable addCenterX:0 toView:contentView];
[contentView addConstraints:@[
[NSLayoutConstraint constraintWithItem:self.titleLable attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:contentView attribute:NSLayoutAttributeLeft multiplier:1 constant:0],
[NSLayoutConstraint constraintWithItem:self.titleLable attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationLessThanOrEqual toItem:contentView attribute:NSLayoutAttributeRight multiplier:1 constant:0]
]];
//Here is the gap between the bound upper and lower controls
self.titleLableTopConstraint = [self.topImageView bottomToView:self.titleLable withSpace:self.spaceBetweenTitleAndImage];
/// Setting default
self.contentVerticalAlignment = self.contentVerticalAlignment;
self.contentHorizontalAlignment = self.contentHorizontalAlignment;
}
- (void)setContentHorizontalAlignment:(UIControlContentHorizontalAlignment)contentHorizontalAlignment
{
//You need to call super or it won't execute
[super setContentHorizontalAlignment:contentHorizontalAlignment];
[self setContentViewHorizontalPosition];
}
- (void)setContentVerticalAlignment:(UIControlContentVerticalAlignment)contentVerticalAlignment
{
[super setContentVerticalAlignment:contentVerticalAlignment];
[self setContentViewVerticalPosition];
}
/***
*Setting Content View Location Nine Locations Six Major Attributes Decision
*/
- (void)setContentViewHorizontalPosition
{
//All set to inactive state
[NSLayoutConstraint deactivateConstraints:self.contentViewHorizontalConstraints.allValues];
NSMutableArray *activeConstraints = [[NSMutableArray alloc] init];
//transverse
if (self.contentHorizontalAlignment == UIControlContentHorizontalAlignmentFill) {
[activeConstraints addObject:[self.contentViewHorizontalConstraints objectForKey:@(UIControlContentHorizontalAlignmentLeft)]];
[activeConstraints addObject:[self.contentViewHorizontalConstraints objectForKey:@(UIControlContentHorizontalAlignmentRight)]];
}else{
[activeConstraints addObject:[self.contentViewHorizontalConstraints objectForKey:@(self.contentHorizontalAlignment)]];
}
[NSLayoutConstraint activateConstraints:activeConstraints];
}
/***
*Setting Content View Location Nine Locations Six Major Attributes Decision
*/
- (void)setContentViewVerticalPosition
{
//All set to inactive state
[NSLayoutConstraint deactivateConstraints:self.contentViewVerticalConstraints.allValues];
NSMutableArray *activeConstraints = [[NSMutableArray alloc] init];
//portrait
if (self.contentVerticalAlignment == UIControlContentVerticalAlignmentFill) {
[activeConstraints addObject:[self.contentViewVerticalConstraints objectForKey:@(UIControlContentVerticalAlignmentTop)]];
[activeConstraints addObject:[self.contentViewVerticalConstraints objectForKey:@(UIControlContentVerticalAlignmentBottom)]];
}else{
[activeConstraints addObject:[self.contentViewVerticalConstraints objectForKey:@(self.contentVerticalAlignment)]];
}
[NSLayoutConstraint activateConstraints:activeConstraints];
}
- (void)setSelected:(BOOL)selected
{
[super setSelected:selected];
UIControlState state = UIControlStateNormal;
if (selected) {
state = UIControlStateSelected;
}else{
state = UIControlStateNormal;
}
EPMImageTitleModel *model = [self getValueFromDicPropertyforKey:state];
[self setImage:model.image andTitleLableText:model.strTitle];
[self setTitleColor:model.color forState:UIControlStateSelected];
}
- (void)setHighlighted:(BOOL)highlighted
{
}
/**
* @description Get the value according to key
* @return EPMImageTitleModel Returns the entity value of the corresponding key
*/
- (EPMImageTitleModel*)getValueFromDicPropertyforKey:(UIControlState)state
{
EPMImageTitleModel *model = nil;
if (![self.dicProperty objectForKey:@(state)]) {
model = [[EPMImageTitleModel alloc] init];
[self.dicProperty setObject:model forKey:@(state)];
}
return model;
}
- (void)setTitle:(NSString *)title forState:(UIControlState)state
{
if (title) {
self.titleLable.text = title;
EPMImageTitleModel *model = [self getValueFromDicPropertyforKey:state];
model.strTitle = title;
}
}
- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state
{
if (color) {
self.titleLable.textColor = color;
EPMImageTitleModel *model = [self getValueFromDicPropertyforKey:state];
model.color = color;
}
}
- (void)setImage:(UIImage *)image forState:(UIControlState)state
{
if (image) {
self.topImageView.image = image;
EPMImageTitleModel *model = [self getValueFromDicPropertyforKey:state];
model.image = image;
}
}
- (void)setImage:(UIImage*)image andTitleLableText:(NSString*)title
{
[self setImage:image forState:UIControlStateNormal];
[self setTitle:title forState:UIControlStateNormal];
}
/**Attribute lazy loading**/
- (UIImageView *)topImageView
{
if (!_topImageView) {
_topImageView = [[UIImageView alloc] init];
}
return _topImageView;
}
- (UILabel *)titleLable
{
if (!_titleLable) {
_titleLable = [[UILabel alloc] init];
}
return _titleLable;
}
- (NSMutableDictionary *)dicProperty
{
if (!_dicProperty) {
_dicProperty = [[NSMutableDictionary alloc] init];
}
return _dicProperty;
}
@end
@implementation RjxImageTitleModel
@end
The effect is as follows:
The invocation is as follows:
Pay attention to the red box
If you do not set two values in the red box: the default is in the middle.