• Objective-c——UI基础开发第八天(QQ聊天界面)


    一、知识点:

      QQ聊天界面

      双模型的使用(dataModel和frameModel)

      UITextField的使用

      通知的使用

      拉伸图片的两种方法(slicing/image对象的resizeableImageWithCapInsets属性)

      枚举

      方法的抽取(相同的拿出,不同的部分作为参数)

    二、设置tableview的基本格式

    1)定义tableview基本

    numberOfSectionsInTableView:设置块

    numberOfRowsInSection:设置每块对应的行数

    cellForRowAtIndexPath:设置cell样式

    2)cell的重用

      设置cell 

    satic NSString *identifier =@"QQCell";

      先从缓存池中寻找

    QQCell *cell =[_tableview dequeuesableCellWithIdentifier:identifier];

      如果缓存池中找不到cell 就创建

    if(cell==nil)

    {cell =[[QQCell alloc]initWithStyle:UITableViewCellStyleDefault reuserIndentiier:identifier];}

    3)设定自定义的cell格式(注意为什么消息框是button:因为既可以设置文本,又可以设置图片)

    a、定义需要用到的属性及样式

    @property(nonatomic,weak)UILabel *timeLabel;

    @property(nonatomic,weak)UIButton *textButton;

    @property(nonatomic,weak)UIImageView *iconImage;

    b、定义初始化方法,注意与viewController中cell创建时调用的方法要一致

    -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{

    if(self =[super initWithStyle:style reuseIdentifier:reuseIdentifier]{

    [self setupUI];//在内部设置button、label之类的样式

    }}return self;

    c、双模型(在懒加载中将数据模型传递给frame模型:原因:
      1、懒加载中,方法只需要执行一次

      2、行高rowheight 方法必须在cell方法调用前调用,所以要在cell中实现frame的计算,传递出来顺序是有问题的

    传递方式: 在frameModel中定义QQModel这一属性

      a、定义model属性

      @class QQModel;

      @property (nonatomic ,strong) QQModel *qqModel;

      b、在懒加载中实现赋值

      QQModel *model =[QQModel QQmodelWithDictionary:dict];

      QQFrameModel *frameModel =[QQFrameModel alloc]init];

      frameModel.qqModel =model;//传递成功

      c、把frameModel的值传入dataArray数组中,因为这会frameModel中既有(数据model也包含各个控件的Frame)

      [_dataArray addObject:frameModel];

    d、如何根据文本数据内容,设置frame

      1)、设置最大可变动区域(如果无限制则:MAXFLOAT)

      CGSize maxArea =CGSizeMake(textMaxA,MAXFLOAT);

      2)、设置属性字典(注意属性字体大小的设置一定要和原先控件中字体大小一致,否则,可能文本中以省略号带过)

      NSDictionary *dict =@{NSFontAttributeName:[UIFont systemFontOfSize:17};

      3)、设置对象数据的真实大小boundingRectWithSize

      CGSize RealSize =[_qqModel.text boundingRectWithSize :maxArea options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context :nil].size;

      

    e、在cell的设置类中调用frameModel和数据模型并设置

      1)重写FrameModel的set方法:

    @property(nonatomic,strong) QQFrameModel *frameModel;

    -(void)setFrameModel:(QQFrameModel *)frameModel{

       2)必须对模型进行实例化

    _frameModel =frameModel;

      3)设置模型中的数据和Frame

    }

      怎么获取qqModel

      #import “QQModel.h”

      QQModel *qqModel =_frameModel.qqModel;

    f、代码实现图片拉伸

    /**

    1、获取图片

    2、设置拉伸 线条构成的中心区域(区域越小越好,所以将宽高都设成其中心线)

    3、调用image对象的resizableImageWithCapInSets属性

    */

    UIImage *image =[UIImage imageNamed:imageName];

    CGFloat *halfWidth =image.size.width/2;

    CGFloat *halfHeight =image.size.height/2;

    UIImage *resizeImage =[image resizableImageWithCapInsets:UIEdgeInsetsMake(halfHeight,halfWidth,halfHeight,halfWidth) resizingMode:UIImageResizingModeStretch];

    g、注意图片拉伸之后,文本可能不在图片内部,可以通过增加button的frame大小,同时设置文本的那边距(contentEdgeInsets UIEdgeInsetsMake)

    textButton.contentEdgeInsets =UIEdgeInsetsMake(20,20,20,20);

    h、设置行高

    heightForRowAtIndexPath

    QQ FrameModel *frameModel =self.dataArray[indexPath.row];

    return frameModel.cellHeight

    三、比较时间(两两比较,同一时间内的label只显示一遍,可以知道,只要比较一次,而且又要获得上一次的时间,最好在懒加载中实现)

    /**

    0、在qqModel中设置一个HiddenTimeLabel属性 存储比较完的结果

    1、取出上一次的数据

    2、进行比较,如果一样的话,就往qqModel 中传入HiddenTimeLabel=YES 

    */

    @property (nonatomic,assign,getter = isHiddenTimeLabel) BOOL HiddenTimeLabel;

    QQFrameModel *latFrameModel =self.dataArray.lastObject;

    if([lastFrameModel.qqModel.time isEqualToString :frameModel.qqModel.time])

    {

    qqModel.HiddenTimeLabel=YES;

    }

    调用:

    _timeLabel.hidden =qqModel.isHiddenTimeLabel;(在hidden属性中直接调用重写的get方法即可)

    四、补充使用枚举(内部的值类别,枚举的值名称,默认从0开始)

    typedef NS_ENUM(NSInteger,QQUserType)

    {

    QQUserTypeOther=0;

    QQuserTypeMe,

    };

    枚举的好处:将无意义的数字转化成有意义的字符,增加代码可读性

    五、设置底部的弹框(了解textField属性和通知概念)

    五.1 TextField 的使用

    textField.placeholder=@"占位符"

     UIView *left =[[UIView alloc]initWithFrame:CGRectMake(100, 0, 10, 10)];

        left.backgroundColor=[UIColor orangeColor];

        text.leftView=left;

        text.leftViewMode = UITextFieldViewModeAlways;

    (添加leftview的时候必须要设置UITextFieldViewMode否则无法显示

    leftview/rightview/leftViewMode/rightViewMode

    密码:
    text.secureTextEntry=YES;

    text.cleanButtonMode =UITextFieldViewModeWhileEditing;

    五、2)通知的使用

    /**

    1、注册监听者

    2、通知中心发布通知

    3、将销毁的监听者移除监听

    */ 

    1

     /**

             addObserver: 监听对象

             selector:监听对象收到通知之后调用的方法

             name:通知的名称

             object: 通知的发布者

             */

            [[NSNotificationCenter defaultCenter] addObserver:ZhangSan selector:@selector(recieveNotification:) name:@"HuoYing" object:souhuHuoYing];

    2

    /**

     接受通知之后,要执行的方法

     */

    -(void) recieveNotification:(NSNotification *)noti

    {

        NSDictionary *c = noti.userInfo;

        Company *company = c[@"company"];

        NSLog(@"%@ 订阅了 %@公司的 %@视频已经更新了",self.personname,company.companyname,company.moviename);

      //  NSLog(@"%@",noti);

    }

    3

    -(void) dealloc

    {

        [[NSNotificationCenter defaultCenter]removeObserver:self.personname];

    }

    五、3)设置键盘监听,通过监听传递出的通知,改变底部输入框的frame和tableview的frame

      1、// 添加监听,  键盘即将隐藏的时候, 调用

        [[NSNotificationCenter defaultCenter] addObserver:self

                                                 selector:@selector(keyboardWillDisAppear:)

                                                     name:UIKeyboardWillHideNotification

                                                   object:nil];

        调用的监听通知名称包括:UIKeyboardWillHideNotification /键盘即将隐藏的通知名

    name:UIKeyboardWillChangeFrameNotification/键盘隐藏或出现的通知名

    UIKeyboardWillShowNotification/键盘出现的通知名

    2、收到通知消息时要执行的动画:(UIView animateWithDuration)

    [UIView animateWithDuration:interval animations:^{

                       self.view.transform = CGAffineTransformMakeTranslation(0, (keyboardEndY - keyboardBeginY));

            }];

    3、用户如果滚动tableview的时候,或者用户输入完成按return的时候,键盘都需要消失

    - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {

           // 撤销textField 的第一响应者身份

        [_textField resignFirstResponder];

    }

    4、默认的时候,tableview都应该滚动到最后一行(UITableView scrollToRowAtIndexPath)

    - (void)scrollToBottom {

        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.dataArray.count - 1 inSection:0];

        [_tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];

    }

    5、既然是聊天框,那么cell就不应该有被选中时候的颜色(selectionStyle)

     // 选中cell后不改变颜色

            cell.selectionStyle = UITableViewCellSelectionStyleNone;

    6、撤销监听

    #warning 一定不要忘记移除监听者

    - (void)dealloc {

        [[NSNotificationCenter defaultCenter] removeObserver:self];

    }

    六、设置时间格式

    /**

    1、取出时间(NSDate date)

    2、初始化格式NSDateFormatter (NASDateFormatter) formatter.dateformat(属性)

    3、日期转字符 formatter stringFromDate:currentDate

    */

       // 取出当前的时间

        NSDate *currentDate = [NSDate date];

        // 设置时间的格式

        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

        // 时间格式

        // yyyy-MM-dd HH:mm:ss  时间格式

        formatter.dateFormat = @"HH:mm";

       

        NSString *dateString = [formatter stringFromDate:currentDate];

    七、通知和代理的区别

    共同:都可以传递消息

    区别:代理是一对一传递,通知是多对多,可以有多个消息发布者和多个消息接收者

    例如,代理可以知道textfiled什么时候开始输入值,什么时候结束输入值,但是像键盘这种弹入弹出它的时间都是不可控的,需要实时监测这个就需要通知中心发布消息。

  • 相关阅读:
    计算器类(C++&JAVA——表达式转换、运算、模板公式)
    使用/\_ 打印正三角形 C/C++
    Triangle2D类(Java)
    让键盘输入不影响界面的动态效果(C++)
    Java 7.21 游戏:豆机(C++&Java)
    Java 7.35 游戏:猜字游戏(C++&Java)
    Java 8.9 游戏:井字游戏(C++&Java)
    JAVA 8.20 游戏:四子连(Java&C++)
    简易Java文本编译器(C++)
    PAT 1089 狼人杀-简单版(20 分)(代码+测试点分析)
  • 原文地址:https://www.cnblogs.com/CityPe/p/5370385.html
Copyright © 2020-2023  润新知