OC 简单的实现购买产品的规格选择

1.使用ProAttrSelectView类实现,代码如下:

#import <UIKit/UIKit.h>
@class ProAttrSelectView;
@protocol ProAttrSelectViewDelegate <NSObject>
@optional
- (void)proAttrSelectView:(ProAttrSelectView *)view didClickSureWithAttrs:(NSMutableArray *)attrs count:(NSInteger)count;
@end
@interface ProAttrSelectView : UIView
- (instancetype)initWithData:(NSArray *)data;
/**当前选择的属性集合*/
@property (nonatomic, strong)NSMutableArray *selectedAttrs;
/**当前选择的商品数量*/
@property (nonatomic, assign)NSInteger *selectedCount;
@property (nonatomic, weak)id<ProAttrSelectViewDelegate>delegate;
- (void)show;
- (void)dismiss;
@end
//属性单元视图
@class AttrSectionView;
@protocol AttrSectionViewDelegate <NSObject>
@optional
- (void)attrSectionView:(AttrSectionView *)view didSelectedAttr:(NSString *)attr atSection:(NSInteger )section;
@end
@interface AttrSectionView : UIView
/**初始化 传入当前属性数据以及分区的号*/
- (instancetype)initWithFrame:(CGRect)frame andData:(NSDictionary *)data andSection:(NSInteger )section;
/**设置属性中的某一个属性按钮是否可用*/
- (void)setAttrEnable:(BOOL)enable withTitle:(NSString *)title;
@property (nonatomic, weak)id<AttrSectionViewDelegate>delegate;
@end
//属性按钮
@interface AttrBtn : UIButton
+ (AttrBtn *)attrBtnWithTitle:(NSString *)title;
@end
//计数视图
@interface CountView : UIView
/**当前的数量 默认为1*/
@property (nonatomic, assign)NSUInteger count;
@end
#import "ProAttrSelectView.h"
#define View_Max_Height (UI_SCREEN_HEIGHT - HOME_INDICATOR_HEIGHT - HeightForNagivationBarAndStatusBar - 100)
#define Attr_Btn_Height 30.0f

@interface ProAttrSelectView()<UIGestureRecognizerDelegate,AttrSectionViewDelegate>
/**承载所有内容的视图*/
@property (nonatomic, strong)UIView *contentView;
/**产品图片*/
@property (nonatomic, strong)UIImageView *imageV;
/**产品价格*/
@property (nonatomic, strong)UILabel *priceL;
/**属性描述*/
@property (nonatomic, strong)UILabel *desL;
/**承载属性的滑动视图*/
@property (nonatomic, strong)UIScrollView *attrScrollView;
/**删除按钮*/
@property (nonatomic, strong)UIButton *deleteBtn;
/**确定按钮*/
@property (nonatomic, strong)UIButton *sureBtn;
/**后台的属性数据*/
@property (nonatomic, strong)NSArray *dataSource;
/**计数视图*/
@property (nonatomic, strong)CountView *countV;
@end
@implementation ProAttrSelectView

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/
- (instancetype)initWithData:(NSArray *)data {
    if ([super init]) {
        self.layer.masksToBounds = YES;
        self.dataSource = data;
        self.selectedAttrs = [NSMutableArray array];
        [self setUpView];
        
    }
    return self;
}
#pragma mark - 设置界面
- (void)setUpView{
    self.frame = CGRectMake(0, 0, UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT - HOME_INDICATOR_HEIGHT);
    self.backgroundColor =  RGBA(0, 0, 0, 0.4);
    self.userInteractionEnabled = YES;
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
    tap.delegate = self;
    [self addGestureRecognizer:tap];
    [self addSubview:self.contentView];
    
    [self.contentView addSubview:self.imageV];
    [self.contentView addSubview:self.priceL];
    [self.contentView addSubview:self.desL];
    [self.contentView addSubview:self.deleteBtn];
    //添加分割线1
    UIView *line1 = [[UIView alloc]initWithFrame:CGRectMake(0, 119, UI_SCREEN_WIDTH, 1)];
    line1.backgroundColor = [UIColor groupTableViewBackgroundColor];
    [self.contentView addSubview:line1];
    //添加属性分区
    [self.contentView addSubview:self.attrScrollView];
    
    CGFloat attrSectionY = 0;
    for (int i = 0; i < self.dataSource.count; i++) {
        AttrSectionView *view = [[AttrSectionView alloc]initWithFrame:CGRectMake(0, attrSectionY, UI_SCREEN_WIDTH, 0) andData:self.dataSource[i] andSection:i];
        view.delegate = self;
        [self.attrScrollView addSubview:view];
        attrSectionY += view.height;
        
        [self.selectedAttrs addObject:@""];
    }
    //添加计数
    self.countV = [[CountView alloc]initWithFrame:CGRectMake(0, attrSectionY, UI_SCREEN_WIDTH, 50)];
    [self.attrScrollView addSubview:self.countV];
    //设置最终的contentsize
    self.attrScrollView.contentSize = CGSizeMake(UI_SCREEN_WIDTH, self.countV.maxY);
    
    
    //添加分割线2
    UIView *line2 = [[UIView alloc]initWithFrame:CGRectMake(0, self.attrScrollView.maxY, UI_SCREEN_WIDTH, 1)];
    line2.backgroundColor = [UIColor groupTableViewBackgroundColor];
    [self.contentView addSubview:line2];
    //确定按钮
    [self.contentView addSubview:self.sureBtn];
    //配置contentView最终高度
    if (self.attrScrollView.contentSize.height < self.self.attrScrollView.height ) {
        self.attrScrollView.height = self.attrScrollView.contentSize.height;
        self.contentView.height = self.attrScrollView.maxY + 60;
        line2.y = self.attrScrollView.maxY;
        self.sureBtn.y = line2.maxY + 10;
    }
}
#pragma mark - 某个属性被选中
- (void)attrSectionView:(AttrSectionView *)view didSelectedAttr:(NSString *)attr atSection:(NSInteger )section {
    [self.selectedAttrs replaceObjectAtIndex:section withObject:attr];
    self.desL.text = [NSString stringWithFormat:@"已经选择:%@", [self.selectedAttrs componentsJoinedByString:@" "]];
}
#pragma makr - 懒加载内容视图
- (UIScrollView *)attrScrollView {
    if (!_attrScrollView) {
        _attrScrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 120, UI_SCREEN_WIDTH, self.contentView.height - 180)];
        _attrScrollView.backgroundColor = [UIColor whiteColor];
    }
    return _attrScrollView;
}
- (UIView *)contentView {
    if (!_contentView) {
        _contentView = [[UIView alloc]initWithFrame:CGRectMake(0, UI_SCREEN_HEIGHT - HOME_INDICATOR_HEIGHT, UI_SCREEN_WIDTH, View_Max_Height)];
        //绘制圆角
        UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:_contentView.bounds byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight cornerRadii:CGSizeMake(15, 15)];
        CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
        maskLayer.frame = _contentView.bounds;
        maskLayer.path = path.CGPath;
        _contentView.layer.mask = maskLayer;
        _contentView.backgroundColor = [UIColor whiteColor];
    }
    return _contentView;
}
- (UIImageView *)imageV {
    if (!_imageV) {
        _imageV = [[UIImageView alloc]initWithFrame:CGRectMake(10, 10, 100, 100)];
        _imageV.backgroundColor = [UIColor grayColor];
        _imageV.layer.cornerRadius = 5;
        _imageV.layer.masksToBounds = YES;
    }
    return _imageV;
}
- (UILabel *)priceL {
    if (!_priceL) {
        _priceL = [[UILabel alloc]initWithFrame:CGRectMake(self.imageV.maxX + 10, 70, UI_SCREEN_HEIGHT - 50, 20)];
        _priceL.font = [UIFont systemFontOfSize:15];
        _priceL.text = @"商品价格暂无";
        _priceL.textColor = [UIColor redColor];
        _priceL.backgroundColor = [UIColor whiteColor];
    }
    return _priceL;
}
- (UIButton *)deleteBtn {
    if (!_deleteBtn) {
        _deleteBtn = [[UIButton alloc]initWithFrame:CGRectMake(UI_SCREEN_WIDTH - 30, 10, 20, 20)];
        [_deleteBtn setImage:[UIImage imageNamed:@"icon_delete"] forState:UIControlStateNormal];
        [_deleteBtn addTarget:self action:@selector(dismiss) forControlEvents:UIControlEventTouchUpInside];
    }
    return _deleteBtn;
}
- (UILabel *)desL {
    if (!_desL) {
        _desL = [[UILabel alloc]initWithFrame:CGRectMake(self.priceL.x, self.priceL.maxY, self.priceL.width, 20)];
        _desL.font = [UIFont systemFontOfSize:14];
        _desL.text = @"请选择商品属性";
        _desL.textColor = [UIColor blackColor];
        _desL.backgroundColor = [UIColor whiteColor];
    }
    return _desL;
}
- (UIButton *)sureBtn {
    if (!_sureBtn) {
        _sureBtn = [[UIButton alloc]initWithFrame:CGRectMake(20, self.attrScrollView.maxY + 10, UI_SCREEN_WIDTH - 40, 40)];
        _sureBtn.backgroundColor = [UIColor redColor];
        [_sureBtn setTitle:@"确定" forState:UIControlStateNormal];
        [_sureBtn addTarget:self action:@selector(sureAction) forControlEvents:UIControlEventTouchUpInside];
        _sureBtn.layer.cornerRadius = 20;
        _sureBtn.layer.masksToBounds = YES;
        [_sureBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    }
    return _sureBtn;
}
#pragma mark - 确定按钮
- (void)sureAction {
    for (NSString *attr in self.selectedAttrs) {
        if ([attr isEqualToString:@""]) {
            NSLog(@"您还有属性还没有选中");
            return;
        }
    }
   
    [self dismiss];
    if ([self.delegate respondsToSelector:@selector(proAttrSelectView:didClickSureWithAttrs:count:)]) {
        [self.delegate proAttrSelectView:self didClickSureWithAttrs:self.selectedAttrs count:self.countV.count];
    }
}
#pragma mark - 弹出视图
- (void)show {
    [[self lastWidow] addSubview:self];
    [UIView animateWithDuration:0.3 animations:^{
        [self.contentView setFrame:CGRectMake(0, UI_SCREEN_HEIGHT - HOME_INDICATOR_HEIGHT - self.contentView.height, UI_SCREEN_WIDTH, self.contentView.height)];
    }];
}
#pragma mark - 点击方法
- (void)tapAction:(UITapGestureRecognizer *)tap {
    if (CGRectContainsPoint(self.contentView.frame, [tap locationInView:self])) {
        
    }else {
        [self dismiss];
    }
}
#pragma mark - 隐藏视图
- (void)dismiss {
    [UIView animateWithDuration:0.3 animations:^{
        [self.contentView setFrame:CGRectMake(0, UI_SCREEN_HEIGHT - HOME_INDICATOR_HEIGHT, UI_SCREEN_WIDTH, self.contentView.height)];
    } completion:^(BOOL finished) {
        [self removeFromSuperview];
    }];
}
#pragma mark - 获取最上层window
- (UIWindow *)lastWidow{
    NSArray *windows = [UIApplication sharedApplication].windows;
    for (UIWindow *window in [windows reverseObjectEnumerator]) {
        if ([window isKindOfClass:[UIWindow class]] && CGRectEqualToRect(window.bounds, [UIScreen mainScreen].bounds)) {
            return window;
        }
    }
    return [UIApplication sharedApplication].keyWindow;
}

@end


@interface AttrSectionView()
/**属性单元的数据*/
@property (nonatomic, strong)NSDictionary *data;
/**属性单元的类型*/
@property (nonatomic, strong)UILabel *attrTypeL;
/**已经选中的属性*/
@property (nonatomic, strong)NSString *selectedAttr;
@end
@implementation AttrSectionView
#define Attr_Btn_H 10.0f //按钮左右间距
#define Attr_Btn_V 10.0f //按钮上下间距

- (instancetype)initWithFrame:(CGRect)frame andData:(NSDictionary *)data andSection:(NSInteger )section{
    if ([super initWithFrame:frame]) {
        _data = data;
        self.tag = section;
        [self setupView];
    }
    return self;
}
#pragma mark - 设置视图
- (void)setupView {
    [self addSubview:self.attrTypeL];
    //配置属性按钮
    NSArray *array = self.data.allValues.firstObject;
    //布局过程中当前按钮的最大X
    CGFloat lastMaxX = Attr_Btn_H;
    //布局过程中当前按钮最大的Y
    CGFloat lastMaxY =  40;
    for (int i = 0; i < array.count; i++) {
        AttrBtn *btn = [AttrBtn attrBtnWithTitle:array[i]];
        [btn addTarget:self action:@selector(attrBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
        if (btn.width + lastMaxX + Attr_Btn_H > self.frame.size.width) {
            //如果这个按钮的宽度过大,两种情况一种是这一行只有这一个按钮,它就是太长 ,另一种是还有别的按钮,要换行
            if (lastMaxX == Attr_Btn_H) {
                //第一种情况 独占一行
                btn.frame = CGRectMake(lastMaxX, lastMaxY, self.frame.size.width - 2 * Attr_Btn_H, btn.height);
                //最大高度改变
                lastMaxY = lastMaxY + btn.height + Attr_Btn_V;
            }else {
                //需要换行
                lastMaxY = lastMaxY + btn.height + Attr_Btn_V;
                lastMaxX = Attr_Btn_H;
                btn.frame = CGRectMake(lastMaxX, lastMaxY, btn.width + lastMaxX + Attr_Btn_H > self.width ? self.width - 2 * Attr_Btn_H : btn.width, btn.height);
                lastMaxX = btn.maxX + Attr_Btn_H;
            }
        }else {
            //可以放得下,不需要换行
            btn.frame = CGRectMake(lastMaxX, lastMaxY, btn.width, btn.height);
            lastMaxX = lastMaxX + btn.width + Attr_Btn_H;
        }
        [self addSubview:btn];
    }
    //设置高度
    self.frame = CGRectMake(self.x, self.y, self.width, lastMaxY + Attr_Btn_Height + Attr_Btn_H);
}
#pragma mark - 设置某个属性是否可用
- (void)setAttrEnable:(BOOL)enable withTitle:(NSString *)title {
    for (UIView *subV in self.subviews) {
        if ([subV isKindOfClass:[AttrBtn class]]) {
            AttrBtn *tempBtn = (AttrBtn *)subV;
            //根据标题获取到属性按钮
            if ([title isEqualToString:tempBtn.titleLabel.text]) {
                if (tempBtn.enabled == enable) {
                    break;
                }else {
                    tempBtn.enabled = enable;
                    if (tempBtn.isEnabled != YES && tempBtn.isSelected == YES) {
                        self.selectedAttr = nil;
                        tempBtn.selected = NO;
                    }
                    //设置背景颜色
                    if (tempBtn.isEnabled == YES) {
                        tempBtn.alpha = 1;
                    }else {
                        tempBtn.alpha = 0.5;
                    }
                }
                break;
            }
        }
    }
}
#pragma mark - 点击属性按钮
- (void)attrBtnClicked:(AttrBtn *)btn {
    if (btn.isSelected == YES) {
        btn.selected = NO;
        if ([self.delegate respondsToSelector:@selector(attrSectionView:didSelectedAttr:atSection:)]) {
            [self.delegate attrSectionView:self didSelectedAttr:@"" atSection:self.tag];
        }
        return;
    }
    for (UIView *subV in self.subviews) {
        if ([subV isKindOfClass:[AttrBtn class]]) {
            AttrBtn *tempBtn = (AttrBtn *)subV;
            tempBtn.selected = NO;
        }
    }
    btn.selected = YES;
    if ([self.delegate respondsToSelector:@selector(attrSectionView:didSelectedAttr:atSection:)]) {
        [self.delegate attrSectionView:self didSelectedAttr:btn.titleLabel.text atSection:self.tag];
    }
}
#pragma mark - 懒加载
- (UILabel *)attrTypeL {
    if (!_attrTypeL) {
        _attrTypeL = [[UILabel alloc]initWithFrame:CGRectMake(10, 0, UI_SCREEN_WIDTH, 40)];
        _attrTypeL.font = [UIFont systemFontOfSize:15];
        _attrTypeL.textColor = [UIColor blackColor];
        _attrTypeL.text = self.data.allKeys.firstObject;
    }
    return _attrTypeL;
}

@end

//实现属性按钮
@implementation AttrBtn
+ (AttrBtn *)attrBtnWithTitle:(NSString *)title {
    AttrBtn *btn = [super buttonWithType:UIButtonTypeCustom];
    [btn setTitle:title forState:UIControlStateNormal];
    btn.titleLabel.font = [UIFont systemFontOfSize:13];
    btn.layer.cornerRadius = 5;
    btn.layer.masksToBounds = YES;
    //设置处于未点击状态下的按钮
    btn.backgroundColor = [UIColor groupTableViewBackgroundColor];
    [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    //设置处于点击状态下的按钮
    [btn setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected];
    //设置尺寸 按钮内部文字 + 20空隙
    CGSize size = [btn.titleLabel sizeThatFits:CGSizeMake(CGFLOAT_MAX, 30)];
    btn.frame = CGRectMake(0, 0, size.width + 20, Attr_Btn_Height);
    //监听按钮的点击状态
    [btn addObserver:btn forKeyPath:@"selected" options:NSKeyValueObservingOptionNew context:nil];
    return btn;
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if (object == self && [keyPath isEqualToString:@"selected"]) {
        if (self.selected) {
            //选中状态
            self.backgroundColor = [UIColor redColor];
            self.layer.borderWidth = 1;
            self.layer.borderColor = [UIColor redColor].CGColor;
        }else {
            //未选中状态
            self.backgroundColor = [UIColor groupTableViewBackgroundColor];
            self.layer.borderWidth = 0;
        }
    }
}

@end


@interface CountView()<UITextFieldDelegate>
/**减按钮*/
@property (nonatomic, strong)UIButton *minusBtn;
/**计数输入框*/
@property (nonatomic, strong)UITextField *countT;
/**加按钮*/
@property (nonatomic, strong)UIButton *plusBtn;
@end
@implementation CountView
- (instancetype)initWithFrame:(CGRect)frame {
    if ([super initWithFrame:frame]) {
        //强行设置frame 的宽高
        self.frame = CGRectMake(frame.origin.x, frame.origin.y, UI_SCREEN_WIDTH, 50);
        self.backgroundColor = [UIColor whiteColor];
        self.count = 1;
        [self setupView];
    }
    return self;
}
- (void)setupView {
    UILabel *tagL = [[UILabel alloc]initWithFrame:CGRectMake(10, 0, 120, self.height)];
    tagL.backgroundColor = [UIColor whiteColor];
    tagL.text = @"购买数量";
    tagL.textColor = [UIColor blackColor];
    [self addSubview:tagL];
    
    [self addSubview:self.minusBtn];
    [self addSubview:self.countT];
    [self addSubview:self.plusBtn];
}
#pragma mark - 懒加载计数视图
- (UIButton *)minusBtn {
    if (!_minusBtn) {
        _minusBtn = [[UIButton alloc]initWithFrame:CGRectMake(UI_SCREEN_WIDTH - 112, 10, 30, 30)];
        _minusBtn.backgroundColor = [UIColor groupTableViewBackgroundColor];
        _minusBtn.alpha = 0.5;
        [_minusBtn addTarget:self action:@selector(minusAction) forControlEvents:UIControlEventTouchUpInside];
        [_minusBtn setTitle:@"-" forState:UIControlStateNormal];
        [_minusBtn setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
        //刚开始时不能再减
        _minusBtn.enabled = NO;
    }
    return _minusBtn;
}
- (UITextField *)countT {
    if (!_countT) {
        _countT = [[UITextField alloc]initWithFrame:CGRectMake(self.minusBtn.maxX + 1, self.minusBtn.y, 40, 30)];
        _countT.backgroundColor = [UIColor groupTableViewBackgroundColor];
        _countT.alpha = 0.5;
        _countT.delegate = self;
        _countT.text = @"1";
        _countT.textColor = [UIColor blackColor];
        _countT.textAlignment = NSTextAlignmentCenter;
        _countT.keyboardType = UIKeyboardTypeNumberPad;
    }
    return _countT;
}
- (UIButton *)plusBtn {
    if (!_plusBtn) {
        _plusBtn = [[UIButton alloc]initWithFrame:CGRectMake(_countT.maxX + 1, _countT.y, 30, 30)];
        _plusBtn.backgroundColor = [UIColor groupTableViewBackgroundColor];
        _plusBtn.alpha = 0.5;
        [_plusBtn setTitle:@"+" forState:UIControlStateNormal];
        [_plusBtn setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
        [_plusBtn addTarget:self action:@selector(plusAction) forControlEvents:UIControlEventTouchUpInside];
    }
    return _plusBtn;
}
#pragma mark - 减号方法
- (void)minusAction {
    if (self.countT.text.integerValue <= 1) {
        return;
    }else {
        self.countT.text = [NSString stringWithFormat:@"%ld",self.countT.text.integerValue - 1];
        if ([self.countT.text isEqualToString:@"1"]) {
            self.minusBtn.enabled = NO;
        }else {
            self.minusBtn.enabled = YES;
        }
        self.count = self.countT.text.integerValue;
    }
}
#pragma mark -结束输入
- (void)textFieldDidEndEditing:(UITextField *)textField {
    if (textField.text.integerValue < 1) {
        textField.text = @"1";
    }
    if ([textField.text isEqualToString:@"1"]) {
        self.minusBtn.enabled = NO;
    }else {
        self.minusBtn.enabled = YES;
    }
    self.count = self.countT.text.integerValue;
}
#pragma mark - 增加
- (void)plusAction {
    self.countT.text = [NSString stringWithFormat:@"%ld",self.countT.text.integerValue + 1];
    if ([self.countT.text isEqualToString:@"1"]) {
        self.minusBtn.enabled = NO;
    }else {
        self.minusBtn.enabled = YES;
    }
    self.count = self.countT.text.integerValue;
}
@end

2.使用方法:

ProAttrSelectView *view = [[ProAttrSelectView alloc]initWithData:@[
                            @{@"颜色":@[@"红色",@"白色",@"黑色",@"金色"]},
                            @{@"内存":@[@"16GB",@"32GB",@"64GB",@"128GB",@"256GB",@"512GB"]}
                            ]];
            view.delegate = self;
            [view show];
- (void)proAttrSelectView:(ProAttrSelectView *)view didClickSureWithAttrs:(NSMutableArray *)attrs count:(NSInteger)count {
    NSLog(@"%@:%ld",attrs,count);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值