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

效果;

时间: 2024-10-21 08:59:29

UI基础之UITableView案例QQ聊天界面的相关文章

UI基础之UITableView案例QQ好友列表

一:模型数据 LLFriend #import <Foundation/Foundation.h> @interface LLFriend : NSObject /** * icon */ @property (nonatomic, copy) NSString *icon; /** * intro */ @property (nonatomic, copy) NSString *intro; /** * name */ @property (nonatomic, copy) NSString

UI基础之UITableView案例团购----自定义cell利用xib

一:模型数据: #import <Foundation/Foundation.h> @interface LLGroup : NSObject /** * icon */ @property (nonatomic, copy) NSString *icon; /** * title */ @property (nonatomic, copy) NSString *title; /** * buyCount */ @property (nonatomic, copy) NSString *buy

UI基础之UITableView案例微博----自定义cell利用代码

第一步:创建微博模型,完成字典转模型 #import <Foundation/Foundation.h> //#import <UIKit/UIKit.h> /** * 第一步:创建微博模型,完成字典转模型 */ @interface LLWeiBo : NSObject /** * icon */ @property (nonatomic, copy) NSString *icon; /** * name */ @property (nonatomic, copy) NSStri

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

一.知识点: QQ聊天界面 双模型的使用(dataModel和frameModel) UITextField的使用 通知的使用 拉伸图片的两种方法(slicing/image对象的resizeableImageWithCapInsets属性) 枚举 方法的抽取(相同的拿出,不同的部分作为参数) 二.设置tableview的基本格式 1)定义tableview基本 numberOfSectionsInTableView:设置块 numberOfRowsInSection:设置每块对应的行数 cel

亲身体验用Java写的仿qq聊天界面

Java开发工具有许多种,新手用记事本写Java程序,有些人用NetBean,jbuilder,高手用eclipse,下面介绍用eclipse开发qq聊天界面. 代码如下: package Myjava_QQ; import java.awt.*; import javax.swing.*; import Myjava_QQ.truess; import java.awt.event.*; import java.applet.*; import java.io.BufferedReader;

【3】QQ 聊天界面

1.说明 稍微修改了下QQ示例里面的聊天界面界面,然后把代码扣过来完成了QQ聊天界面部分,效果还可以. 2.代码部分 // QQTalk.h文件 #ifndef __QQ_TALK_H__ #define __QQ_TALK_H__ #include <DuiLib/DuiLibEnv.h> #include <DuiLib/UIlib.h> using namespace DuiLib; #define QQ_TALK_XML _T("chatbox.xml"

QQ聊天界面的输入法顶起界面底部输入框效果的实现

转载请注明:http://www.cnblogs.com/frank-zouxu/p/4127115.html 今天在公司做项目的时候遇到一个需求:需要做一个界面,效果类似QQ聊天界面,如图1,当我们点击内容输入框准备输入内容的时候,底部的表情框的那一栏会被输入法的软键盘给顶起来,默认状态下,输入法会覆盖掉我们的表情输入框.起初,百思不得解的我费尽了心思,未果,偶然看到此篇博客http://blog.csdn.net/twoicewoo/article/details/7384398.其实,欲达

简单模仿QQ聊天界面

首先看一下最终的效果,显示了消息时间,用户昵称,用户头像. 大致实现方法: 用最简单的ListView显示消息内容. 不同的用户使用不同的消息布局文件,例子有2个用户"Tony","Hill". 代码文件清单: 主布局文件activity_main.xml: 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools=&

[iOS基础控件 - 6.9] 聊天界面Demo

A.需求 做出一个类似于QQ.微信的聊天界面 1.每个cell包含发送时间.发送人(头像).发送信息 2.使用对方头像放在左边,我方头像在右边 3.对方信息使用白色背景对话框,我方信息使用蓝色背景对话框 4.隐藏相同的发送时间 5.底部功能按钮:语音按钮.消息输入框.表情按钮.附加按钮 6.响应键盘事件,呼出键盘.隐藏键盘时对上述的视图作出上移操作 7.键盘的发送事件处理 B.实现点 1.底层视图搭建 上部分聊天信息框:UITableView 下部分功能区:UIButton 信息输入框使用无边框