iOS-使用UIControl类封装一个@"上图下文"控件

写在前面

  • 说明一下为什么使用UIControl来封装控件。

    a.从需求方面来看,这个控件不仅仅是展示内容,有可能需要实现点击事件。
    b.这个控件有可能存在选中状态和未选中状态等各种状态。
    c.当这个控件的尺寸过大时,我们有可能需要控件的内容实现居上、居中、居下、居左、居右 and so on.

  • UIControl相对于UIView的优点。

    众所周知,UIButton继承自UIControl.
    A、查看UIControl的API,可以发现如下内容:
    contentVerticalAlignment、contentHorizontalAlignment就是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类,我们想要做到实现点击事件以及选中等各种状态下的样式,可以参考UIButton的API进行封装。说白了,就是提供给外界使用的方法
- (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;

通过上述内容,应该总结UIControl以及UIButton的API方法,进行封装。

代码以及相关说明:

.h文件
.h文件提供了控件的Label以及ImageView属性。
同事实现了UIButton相似的方法以及快捷设置
(void)setImage:(UIImage*)image andTitleLableText:(NSString*)title

#import <UIKit/UIKit.h>
/** 上图下文组件 */
@interface RjxImageTitleView : UIControl

///上面图片
@property (nonatomic,strong) UIImageView          *topImageView;
///下面文本
@property (nonatomic,strong) UILabel              *titleLable;
///中间间隔
@property (nonatomic,assign) CGFloat               spaceBetweenTitleAndImage;


/**
 * @description 根据不同状态设置下面文本的值
 * @param title 文本内容 可以为空
 * @Param state UIControlState 枚举类型 状态值
 */
- (void)setTitle:(NSString *)title forState:(UIControlState)state;


/**
 * @description 根据不同状态设置下面文本的颜色
 * @param title 颜色
 * @Param state UIControlState 枚举类型 状态值
 */
- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state;

/**
 * @description 根据不同状态设置图片
 * @param image 图片
 * @Param state UIControlState 枚举类型 状态值
 */
- (void)setImage:(UIImage *)image forState:(UIControlState)state;

/**
 * @description 快捷设置上面图片和下面文本的值  这个时候状态默认为 UIControlStateNormal
 * @param image 图片
 * @Param title 文本的值
 */
- (void)setImage:(UIImage*)image andTitleLableText:(NSString*)title;

@end

///用于记录一些属性  当控件在不同状态的时候
@interface RjxImageTitleModel : NSObject
@property (nonatomic,strong) NSString    *strTitle;
@property (nonatomic,strong) UIColor     *color;
@property (nonatomic,strong) UIImage     *image;
@end

.m文件
.m文件内容较多。望仔细阅读,
[NSLayoutConstraint activateConstraints:activeConstraints];激活某些约束
[NSLayoutConstraint deactivateConstraints:activeConstraints];关闭某些约束

#import "RjxImageTitleView.h"

@interface RjxImageTitleView()

//字典记录相应属性和对应的值  值应该是 key @(UIControlState)  value : RjxImageTitleModel
@property (nonatomic,strong) NSMutableDictionary *dicProperty;

//底部标题距离上面图片的高度
@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;


}
//初始化控件
- (void)initView
{
    //
    _spaceBetweenTitleAndImage = 2.;

    UIView *contentView = [[UIView alloc] init];
    [self addSubview:contentView];
    contentView.backgroundColor = [UIColor yellowColor];

    //使用NSLayoutConstraint添加约束
    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];

// 一些位置约束 这里的约束就是用于contentVerticalAlignment和contentHorizontalAlignment来控制位置
    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];

// 这里分为横向纵向,分别将对用的值保存起来,
    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]

                                  ]];


    //正常的约束
    [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]
                                  ]];

    //这里是绑定上下控件间隙
    self.titleLableTopConstraint = [self.topImageView bottomToView:self.titleLable withSpace:self.spaceBetweenTitleAndImage];


    /// 设置默认
    self.contentVerticalAlignment = self.contentVerticalAlignment;
    self.contentHorizontalAlignment = self.contentHorizontalAlignment;

}

- (void)setContentHorizontalAlignment:(UIControlContentHorizontalAlignment)contentHorizontalAlignment
{
    //需要调用super 不然不会执行
    [super setContentHorizontalAlignment:contentHorizontalAlignment];
    [self setContentViewHorizontalPosition];

}
- (void)setContentVerticalAlignment:(UIControlContentVerticalAlignment)contentVerticalAlignment
{
    [super setContentVerticalAlignment:contentVerticalAlignment];
    [self setContentViewVerticalPosition];
}

/***
 *设置contentview 的位置 九宫格 九种位置 6大属性决定
 */
- (void)setContentViewHorizontalPosition
{
    //全部设置为不激活状态
    [NSLayoutConstraint deactivateConstraints:self.contentViewHorizontalConstraints.allValues];

    NSMutableArray *activeConstraints = [[NSMutableArray alloc] init];
    //横向
    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];

}

/***
 *设置contentview 的位置 九宫格 九种位置 6大属性决定
 */
- (void)setContentViewVerticalPosition
{
    //全部设置为不激活状态
    [NSLayoutConstraint deactivateConstraints:self.contentViewVerticalConstraints.allValues];

    NSMutableArray *activeConstraints = [[NSMutableArray alloc] init];

    //纵向
    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;

    }
    RjxImageTitleModel *model = [self getValueFromDicPropertyforKey:state];
    [self setImage:model.image andTitleLableText:model.strTitle];
    [self setTitleColor:model.color forState:UIControlStateSelected];
}
- (void)setHighlighted:(BOOL)highlighted
{

}

/**
 * @description 根据key获取值
 * @return RjxImageTitleModel 返回对应key的实体值
 */
- (RjxImageTitleModel*)getValueFromDicPropertyforKey:(UIControlState)state
{
    RjxImageTitleModel *model = nil;
    if (![self.dicProperty objectForKey:@(state)]) {
        model = [[RjxImageTitleModel alloc] init];
        [self.dicProperty setObject:model forKey:@(state)];
    }
    return model;
}



- (void)setTitle:(NSString *)title forState:(UIControlState)state
{
    if (title) {
        self.titleLable.text = title;
        RjxImageTitleModel *model = [self getValueFromDicPropertyforKey:state];
        model.strTitle = title;
    }

}

- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state
{
    if (color) {
        self.titleLable.textColor = color;
        RjxImageTitleModel *model = [self getValueFromDicPropertyforKey:state];
        model.color = color;
    }
}


- (void)setImage:(UIImage *)image forState:(UIControlState)state
{
    if (image) {
        self.topImageView.image = image;
        RjxImageTitleModel *model = [self getValueFromDicPropertyforKey:state];
        model.image = image;
    }
}


- (void)setImage:(UIImage*)image andTitleLableText:(NSString*)title
{
    [self setImage:image forState:UIControlStateNormal];
    [self setTitle:title forState:UIControlStateNormal];
}





/**属性懒加载**/

- (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

效果如下图:

调用方式如下图:
注意红色框内
这里写图片描述

这里写图片描述

如果不设置红色框内的两个值:默认是居中的。
这里写图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值