zoukankan      html  css  js  c++  java
  • UI基础之UITableView案例QQ聊天界面

    数据模型:

    #import <Foundation/Foundation.h>
    
    typedef enum{
        LLMessageTypeMe,
        LLMessageTypeOther
    }LLMessageType;
    
    @interface LLMessage : NSObject
    
    /**
     *  time
     */
    @property (nonatomic, copy) NSString *time;
    
    /**
     *  text
     */
    @property (nonatomic, copy) NSString *text;
    
    /**
     *  type 定义为枚举类型的好处
     */
    @property (nonatomic, assign) LLMessageType type;
    
    /**
     *  hiddenTime 时间是否隐藏
     */
    @property (nonatomic, assign, getter=isHiddenTime) BOOL hiddenTime;
    
    - (instancetype)initWithDic:(NSDictionary *)dic;
    + (instancetype)messageWithDic:(NSDictionary *)dic;
    
    + (NSMutableArray *)messageList;
    
    @end
    #import "LLMessage.h"
    
    @implementation LLMessage
    
    - (instancetype)initWithDic:(NSDictionary *)dic
    {
        if (self = [super init]) {
            [self setValuesForKeysWithDictionary:dic];
        }
        return self;
    }
    
    + (instancetype)messageWithDic:(NSDictionary *)dic
    {
        return [[self alloc] initWithDic:dic];
    }
    
    + (NSMutableArray *)messageList
    {
        NSString *path = [[NSBundle mainBundle] pathForResource:@"messages" ofType:@"plist"];
        NSArray *dicArr = [NSArray arrayWithContentsOfFile:path];
        
        NSMutableArray *tmpArr = [[NSMutableArray alloc] initWithCapacity:dicArr.count];
        for (NSDictionary *dic in dicArr) {
            LLMessage *endMessage = [tmpArr lastObject];
            LLMessage *message = [LLMessage messageWithDic:dic];
            
            if ([message.time isEqualToString:endMessage.time]) {
                
                message.hiddenTime = YES;
            }
            
            [tmpArr addObject:message];
        }
        return tmpArr;
    }
    
    @end

    frame模型

    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    #define LLTIMEFONT [UIFont systemFontOfSize:12]
    #define LLTEXTFONT [UIFont systemFontOfSize:13]
    #define LLPADDING 20
    @class LLMessage;
    @interface LLMessageFrame : NSObject
    
    @property (nonatomic, strong) LLMessage *message;
    
    @property (nonatomic, assign,readonly) CGRect timeF;
    
    @property (nonatomic, assign, readonly) CGRect textF;
    
    @property (nonatomic, assign, readonly) CGRect iconF;
    
    @property (nonatomic, assign, readonly) CGFloat cellHeight;
    
    + (NSMutableArray *)messageFrameList;
    
    @end
    #import "LLMessageFrame.h"
    #import "LLMessage.h"
    #import "NSString+LLNSStringExtension.h"
    @implementation LLMessageFrame
    
    + (NSMutableArray *)messageFrameList
    {
        NSMutableArray *messageArr = [LLMessage messageList];
        NSMutableArray *tmpArray = [[NSMutableArray alloc] initWithCapacity:messageArr.count];
        for (LLMessage *message in messageArr) {
            LLMessageFrame *frame = [[LLMessageFrame alloc] init];
            frame.message = message;
            [tmpArray addObject:frame];
        }
        return tmpArray;
    }
    
    - (void)setMessage:(LLMessage *)message
    {
        _message = message;
        
        CGFloat margin = 10;
        // 时间
        CGFloat timeX = 0;
        CGFloat timeY = 0;
        CGFloat timeW = 320;
        CGFloat timeH = 40;
        if (!message.isHiddenTime){
            _timeF = CGRectMake(timeX, timeY, timeW, timeH);
        }
        
        // icon
        CGFloat iconY = CGRectGetMaxY(_timeF);
        CGFloat iconWH = 30;
        CGFloat iconX;
        if (message.type == LLMessageTypeMe) { // Me
            
            iconX = timeW - iconWH - margin;
        } else { // Other
            
            iconX = margin;
        }
        _iconF = CGRectMake(iconX, iconY, iconWH, iconWH);
        
        // text
        CGFloat textY = iconY;
        CGSize textSize = [message.text textOfSize:CGSizeMake(200, MAXFLOAT) font:LLTEXTFONT];
        CGSize buttonSize = CGSizeMake(textSize.width + LLPADDING * 2, textSize.height + LLPADDING * 2);
        CGFloat textX;
        if (message.type == LLMessageTypeMe) { // Me
            
            textX = iconX - margin - buttonSize.width;
        } else {
            
            textX = CGRectGetMaxX(_iconF) + margin;
        }
        _textF = (CGRect){{textX, textY} , buttonSize};
        
        CGFloat textMaxY = CGRectGetMaxY(_textF);
        CGFloat iconMaxY = CGRectGetMaxY(_iconF);
        
        _cellHeight = MAX(textMaxY, iconMaxY);
        
    }
    
    @end

    代码自定义cell

    #import <UIKit/UIKit.h>
    @class LLMessageFrame;
    @interface LLMessageCell : UITableViewCell
    
    @property (nonatomic, strong) LLMessageFrame *messageFrame;
    
    + (instancetype)messageCellWith:(UITableView *)tableView;
    
    @end
    #import "LLMessageCell.h"
    #import "LLMessageFrame.h"
    #import "LLMessage.h"
    #import <UIKit/UIKit.h>
    #import "UIImage+LLUIImageExtension.h"
    @interface LLMessageCell ()
    
    @property (nonatomic, weak) UILabel *timeView;
    @property (nonatomic, weak) UIImageView *iconView;
    @property (nonatomic, weak) UIButton *textView;
    
    @end
    
    @implementation LLMessageCell
    
    + (instancetype)messageCellWith:(UITableView *)tableView
    {
        static NSString *ID = @"messageCell";
        LLMessageCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
        if (!cell) {
            
            cell = [[LLMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
        }
        return cell;
    }
    
    - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
    {
        if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
            
            // 创建cell子控件
            self.backgroundColor = [UIColor clearColor];
            // time
            UILabel *timeView = [[UILabel alloc] init];
            [self.contentView addSubview:timeView];
            timeView.textAlignment = NSTextAlignmentCenter;
            timeView.font = LLTIMEFONT;
            self.timeView = timeView;
            
            // icon
            UIImageView *iconView = [[UIImageView alloc] init];
            [self.contentView addSubview:iconView];
            self.iconView = iconView;
            
            // text
            UIButton *textView = [[UIButton alloc] init];
            [self.contentView addSubview: textView];
            textView.titleLabel.font = LLTEXTFONT;
            textView.titleLabel.numberOfLines = 0;
            textView.contentEdgeInsets = UIEdgeInsetsMake(LLPADDING, LLPADDING, LLPADDING, LLPADDING);
            self.textView = textView;
            
            
        }
        return self;
    }
    
    - (void)setMessageFrame:(LLMessageFrame *)messageFrame
    {
        _messageFrame = messageFrame;
        
        // 1,设置数据
        [self setDate];
        
        // 2,设置frame
        [self setSubviewsFrame];
    }
    
    - (void)setDate
    {
        LLMessage *message = self.messageFrame.message;
        self.timeView.text = message.time;
        
        NSString *iconName = message.type == LLMessageTypeMe ? @"me" : @"other";
        self.iconView.image = [UIImage imageNamed:iconName];
        // 设置图片背景
        
        
    #warning 设置按钮上label字体方法
        [self.textView setTitle:message.text forState:UIControlStateNormal];
        if (message.type == LLMessageTypeMe) {
            [self.textView setBackgroundImage:[UIImage registerImage:@"chat_send_nor"] forState:UIControlStateNormal];
            [self.textView setBackgroundImage:[UIImage registerImage:@"chat_send_press_pic"] forState:UIControlStateHighlighted];
            [self.textView setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
        } else {
            [self.textView setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
            [self.textView setBackgroundImage:[UIImage registerImage:@"chat_recive_nor"] forState:UIControlStateNormal];
            [self.textView setBackgroundImage:[UIImage registerImage:@"chat_recive_press_pic"] forState:UIControlStateHighlighted];
        }
    }
    
    - (void)setSubviewsFrame
    {
        self.timeView.frame = self.messageFrame.timeF;
        self.iconView.frame = self.messageFrame.iconF;
        self.textView.frame = self.messageFrame.textF;
    }
    
    
    @end

    分类:NSString

    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    
    @interface NSString (LLNSStringExtension)
    
    - (CGSize)textOfSize:(CGSize)maxSize font:(UIFont *)font;
    
    @end
    
    #import "NSString+LLNSStringExtension.h"
    
    @implementation NSString (LLNSStringExtension)
    
    - (CGSize)textOfSize:(CGSize)maxSize font:(UIFont *)font
    {
        return [self boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : font} context:nil].size;
    }
    
    @end

    UIImage分类

    #import <UIKit/UIKit.h>
    
    @interface UIImage (LLUIImageExtension)
    
    + (UIImage *)registerImage:(NSString *)imageName;
    
    @end
    
    
    
    #import "UIImage+LLUIImageExtension.h"
    #import <UIKit/UIKit.h>
    @implementation UIImage (LLUIImageExtension)
    
    + (UIImage *)registerImage:(NSString *)imageName
    {
        UIImage * image = [UIImage imageNamed:imageName];
        return [image stretchableImageWithLeftCapWidth:image.size.width * 0.5 topCapHeight:image.size.height * 0.5];
    }
    
    @end

    controller:

    #import "ViewController.h"
    #import "LLMessageFrame.h"
    #import "LLMessage.h"
    #import "LLMessageCell.h"
    
    @interface ViewController () <UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate>
    
    @property (nonatomic, strong) NSMutableArray *messageFrames;
    
    @property (weak, nonatomic) IBOutlet UITableView *tableView;
    
    @property (weak, nonatomic) IBOutlet UIView *footerView;
    @property (weak, nonatomic) IBOutlet UITextField *textField;
    
    @end
    
    @implementation ViewController
    
    #pragma mark - 懒加载数据模型
    - (NSMutableArray *)messageFrames
    {
        if (!_messageFrames) {
            
           _messageFrames = [LLMessageFrame messageFrameList];
        }
        return _messageFrames;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        // 隐藏分割线
        self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
        
        // 取消tableView的点击
        self.tableView.allowsSelection = NO;
    
        self.tableView.backgroundColor = [UIColor colorWithRed:240/255.0 green:224/255.0 blue:224/255.0 alpha:1.0];
        
        // 监听通知
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(clickTextFiled:) name:UIKeyboardWillChangeFrameNotification object:nil];
        
        // 设置文本框左边内容默认有间距
        self.textField.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 8, 0)];
        self.textField.leftViewMode = UITextFieldViewModeAlways;
    }
    
    - (void)clickTextFiled:(NSNotification *)noti
    {
        CGRect rect = [noti.userInfo[@"UIKeyboardFrameEndUserInfoKey"] CGRectValue];
        CGFloat moveY = rect.origin.y - self.view.frame.size.height;
        self.view.transform = CGAffineTransformMakeTranslation(0, moveY);
    }
    
    - (void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    
    #pragma mark - 数据源方法
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return self.messageFrames.count;
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        // 1,创建cell
        LLMessageCell *cell = [LLMessageCell messageCellWith:tableView];
        
        // 2,设置cell
        cell.messageFrame = self.messageFrames[indexPath.row];
        
        return cell;
    }
    
    #pragma mark - 代理方法
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        return [self.messageFrames[indexPath.row] cellHeight];
    }
    
    - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
    {
        [self.view endEditing:YES];
    }
    
    #pragma mark - 文本框代理方法
    - (BOOL)textFieldShouldReturn:(UITextField *)textField
    {
        LLMessageFrame *frame = [[LLMessageFrame alloc] init];
        LLMessage *message = [[LLMessage alloc] init];
        NSDate *date = [NSDate date];
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        formatter.dateFormat = @"hh:mm";
        NSString *time = [formatter stringFromDate:date];
        message.time = time;
        message.text = textField.text;
        message.type = LLMessageTypeMe;
        LLMessageFrame *lastMF = [self.messageFrames lastObject];
        if ([lastMF.message.time isEqualToString:message.time]) {
            message.hiddenTime = YES;
        }
            frame.message = message;
        [self.messageFrames addObject:frame];
        
        // 刷新
        [self.tableView reloadData];
        
        // 自动上滚
        NSIndexPath *path = [NSIndexPath indexPathForRow:self.messageFrames.count - 1 inSection:0];
        [self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionBottom animated:YES];
        
        
        textField.text = nil;
        return YES;
    }
    
    - (BOOL)prefersStatusBarHidden
    {
        return YES;
    }
    
    @end

    效果;

  • 相关阅读:
    【转】VS2010中 C++创建DLL图解
    [转]error: 'retainCount' is unavailable: not available in automatic reference counting mode
    [转]关于NSAutoreleasePool' is unavailable: not available in automatic reference counting mode的解决方法
    【转】 Tomcat v7.0 Server at localhost was unable to start within 45
    【转】Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds. If
    【转】SVN管理多个项目版本库
    【转】eclipse安装SVN插件的两种方法
    【转】MYSQL启用日志,和查看日志
    【转】Repository has not been enabled to accept revision propchanges
    【转】SVN库的迁移
  • 原文地址:https://www.cnblogs.com/-boy/p/4133663.html
Copyright © 2011-2022 走看看