• IOS开发基础知识--碎片18


    1:initWithFrame方法的理解

    1. initWithFrame方法是什么?
    initWithFrame方法用来初始化并返回一个新的视图对象,根据指定的CGRect(尺寸)。
    当然,其他UI对象,也有initWithFrame方法,但是,我们以UIView为例,来搞清楚initWithFrame方法。
    
    2.什么时候用initWithFrame方法?
    简单的说,我们用编程方式申明,创建UIView对象时,使用initWithFrame方法。
    在此,我们必须搞清楚,两种方式来进行初始化UIView。
    a.使用 Interface Builder 方式。
    这种方式,就是使用nib文件。通常我们说的“拖控件” 的方式。
    实际编程中,我们如果用Interface Builder 方式创建了UIView对象。(也就是,用拖控件的方式)
    那么,initWithFrame方法方法是不会被调用的。因为nib文件已经知道如何初始化该View。(因为,我们在拖该view的时候,就定义好了长、宽、背景等属性)。
    这时候,会调用initWithCoder方法,我们可以用initWithCoder方法来重新定义我们在nib中已经设置的各项属性。
    
    b.使用编程方式。
    就是我们声明一个UIView的子类,进行“手工”编写代码的方式。
    实际编程中,我们使用编程方式下,来创建一个UIView或者创建UIView的子类。这时候,将调用initWithFrame方法,来实例化UIView。
    特别注意,如果在子类中重载initWithFrame方法,必须先调用父类的initWithFrame方法。在对自定义的UIView子类进行初始化操作。
    比如:
    - (id)initWithFrame:(CGRect)frame{
        self = [super initWithFrame:frame];// 先调用父类的initWithFrame方法
        if (self) {
            
            // 再自定义该类(UIView子类)的初始化操作。
            _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
            [_scrollView setFrame:CGRectMake(0, 0, 320, 480)];
            _scrollView.contentSize = CGSizeMake(320*3, 480);
            
            [self addSubview:_scrollView];
        }
        return self;
    }

    2:layoutSubviews总结

    layoutSubviews在以下情况下会被调用:
    a、init初始化不会触发layoutSubviews
       但是是用initWithFrame 进行初始化时,当rect的值不为CGRectZero时,也会触发
    b、addSubview会触发layoutSubviews
    c、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化
    d、滚动一个UIScrollView会触发layoutSubviews
    e、旋转Screen会触发父UIView上的layoutSubviews事件
    f、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件
    
    layoutSubviews, 当我们在某个类的内部调整子视图位置时,需要调用。反过来的意思就是说:如果你想要在外部设置subviews的位置,就不要重写。layoutSubviews对subviews重新布局,layoutSubviews方法调用先于drawRect
    
    刷新子对象布局
    -layoutSubviews方法:这个方法,默认没有做任何事情,需要子类进行重写
    -setNeedsLayout方法: 标记为需要重新布局,异步调用layoutIfNeeded刷新布局,不立即刷新,但layoutSubviews一定会被调用
    -layoutIfNeeded方法:如果,有需要刷新的标记,立即调用layoutSubviews进行布局(如果没有标记,不会调用layoutSubviews)
    如果要立即刷新,要先调用[view setNeedsLayout],把标记设为需要布局,然后马上调用[view layoutIfNeeded],实现布局
    在视图第一次显示之前,标记总是“需要刷新”的,可以直接调用[view layoutIfNeeded]

    3:单元行有其它控件时,行选中时关于控件高亮的问题

    此处是cell中的accessoryView放一UIButton,在行被选中的情况下,UIButton同时也被高亮处于被选中的壮态,通过下面这样处理可以解决问题
    
    @interface UCaiTableViewCell : UITableViewCell
    
    @end
    
    @implementation UCaiTableViewCell
    
    @synthesize piosaDelegate = _piosaDelegate;
    
    - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated{
        [super setHighlighted:highlighted animated:animated];
        
        if (highlighted) {
            [(UIButton *)self.accessoryView setHighlighted:NO];
        }
    }
    
    - (void)setSelected:(BOOL)selected animated:(BOOL)animated{
        [super setSelected:selected animated:animated];
        
        if (selected) {
            [(UIButton *)self.accessoryView setHighlighted:NO];
        }
    }

    4:UIButton高亮效果去除

    继承UIButton然后可以重写setHighlighed方法,里面什么内容也不写;
    
    .H文件:
    
    #import <UIKit/UIKit.h>
    
    @interface HWEmotionTabBarButton : UIButton
    
    @end
    
    
    .M文件:
    
    #import "HWEmotionTabBarButton.h"
    
    @implementation HWEmotionTabBarButton
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            // 设置文字颜色
            [self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
            [self setTitleColor:[UIColor darkGrayColor] forState:UIControlStateDisabled];
            // 设置字体
            self.titleLabel.font = [UIFont systemFontOfSize:13];
        }
        return self;
    }
    
    - (void)setHighlighted:(BOOL)highlighted {
        // 按钮高亮所做的一切操作都不在了
    }
    @end

    5:一个选项卡的封装

    .H文件内容
    
    #import <UIKit/UIKit.h>
    
    typedef enum {
        HWEmotionTabBarButtonTypeRecent, // 最近
        HWEmotionTabBarButtonTypeDefault, // 默认
        HWEmotionTabBarButtonTypeEmoji, // emoji
        HWEmotionTabBarButtonTypeLxh, // 浪小花
    } HWEmotionTabBarButtonType;
    
    @class HWEmotionTabBar;
    
    @protocol HWEmotionTabBarDelegate <NSObject>
    
    @optional
    - (void)emotionTabBar:(HWEmotionTabBar *)tabBar didSelectButton:(HWEmotionTabBarButtonType)buttonType;
    @end
    
    @interface HWEmotionTabBar : UIView
    @property (nonatomic, weak) id<HWEmotionTabBarDelegate> delegate;
    @end
    
    注意:这边主要是要引入@class
    
    
    .M文件内容:
    
    @interface HWEmotionTabBar()
    @property (nonatomic, weak) HWEmotionTabBarButton *selectedBtn;
    @end
    
    @implementation HWEmotionTabBar
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            [self setupBtn:@"最近" buttonType:HWEmotionTabBarButtonTypeRecent];
            [self setupBtn:@"默认" buttonType:HWEmotionTabBarButtonTypeDefault];
    //        [self btnClick:[self setupBtn:@"默认" buttonType:HWEmotionTabBarButtonTypeDefault]];
            [self setupBtn:@"Emoji" buttonType:HWEmotionTabBarButtonTypeEmoji];
            [self setupBtn:@"浪小花" buttonType:HWEmotionTabBarButtonTypeLxh];
        }
        return self;
    }
    
    /**
     *  创建一个按钮
     *
     *  @param title 按钮文字
     */
    - (HWEmotionTabBarButton *)setupBtn:(NSString *)title buttonType:(HWEmotionTabBarButtonType)buttonType
    {
        // 创建按钮
        HWEmotionTabBarButton *btn = [[HWEmotionTabBarButton alloc] init];
        [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown];
        btn.tag = buttonType;
        [btn setTitle:title forState:UIControlStateNormal];
        [self addSubview:btn];
        
        // 设置背景图片
        NSString *image = @"compose_emotion_table_mid_normal";
        NSString *selectImage = @"compose_emotion_table_mid_selected";
        if (self.subviews.count == 1) {
            image = @"compose_emotion_table_left_normal";
            selectImage = @"compose_emotion_table_left_selected";
        } else if (self.subviews.count == 4) {
            image = @"compose_emotion_table_right_normal";
            selectImage = @"compose_emotion_table_right_selected";
        }
        
        [btn setBackgroundImage:[UIImage imageNamed:image] forState:UIControlStateNormal];
        [btn setBackgroundImage:[UIImage imageNamed:selectImage] forState:UIControlStateDisabled];
        
        return btn;
    }
    
    - (void)layoutSubviews
    {
        [super layoutSubviews];
        
        // 设置按钮的frame
        NSUInteger btnCount = self.subviews.count;
        CGFloat btnW = self.width / btnCount;
        CGFloat btnH = self.height;
        for (int i = 0; i<btnCount; i++) {
            HWEmotionTabBarButton *btn = self.subviews[i];
            btn.y = 0;
            btn.width = btnW;
            btn.x = i * btnW;
            btn.height = btnH;
        }
    }
    
    - (void)setDelegate:(id<HWEmotionTabBarDelegate>)delegate
    {
        _delegate = delegate;
        
        // 选中“默认”按钮
        [self btnClick:(HWEmotionTabBarButton *)[self viewWithTag:HWEmotionTabBarButtonTypeDefault]];
    }
    
    /**
     *  按钮点击
     */
    - (void)btnClick:(HWEmotionTabBarButton *)btn
    {
        //转换被选中的效果
        self.selectedBtn.enabled = YES;
        btn.enabled = NO;
        self.selectedBtn = btn;
        
        // 通知代理
        if ([self.delegate respondsToSelector:@selector(emotionTabBar:didSelectButton:)]) {
            [self.delegate emotionTabBar:self didSelectButton:btn.tag];
        }
    }
    
    @end
    
    注意:当增加完控件后,self.subviews.count这个值就是从1开始,而setDelegate则是为了用来显示默认被选中,因为有枚举所以可以很准确定位到想设置默认的那个UIButton,UIControlStateDisabled这个状态是为了当被选中后就不能再点击,配合着enabled设置,代码中创建的一个属性用于存放当前被选中的UIButton,在事件btnClick中对它进行转换赋值;

     6:UITextField实现获取光标但第一次不弹出键盘

    实现原理如下先在上面的盖一层视图,然后增加点击事件,主要代码如下:

        if (!_myTextField) {
            _myTextField=[UITextField new];
            _myTextField.font=[UIFont fontWithName:@"Helvetica-Bold" size:40];
            _myTextField.textColor=[UIColor blackColor];
            _myTextField.delegate=self;
            _myTextField.tintColor=[UIColor blackColor];
            _myTextField.text=self.billing_amount;
            _myTextField.textAlignment=NSTextAlignmentLeft;
            _myTextField.keyboardType=UIKeyboardTypeNumberPad;
            _myTextField.userInteractionEnabled=YES;
            _myTextField.inputView=[[UIView alloc]initWithFrame:CGRectZero];
            [_myTextField becomeFirstResponder];
            [self addSubview:_myTextField];
            [_myTextField mas_makeConstraints:^(MASConstraintMaker *make) {
                make.left.mas_equalTo(_myPriceBadgeLabel.right).offset(AdaptedSize(0));
                make.top.mas_equalTo(_myPriceBadgeLabel.top);
                make.right.mas_equalTo(-AdaptedSize(15));
            }];
        }
        
        if (!_topTextFieldView) {
            _topTextFieldView=[UIView new];
            [_topTextFieldView bk_whenTapped:^{
                _myTextField.inputView=nil;
                [_topTextFieldView removeFromSuperview];
                [_myTextField reloadInputViews];
            }];
            [self addSubview:_topTextFieldView];
            
            [_topTextFieldView mas_makeConstraints:^(MASConstraintMaker *make) {
                make.edges.mas_equalTo(_myTextField);
            }];
        }
  • 相关阅读:
    如何进行市场洞察?
    敏捷开发团队的四种组织形式
    RxJava + Retrofit源码解析
    Node.js基础入门第七天
    Node.js基础入门第十天
    Node.js基础入门第八天
    Node.js基础入门第九天
    android 线程更新UI的问题
    svelte组件:svelte3自定义桌面PC端对话框组件sveltelayer
    进程通讯 & Binder机制 & Service 笔记
  • 原文地址:https://www.cnblogs.com/wujy/p/4631745.html
Copyright © 2020-2023  润新知