美文网首页iOS进阶+实战UI进价架构师之路
干货!老司机工作中用到的自定义控件,总有一个适合你的(二)

干货!老司机工作中用到的自定义控件,总有一个适合你的(二)

作者: 杂雾无尘 | 来源:发表于2016-11-27 16:21 被阅读3917次

    ** 时隔半个月,终于来更新第二篇了,大家有木有很期待! **


    一、一个强大的UITextView分类,让系统TextView自带placeholder属性、自动高度、支持输入图片三大功能

    1、效果:

    功能一、让系统TextView自带placeholder属性

    imageimage

    功能二、自动改变高度,类似聊天输入框

    imageimage

    功能三、支持输入图片

    imageimage
    2、使用方法:

    将UITextView+WZB.h和UITextView+WZB.m拖入工程

    只需要在需要使用的地方直接导入头文件UITextView+WZB.h,你的UITextView就拥有了这三大功能

    // 直接设置placeholder属性即可
        textView.placeholder = @"i love you";
        [self.view addSubview:textView];
        
    
    imageimage

    如果想要计算高度,只需要调用这个方法即可,你需要在block回调里手动更改textView的高度

    
    /* 自动高度的方法,maxHeight:最大高度, textHeightDidChanged:高度改变的时候调用 */
    - (void)autoHeightWithMaxHeight:(CGFloat)maxHeight textViewHeightDidChanged:(textViewHeightDidChangedBlock)textViewHeightDidChanged;
    
    

    如图

    imageimage

    插入图片的方法如下:

    
    /* 添加一张图片 image:要添加的图片 */
    - (void)addImage:(UIImage *)image;
    /* 添加一张图片 image:要添加的图片 size:图片大小 */
    - (void)addImage:(UIImage *)image size:(CGSize)size;
    /* 插入一张图片 image:要添加的图片 size:图片大小 index:插入的位置 */
    - (void)insertImage:(UIImage *)image size:(CGSize)size index:(NSInteger)index;
    
    /* 添加一张图片 image:要添加的图片 multiple:放大/缩小的倍数 */
    - (void)addImage:(UIImage *)image multiple:(CGFloat)multiple;
    /* 插入一张图片 image:要添加的图片 multiple:放大/缩小的倍数 index:插入的位置 */
    - (void)insertImage:(UIImage *)image multiple:(CGFloat)multiple index:(NSInteger)index;
    
    

    注释写的很清楚,效果如下:

    imageimage
    3、实现大致原理:

    使用runtime为textView添加如下属性

    
    // 占位文字
    static const void *WZBPlaceholderViewKey = &WZBPlaceholderViewKey;
    // 占位文字颜色
    static const void *WZBPlaceholderColorKey = &WZBPlaceholderColorKey;
    // 最大高度
    static const void *WZBTextViewMaxHeightKey = &WZBTextViewMaxHeightKey;
    // 高度变化的block
    static const void *WZBTextViewHeightDidChangedBlockKey = &WZBTextViewHeightDidChangedBlockKey;
    // 动态添加属性的本质是: 让对象的某个属性与值产生关联
    objc_setAssociatedObject(self, WZBPlaceholderViewKey, placeholderView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    objc_setAssociatedObject(self, WZBTextViewMaxHeightKey, [NSString stringWithFormat:@"%lf", maxHeight], OBJC_ASSOCIATION_COPY_NONATOMIC);
    objc_setAssociatedObject(self, WZBTextViewHeightDidChangedBlockKey, textViewHeightDidChanged, OBJC_ASSOCIATION_COPY_NONATOMIC);
    objc_setAssociatedObject(self, WZBPlaceholderColorKey, placeholderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    

    监听

    
        // 监听文字改变
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewTextChange) name:UITextViewTextDidChangeNotification object:self];
        // 这些属性改变时,都要作出一定的改变,尽管已经监听了TextDidChange的通知,也要监听text属性,因为通知监听不到setText:
        NSArray *propertys = @[@"frame", @"bounds", @"font", @"text", @"textAlignment", @"textContainerInset"];
        // 监听属性
        for (NSString *property in propertys) {
           [self addObserver:self forKeyPath:property options:NSKeyValueObservingOptionNew context:nil];
        }
        
    

    当文字发生变化的时候

    
    - (void)textViewTextChange {
        self.placeholderView.hidden = (self.attributedText.length > 0 && self.attributedText);
        if (self.maxHeight >= self.bounds.size.height) {
            // 计算高度
            NSInteger currentHeight = ceil([self sizeThatFits:CGSizeMake(self.bounds.size.width, MAXFLOAT)].height);
            NSInteger lastheight = ceil(self.maxHeight + self.textContainerInset.top + self.textContainerInset.bottom);
            // 如果高度有变化,调用block
            if (currentHeight != lastheight) {
                
                self.scrollEnabled = currentHeight >= self.maxHeight;
                if (self.textViewHeightDidChanged) {
                    self.textViewHeightDidChanged((currentHeight >= self.maxHeight ? self.maxHeight : currentHeight));
                }
            }
        }
    }
    
    

    添加图片是用的NSTextAttachment

    
    - (void)addImage:(UIImage *)image size:(CGSize)size index:(NSInteger)index multiple:(CGFloat)multiple {
        NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
        NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
        textAttachment.image = image;
        CGRect bounds = textAttachment.bounds;
        if (!CGSizeEqualToSize(size, CGSizeZero)) {
            bounds.size = size;
            textAttachment.bounds = bounds;
        } else if (multiple > 0.0f) {
            textAttachment.image = [UIImage imageWithCGImage:textAttachment.image.CGImage scale:multiple orientation:UIImageOrientationUp];
        } else {
            CGFloat oldWidth = textAttachment.image.size.width;
            CGFloat scaleFactor = oldWidth / (self.frame.size.width - 10);
            textAttachment.image = [UIImage imageWithCGImage:textAttachment.image.CGImage scale:scaleFactor orientation:UIImageOrientationUp];
        }
        
        NSAttributedString *attrStringWithImage = [NSAttributedString attributedStringWithAttachment:textAttachment];
        [attributedString replaceCharactersInRange:NSMakeRange(index, 0) withAttributedString:attrStringWithImage];
        self.attributedText = attributedString;
        // 记得走下这两个方法
        [self textViewTextChange];
        [self refreshPlaceholderView];
    }
    
    
    4、GitHub源码地址:UITextView-WZB

    二、一句话实现一个可以自动计算年龄和星座的DatePicker

    1、效果:
    普通显示在界面上普通显示在界面上
    从屏幕下边弹出从屏幕下边弹出
    做键盘显示做键盘显示
    2、使用方法:

    将WZBDatePicker.h和WZBDatePicker.m拖入工程

    只需要在需要使用的地方直接导入头文件WZBDatePicker.h,然后调用下边这个方法即可

    
    /* 显示方法 view:如果WZBDatePickerInputView传拥有inputView的控件,其他传普通的view,pickerType:显示方式 resultDidChange:滑动picker的时候调用  block参数age:年龄,constellation:星座 **/
        [WZBDatePicker showToView:self.view pickerType:WZBDatePickerNormal resultDidChange:^(NSString *age, NSString *constellation){
            // to do
        }];
        
    
    typedef NS_ENUM(NSInteger, WZBDatePickerType) {
        WZBDatePickerNormal = 0,    // 普通的显示在界面上
        WZBDatePickerInputView = 1,      // 做键盘显示
        WZBDatePickerBottomPop          // 从视图底部弹出
    };
    
    @interface WZBDatePicker : UIView
    
    /* 显示方法 view:如果WZBDatePickerInputView传拥有inputView的空间,其他传普通的view,pickerType:显示方式 resultDidChange:滑动picker的时候调用  block参数age:年龄,constellation:星座 **/
    + (instancetype)showToView:(UIView *)view pickerType:(WZBDatePickerType)pickerType resultDidChange:(void(^)(NSString *age, NSString *constellation))resultDidChange;
    
    /* 设置初始时间 **/
    - (void)setCurrentDate:(NSDate *)date;
    
    /* 隐藏 **/
    - (void)hidden;
    
    /* 是否有黑色半透明遮罩,默认没有,在pickerType!=WZBDatePickerBottomPop时不起任何作用 **/
    @property (nonatomic, assign, getter=isEnableDarkMask) BOOL enableDarkMask;
        
    

    h文件中提供了这些方法和属性,注释写的很清楚,可以直接使用。

    如果做键盘显示,需要这样:

    
    /* 显示方法 view:如果WZBDatePickerInputView传拥有inputView的空间,其他传普通的view,pickerType:显示方式 resultDidChange:滑动picker的时候调用  block参数age:年龄,constellation:星座 **/
        [WZBDatePicker showToView:self.textField pickerType:WZBDatePickerInputView resultDidChange:^(NSString *age, NSString *constellation){
            self.textField.text = [NSString stringWithFormat:@"%@--%@", age, constellation];
        }];
    
    

    注意,参数view,必须传带有inputView的控件,比如UITextField或UITextView等

    3、实现大致原理:

    里边是一个tableView,tableView的headerView是一个label,显示信息。tableView的footerView是个UIDatePicker,显示日期。这样写是因为比较好控制中间两行cell的显示与隐藏,headerView和footerView也不用单独管理size

    监听picker的滚动,并刷新tableView或者调用block更新时间,如果是键盘,隐藏了中间两行cell,所以不需要刷新tableView

    - (void)dateDidChanged:(UIDatePicker *)datePicker {
        self.checkedDate = datePicker.date;
        self.pickerType == WZBDatePickerInputView ? [self upData] : [self.tableView reloadData];
    }
    
    

    如果enableDarkMask为yes,背景颜色变成半透明颜色,并且启用单击手势

    
    - (void)setEnableDarkMask:(BOOL)enableDarkMask {
        _enableDarkMask = enableDarkMask;
        if (self.pickerType == WZBDatePickerBottomPop) {
            self.backgroundColor = self.isEnableDarkMask ? [UIColor colorWithWhite:0 alpha:0.2] : [UIColor clearColor];
        }
    }
    
    
    4、GitHub源码地址:WZBDatePicker

    三、一句话实现一个带有文字闪动渐变的标签

    1、效果:
    带有文字闪动渐变的label带有文字闪动渐变的label
    2、使用方法:

    将WZBGradualLabel.h和WZBGradualLabel.m拖入工程

    只需要在需要使用的地方直接导入头文件WZBGradualLabel.h,然后调用下边这个方法即可

    /*
         * frame:label的frame
         * title:text
         * duration:时间间隔
         * gradualWidth:渐变颜色的宽
         * superView:label的父控件
         **/
        [WZBGradualLabel gradualLabelWithFrame:(CGRect){10, 450, WZBScreenWidth - 20, 40} title:@"123456789012345678901234567890" duration:2  superview:self.view];
        
    
    效果效果

    下边是提供的一些属性和方法

    /*
    /* 渐变颜色色值,有默认值 **/
    @property (nonatomic, strong) NSArray *gradualColors;
    /*
     * frame:label的frame
     * title:text
     * duration:时间间隔
     * gradualWidth:渐变颜色的宽
     * superView:label的父控件
     **/
    + (instancetype)gradualLabelWithFrame:(CGRect)frame title:(NSString *)title duration:(NSTimeInterval)duration gradualWidth:(CGFloat)gradualWidth superview:(UIView *)superview;
    /*
     * frame:label的frame
     * title:text
     * superView:label的父控件
     **/
    + (instancetype)gradualLabelWithFrame:(CGRect)frame title:(NSString *)title superview:(UIView *)superview;
    /*
     * frame:label的frame
     * title:text
     * duration:时间间隔
     * superView:label的父控件
     **/
    + (instancetype)gradualLabelWithFrame:(CGRect)frame title:(NSString *)title duration:(NSTimeInterval)duration superview:(UIView *)superview;
    /*
     * frame:label的frame
     * title:text
     * gradualWidth:渐变颜色的宽
     * superView:label的父控件
     **/
    + (instancetype)gradualLabelWithFrame:(CGRect)frame title:(NSString *)title gradualWidth:(CGFloat)gradualWidth superview:(UIView *)superview;
        
    

    h文件中提供了这些方法和属性,注释写的很清楚,所有方法可以直接使用。colors是个数组,可以设置渐变层的颜色,至少传入两个值

    3、实现大致原理:
    原理分析原理分析

    其实看到层级图,它是有三层的,最底层的label就是你要显示的label,中间有层红色的部分,这个其实是渐变层view(截图没截好),最上层的label是渐变层的文字

    
        self.gradientLayer.mask = self.label.layer;
        
    

    这句话是设置渐变图层的mask为label图层,这样就可以用文字裁剪渐变图层了,只保留文字的部分

    至于动画改变,我用的是一个UIView动画,动态改变中间层View和渐变层label的x值,view是添加在底层label上的,上层label是添加在中间view上的,先让view在父控件的最左边,上层label在此view的右边,说白了就是让上层label和底层label完全重合,为了维持这一状态,中间的view向右走,上层label必须以同样的值向左走!具体请看代码:

    
    - (void)changX {
        __block CGRect frame1 = self.leftView.frame;
        __block CGRect frame2 = self.label.frame;
        frame1.origin.x = -self.gradualWidth;
        frame2.origin.x = self.gradualWidth;
        self.leftView.frame = frame1;
        self.label.frame = frame2;
        [UIView animateWithDuration:self.duration animations:^{
            frame1.origin.x = self.bounds.size.width;
            self.leftView.frame = frame1;
            frame2.origin.x = -self.bounds.size.width;
            self.label.frame = frame2;
        }];
    }
    
    

    kvo监听这些属性,也是为了维持上层label和底层label能完全重合的状态,以便支持用户对label进行文字对其、文字改变、文字换行、字体大小、frame、换行以及attributedText等操作

    // kvo监听属性
    for (NSString *property in self.propertys) {
        [self addObserver:self forKeyPath:property options:NSKeyValueObservingOptionNew context:nil];
    }
    
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
        if ([keyPath isEqualToString:@"text"]) {
            self.label.text = self.text;
        } else if ([keyPath isEqualToString:@"font"]) {
            self.label.font = self.font;
        } else if ([keyPath isEqualToString:@"textAlignment"]) {
            self.label.textAlignment = self.textAlignment;
        } else if ([keyPath isEqualToString:@"attributedText"]) {
            self.label.attributedText = self.attributedText;
        } else if ([keyPath isEqualToString:@"frame"]) {
            self.label.frame = (CGRect){self.label.frame.origin, self.frame.size};
        } else if ([keyPath isEqualToString:@"numberOfLines"]) {
            self.label.numberOfLines = self.numberOfLines;
        }
    }
    
    4、GitHub源码地址:WZBGradualLabel

    四、一行代码画一个表格,UIView的分类,可以很简单的画擅长表格

    1、效果:

    很多app用到了这种html元素效果,写了个demo
    效果如下:

    imageimage
    2、使用方法:

    只需要一行代码 ,可以自定义文字颜色、背景颜色、合并单元格、点击事件等操作

    /**
         * 创建一个表格
         * line:列数
         * columns:行数
         * data:数据
         */
        [v1 wzb_drawListWithRect:v1.bounds line:4 columns:3 datas:@[@"", @"语文", @"数学", @"英语", @"王晓明", @"100.5", @"128", @"95", @"李小华", @"100.5", @"128", @"95", @"张爱奇", @"100.5", @"128", @"95"]];
        
        
    
    /**
     * 创建一个表格
     * line:列数
     * columns:行数
     * data:数据
     */
    - (void)wzb_drawListWithRect:(CGRect)rect line:(NSInteger)line columns:(NSInteger)columns datas:(NSArray *)datas;
    
    /**
     * 创建一个表格
     * line:列数
     * columns:行数
     * data:数据
     * lineInfo:行信息,传入格式:@{@"0" : @"3"}意味着第一行创建3个格子
     */
    - (void)wzb_drawListWithRect:(CGRect)rect line:(NSInteger)line columns:(NSInteger)columns datas:(NSArray *)datas lineInfo:(NSDictionary *)lineInfo;
    
    /**
     * 创建一个表格
     * line:列数
     * columns:行数
     * data:数据
     * colorInfo:颜色信息,传入格式:@{@"0" : [UIColor redColor]}意味着第一个格子文字将会变成红色
     */
    - (void)wzb_drawListWithRect:(CGRect)rect line:(NSInteger)line columns:(NSInteger)columns datas:(NSArray *)datas colorInfo:(NSDictionary *)colorInfo;
    /**
     * 创建一个表格
     * line:列数
     * columns:行数
     * data:数据
     * colorInfo:颜色信息,传入格式:@{@"0" : [UIColor redColor]}意味着第一个格子文字将会变成红色
     * lineInfo:行信息,传入格式:@{@"0" : @"3"}意味着第一行创建3个格子
     */
    - (void)wzb_drawListWithRect:(CGRect)rect line:(NSInteger)line columns:(NSInteger)columns datas:(NSArray *)datas colorInfo:(NSDictionary *)colorInfo lineInfo:(NSDictionary *)lineInfo;
    /**
     * 创建一个表格
     * line:列数
     * columns:行数
     * data:数据
     * colorInfo:颜色信息,传入格式:@{@"0" : [UIColor redColor]}意味着第一个格子文字将会变成红色
     * lineInfo:行信息,传入格式:@{@"0" : @"3"}意味着第一行创建3个格子
     * backgroundColorInfo:行信息,传入格式:@{@"0" : [UIColor redColor]}意味着第一个格子背景颜色变成红色
     */
    - (void)wzb_drawListWithRect:(CGRect)rect line:(NSInteger)line columns:(NSInteger)columns datas:(NSArray *)datas colorInfo:(NSDictionary *)colorInfo lineInfo:(NSDictionary *)lineInfo backgroundColorInfo:(NSDictionary *)backgroundColorInfo;
    /**
     * 获取第index个格子的label
     */
    - (UILabel *)getLabelWithIndex:(NSInteger)index;
    
    /**
     * 画一条线
     * frame: 线的frame
     * color:线的颜色
     * lineWidth:线宽
     */
    - (void)wzb_drawLineWithFrame:(CGRect)frame lineType:(WZBLineType)lineType color:(UIColor *)color lineWidth:(CGFloat)lineWidth;
    
    
    
    

    .h文件中提供了这些方法,用法看注释即可,getLabelWithIndex:方法是得到第index个格子,比如你有10个格子,[view getLabelWithIndex:0];是得到第一个格子,可以对其进行任何操作,比如我在第三个表格中拿到右边三个label,添加单击手势进行跳转

    3、实现大致原理:
    
    /**
     * 创建一个表格
     * line:列数
     * columns:行数
     * data:数据
     * colorInfo:颜色信息,传入格式:@{@"0" : [UIColor redColor]}意味着第一个格子文字将会变成红色
     * lineInfo:行信息,传入格式:@{@"0" : @"3"}意味着第一行创建3个格子
     * backgroundColorInfo:行信息,传入格式:@{@"0" : [UIColor redColor]}意味着第一个格子背景颜色变成红色
     */
    - (void)wzb_drawListWithRect:(CGRect)rect line:(NSInteger)line columns:(NSInteger)columns datas:(NSArray *)datas colorInfo:(NSDictionary *)colorInfo lineInfo:(NSDictionary *)lineInfo backgroundColorInfo:(NSDictionary *)backgroundColorInfo {
        NSInteger index = 0;
        CGFloat x = rect.origin.x;
        CGFloat y = rect.origin.y;
        CGFloat h = (1.0) * rect.size.height / columns;
        NSInteger newLine = 0;
        for (NSInteger i = 0; i < columns; i++) {
            
            // 判断合并单元格
            if (lineInfo) {
                for (NSInteger a = 0; a < lineInfo.allKeys.count; a++) {
                    
                    // 新的列数
                    NSInteger newColumn = [lineInfo.allKeys[a] integerValue];
                    if (i == newColumn) {
                        newLine = [lineInfo[lineInfo.allKeys[a]] integerValue];
                    } else {
                        newLine = line;
                    }
                }
            } else {
                newLine = line;
            }
            
            
            for (NSInteger j = 0; j < newLine; j++) {
                
                // 线宽
                CGFloat w = (1.0) * rect.size.width / newLine;
                CGRect frame = (CGRect){x + w * j, y + h * i, w, h};
                
                // 画线
                [self wzb_drawRectWithRect:frame];
                
                // 创建label
                UILabel *label = [[UILabel alloc] initWithFrame:frame];
                
                // 文字居中
                label.textAlignment = NSTextAlignmentCenter;
                [self addSubview:label];
                
                // 判断文字颜色
                UIColor *textColor = [colorInfo objectForKey:[NSString stringWithFormat:@"%zd", index]];
                if (!textColor) {
                    textColor = [UIColor grayColor];
                }
                label.textColor = textColor;
                
                // 判断背景颜色
                UIColor *backgroundColor = [backgroundColorInfo objectForKey:[NSString stringWithFormat:@"%zd", index]];
                if (!backgroundColor) {
                    backgroundColor = [UIColor clearColor];
                }
                label.backgroundColor = backgroundColor;
                
                // 字体大小
                label.font = [UIFont systemFontOfSize:13];
                
                // label文字
                label.text = datas[index];
                
                // label的tag值
                label.tag = WZBTag + index;
                index++;
            }
        }
    }
    
    

    这是核心代码,其中做了合并单元格、文字颜色、背景颜色、等判断。画线是用的贝塞尔曲线和CAShapeLayer,代码在下边,每个单元格里都创建了label显示文字。我还提供了方法画一条直线,相信项目中很多页面某些位置需要画一条直线, - (void)wzb_drawLineWithFrame:(CGRect)frame lineType:(WZBLineType)lineType color:(UIColor *)color lineWidth:(CGFloat)lineWidth这个方法能够很方便的实现这一需求

    
    - (void)wzb_drawLineWithFrame:(CGRect)frame lineType:(WZBLineType)lineType color:(UIColor *)color lineWidth:(CGFloat)lineWidth {
        
        // 创建贝塞尔曲线
        UIBezierPath *linePath = [[UIBezierPath alloc] init];
        
        // 线宽
        linePath.lineWidth = lineWidth;
        
        // 起点
        [linePath moveToPoint:CGPointMake(0, 0)];
        
        // 重点:判断是水平方向还是垂直方向
        [linePath addLineToPoint: lineType == WZBLineHorizontal ? CGPointMake(frame.size.width, 0) : CGPointMake(0, frame.size.height)];
        
        // 创建CAShapeLayer
        CAShapeLayer *lineLayer = [CAShapeLayer layer];
        
        // 颜色
        lineLayer.strokeColor = color.CGColor;
        // 宽度
        lineLayer.lineWidth = lineWidth;
        
        // frame
        lineLayer.frame = frame;
        
        // 路径
        lineLayer.path = linePath.CGPath;
        
        // 添加到layer上
        [self.layer addSublayer:lineLayer];
    }
    
    
    

    下边画了一下随机颜色的线条,最终效果是这样:

    imageimage
    4、GitHub源码地址:UIView-WZB

    怎么样,这些您学会怎么用了吗?

    有不懂或者任何疑问的地方都可以在下方评论,或者随时联系我,您还可以用QQ扫描底部的二维码加入我们的技术交流群,让我们一起爱智求真,我在那里等着你!想看更多文章,入口在此:我的所有文章

    请不要吝惜,随手点个喜欢或者关注一下吧!您的支持是我最大的动力😊!
    此系列文章持续更新,还有些牛X控件因为尚未封装完善,被我砍下来放到下篇文章,您可以关注我以便及时查看我的最新文章或者您还可以加入我们的群,大家庭期待您的加入哦!

    我们的社区我们的社区

    相关文章

      网友评论

      • e85ed872d5c4:貌似不能改变某一列表格的宽度
      • Hai1丶HydrA:自动改变textview的高度的时候,为什么一定要设置placeholder才能自动增加高度,不设置placeholder不能自动改变高度?我看你的源码是在set的时候才监听的文字改变,那不需要placeHolder怎么办
        Hai1丶HydrA:@杂雾无尘 好滴,谢谢啦.还是很好用的~
        杂雾无尘:@Hai1丶HydrA 这是个bug,目前已经修复了,请到我的GitHub上下载最新源码。https://github.com/WZBbiao/UITextView-WZB
      • 努努Nunu:大神 表格的这个 如果可以编辑的话用啥写好点呢
        努努Nunu:@杂雾无尘 嗯嗯 三克油 真哒是秒回 :+1:
        杂雾无尘:@努努Nunu textfield吧
      • hhgvg:这个东西真用不了 第一次能换行 你第二次弹出键盘输入的时候就不行了 哎 不知道你们怎么说好用的
        杂雾无尘:@hhgvg 没发现您描述的第二次键盘弹出不能换行的问题,您可以私信我看能否帮您解决下!
      • c7fd7e0ef519:Mark~~
      • ca4debe814a1:牛逼啊,赶紧学习学习
      • 2349f65f6410:干货,简书有你更精彩!
      • 风的低语:写的很详实,干货👍
      • shuai_summer:将WZBTextView文件拖进工程, 为什么在push出来的界面添加UITetxView会造成pop回去,点击什么都无法响应?
        hhgvg:@shuai_summer 因为一直循环导致内存暴涨 界面卡死
        杂雾无尘:@shuai_summer 感谢您提的问题🙏,目前问题已经修复,请到我的GitHub上下载最新的版本https://github.com/WZBbiao/UITextView-WZB😊
        杂雾无尘:@shuai_summer 我回去看下
      • Easy_VO:已上老司机的车
      • 5f29619bda4d:很棒的总结
      • 119ae31c9761:棒:+1:🏻
      • 大牛的春天:很棒,工作中很有用
      • RBNote:喜欢,愿分享更多的很好的东西
      • coderChrisLee:干货,值得学习!

      本文标题:干货!老司机工作中用到的自定义控件,总有一个适合你的(二)

      本文链接:https://www.haomeiwen.com/subject/iwhnpttx.html