iOS学习08代码2
来源:互联网 发布:阿里云搭建hadoop 编辑:程序博客网 时间:2024/05/24 07:33
两个小例子涉及到的知识:
1. 代码自定义cell,且高度不同
2. 文本在屏幕宽高的计算
3. 图片拉伸
4. 通知机制
5. 键盘处理
6. 代理设计模式
7. 模型中有模型
8. 自定义tableView每组的headerView
QQ聊天界面
// Controller// ViewController.m// 1107-QQcel//// Created by 修修 on 15/11/7.// Copyright © 2015年 cn.Xsoft. All rights reserved.//#import "ViewController.h"#import "SLMessageFrame.h"#import "SLMessage.h"#import "SLMessageCell.h"@interface ViewController () <UITableViewDataSource, UITableViewDelegate, UITextViewDelegate>@property (weak, nonatomic) IBOutlet UITableView *tableView;/** * 模型数组 */@property (nonatomic, strong) NSMutableArray *messageFrames;/** * 下面的工具条 */@property (weak, nonatomic) IBOutlet UIView *toolView;/** * 文本框 */@property (weak, nonatomic) IBOutlet UITextField *textView;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; // 设置tableview的背景色 self.tableView.backgroundColor = [UIColor colorWithRed:224/255.0 green:224/255.0 blue:224/255.0 alpha:1.0]; // 去除tableview的分割线 self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; // 注册监听器 NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; [center addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil]; // 光标位置 UIView *rigthview = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 8, 0)]; self.textView.leftView = rigthview; self.textView.leftViewMode = UITextFieldViewModeAlways; }/** * 当return按下后调用 */- (BOOL)textFieldShouldReturn:(UITextField *)textField{ // 拿到文本框中的文字 NSString *content = textField.text; SLMessage *newMessage = [[SLMessage alloc] init]; // 内容 newMessage.text = content; // 类型 newMessage.type = MessageTypeMe; // 时间 NSDate *now = [NSDate date]; NSDateFormatter *format = [[NSDateFormatter alloc] init]; format.dateFormat = @"HH:mm"; newMessage.time = [format stringFromDate:now]; // 时间是否与上一条一样 SLMessageFrame *lastFrame = [self.messageFrames lastObject]; SLMessage *lastMessage = lastFrame.message; newMessage.sameTime = [newMessage.time isEqualToString:lastMessage.time]; // 增加模型 SLMessageFrame *newFrame = [[SLMessageFrame alloc] init]; newFrame.message = newMessage; [self.messageFrames addObject:newFrame]; // 刷新界面 [self.tableView reloadData]; // 立即滚到所发的信息(最后一行) NSIndexPath *lastPath = [NSIndexPath indexPathForRow:self.messageFrames.count - 1 inSection:0]; [self.tableView scrollToRowAtIndexPath:lastPath atScrollPosition:UITableViewScrollPositionBottom animated:YES]; // 清空文本 self.textView.text = nil; // 通常都是返回yes return YES;}- (void)dealloc{ // 移除监听器 [[NSNotificationCenter defaultCenter] removeObserver:self];}// 收到通知后调用- (void)keyboardWillChangeFrame:(NSNotification *)notification{ // 取出通知中的的字典 NSDictionary *userInfoDict = notification.userInfo; // 获得动画时间 CGFloat animTime = [userInfoDict[UIKeyboardAnimationDurationUserInfoKey] floatValue]; // 键盘的高度 CGFloat keybroadY = [userInfoDict[UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y; // view的变化高度 CGFloat tranY = keybroadY - self.view.frame.size.height; // 动画 [UIView animateWithDuration:animTime animations:^{ self.view.transform = CGAffineTransformMakeTranslation(0, tranY); }]; }// 去除屏幕的状态栏- (BOOL)prefersStatusBarHidden { return YES;}# pragma mark - getter懒加载方法- (NSMutableArray *)messageFrames{ if (_messageFrames == nil) { // 拿到plist里的数组 NSString *path = [[NSBundle mainBundle] pathForResource:@"messages.plist" ofType:nil]; NSArray *tempAry = [NSArray arrayWithContentsOfFile:path]; // 可变数组,临时保存模型的数据 NSMutableArray *tempMuary = [NSMutableArray array]; // 遍历数组,完成字典转模型 for (NSDictionary *dict in tempAry) { // 通过字典初始化模型 SLMessage *message = [SLMessage messageWithDict:dict]; // 判断当前消息的时间是否与上一条消息相同,如果相同,不要显示时间 // 拿到上一个位置模型,就是可变数组的最后一个元素 SLMessageFrame *pastFrame = [tempMuary lastObject]; // 得到数据模型 SLMessage *pastMes = pastFrame.message; // 判断事件是否相同 if ([pastMes.time isEqualToString:message.time]) { // 将数据模型的sameTime设置为YES message.sameTime = YES; } // 初始化位置模型 SLMessageFrame *messageframe = [[SLMessageFrame alloc] init]; // 给位置模型中的数据模型赋值,同时会计算出相应控件的位置 messageframe.message = message; // 将位置模型添加到可变数组中 [tempMuary addObject:messageframe]; } _messageFrames =tempMuary; } return _messageFrames;}#pragma mark - tableView数据源方法- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return self.messageFrames.count;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ SLMessageCell *cell = [SLMessageCell messageCellWithTableView:tableView]; cell.messageFrame = self.messageFrames[indexPath.row]; return cell;}#pragma mark - tableView代理方法- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ SLMessageFrame *tempF = self.messageFrames[indexPath.row]; return tempF.cellHeight;}// tableview 滑动的时候退出键盘- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{ // 退出键盘 [self.view endEditing:YES];}@end<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
// <span style="font-family: Arial, Helvetica, sans-serif;">Model-frame</span>// SLMessageCell.h// 1107-QQcel//// Created by 修修 on 15/11/7.// Copyright © 2015年 cn.Xsoft. All rights reserved.//#import <UIKit/UIKit.h>@class SLMessageFrame;@interface SLMessageCell : UITableViewCell/** * 位置模型 */@property (nonatomic, strong) SLMessageFrame *messageFrame;/** * 初始化一个cell * * @param tableView 当前的tableview * @param reuseIdentifier cell的唯一标识 */- (instancetype)initWithTableView:(UITableView *)tableView reuseIdentifier:(NSString *)reuseIdentifier;+ (instancetype)messageCellWithTableView:(UITableView *)tableView;@end//// SLMessageCell.m// 1107-QQcel//// Created by 修修 on 15/11/7.// Copyright © 2015年 cn.Xsoft. All rights reserved.//#import "SLMessageCell.h"#import "SLMessageFrame.h"#import "SLMessage.h"@interface SLMessageCell ()/** * icon */@property (nonatomic, weak) UIImageView *iconView;/** * time */@property (nonatomic, weak) UILabel *timeLabel;/** * text */@property (nonatomic, weak) UIButton *textBtn;@end@implementation SLMessageCell+ (instancetype)messageCellWithTableView:(UITableView *)tableView{ // 这里涉及到循环利用 static NSString *ID = @"message"; SLMessageCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (cell == nil) { cell = [[SLMessageCell alloc] initWithTableView:tableView reuseIdentifier:ID]; } return cell;}- (instancetype)initWithTableView:(UITableView *)tableView reuseIdentifier:(NSString *)reuseIdentifier{ // 一定要先将父类初始化 self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier]; if (self) { // 设置cell的颜色 UIColor *col = [UIColor colorWithRed:224/255.0 green:224/255.0 blue:224/255.0 alpha:1]; [self setBackgroundColor:col]; // 头像的ImageView控件 UIImageView *iconview = [[UIImageView alloc] init]; [self.contentView addSubview:iconview]; self.iconView = iconview; // 时间的Label控件 UILabel *timelabel = [[UILabel alloc] init]; timelabel.font = [UIFont systemFontOfSize:10]; // 设置字体 timelabel.textAlignment = YES; // 设置居中显示 [self.contentView addSubview:timelabel]; self.timeLabel = timelabel; // 消息文本的Button UIButton *textbtn = [[UIButton alloc] init]; textbtn.titleLabel.numberOfLines = 0; // 设置文字可以换行 [textbtn.titleLabel setFont:[UIFont systemFontOfSize:15]]; // 设置字体 [textbtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; // 字体颜色 // 因为btn背景图片边缘是透明的,而图片是填充显示的,所以要文字向里缩(设置文字的内边距) [textbtn setTitleEdgeInsets:UIEdgeInsetsMake(20, 20, 20, 20)]; // 文字的内边距 [self.contentView addSubview:textbtn]; self.textBtn = textbtn; } return self;}/** * 通过重写位置模型的setter方法,将控件的frame和相应属性设置值 */- (void)setMessageFrame:(SLMessageFrame *)messageFrame{ // 必须写 _messageFrame = messageFrame; // 拿到位置模型的数据模型 SLMessage *message = messageFrame.message; // time的Label控件 self.timeLabel.frame = messageFrame.timeF; self.timeLabel.text = message.time; // icon的ImageView控件 self.iconView.frame = messageFrame.iconF; // 要根据消息的类型设置不一样的头像 if (message.type) { self.iconView.image = [UIImage imageNamed:@"other"]; // 别人的 }else { self.iconView.image = [UIImage imageNamed:@"me"]; // 自己的 } // text的Button控件 self.textBtn.frame = messageFrame.textF; [self.textBtn setTitle:message.text forState:UIControlStateNormal]; // 设置气泡(背景的图片) if (message.type) { // 图片拉伸 UIImage *imageN =[self resizeImage:@"chat_recive_nor"]; [self.textBtn setBackgroundImage:imageN forState:UIControlStateNormal]; UIImage *imageH =[self resizeImage:@"chat_recive_press_pic"]; [self.textBtn setBackgroundImage:imageH forState:UIControlStateHighlighted]; }else { UIImage *imageN = [self resizeImage:@"chat_send_nor"]; [self.textBtn setBackgroundImage:imageN forState:UIControlStateNormal]; UIImage *imageH =[self resizeImage:@"chat_send_press_pic"]; [self.textBtn setBackgroundImage:imageH forState:UIControlStateHighlighted]; } }/** * 图片拉伸方法,不会改变边缘 * * @param imageName 图片名称 * * @return 一张拉伸好的的图片 */- (UIImage *)resizeImage:(NSString *)imageName{ // 拿到图片 UIImage *image = [UIImage imageNamed:imageName]; CGFloat internal = image.size.width * 0.5; UIEdgeInsets inset = UIEdgeInsetsMake(internal, internal, internal, internal); // 图片的一个类方法 return [image resizableImageWithCapInsets:inset];}/*- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets NS_AVAILABLE_IOS(5_0); // create a resizable version of this image. the interior is tiled when drawn.- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode NS_AVAILABLE_IOS(6_0); // the interior is resized according to the resizingMode */@end
// Model-data// SLMessage.h// 1107-QQcel//// Created by 修修 on 15/11/7.// Copyright © 2015年 cn.Xsoft. All rights reserved.//#import <Foundation/Foundation.h>@interface SLMessage : NSObject/** * 信息类型的枚举 */typedef enum { MessageTypeMe = 0, // 自己发的 MessageTypeOther // 别人发的} SLMessageType;/** * 消息 */@property (nonatomic, copy) NSString *text;/** * 时间 */@property (nonatomic, copy) NSString *time;/** * 发送人 */@property (nonatomic, assign) SLMessageType type;/** * 消息是否要显示时间(是不是同一时间发的) */@property (nonatomic, assign, getter=isSameTime) BOOL sameTime;+ (instancetype)messageWithDict:(NSDictionary *)dict;- (instancetype)initMessageWithDict:(NSDictionary *)dict;@end//// SLMessage.m// 1107-QQcel//// Created by 修修 on 15/11/7.// Copyright © 2015年 cn.Xsoft. All rights reserved.//#import "SLMessage.h"@implementation SLMessage+ (instancetype)messageWithDict:(NSDictionary *)dict{ return [[self alloc] initMessageWithDict:dict];}- (instancetype)initMessageWithDict:(NSDictionary *)dict{ if (self = [super init]) { [self setValuesForKeysWithDictionary:dict]; } return self;}@end
QQ分组
// Controller// ViewController.m// 1108-QQ分组//// Created by 修修 on 15/11/8.// Copyright © 2015年 cn.Xsoft. All rights reserved.//#import "SLViewController.h"#import "SLGroup.h"#import "SLFriend.h"#import "SLHeaderView.h"@interface SLViewController () <headerViewDelegate>/** * 模型数组 */@property (nonatomic, strong) NSArray *groups;@end@implementation SLViewController- (void)viewDidLoad { [super viewDidLoad]; // 设置头部view的高度 self.tableView.sectionHeaderHeight = 50;}-(BOOL)prefersStatusBarHidden { // 隐藏状态栏 return YES;}#pragma mark - 懒加载- (NSArray *)groups{ if (_groups == nil) { NSArray *tempArr = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"friends.plist" ofType:nil]]; NSMutableArray *tempMuArr = [NSMutableArray array]; for (NSDictionary *dict in tempArr) { SLGroup *group = [SLGroup groupWithDict:dict]; [tempMuArr addObject:group]; } _groups = tempMuArr; } return _groups;}#pragma mark - tableView的数据源和代理/** * 返回有多少组 */- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return self.groups.count;}/** * 返回每组有多少行,在这里控制分组的开关,关就是0行 */- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ SLGroup *group = self.groups[section]; return group.isOpen ? group.friends.count : 0;}/** * 返回每一行的cell,这里都一样就没有封装,实际上是要封装一步的,把创建cell的过程封装起来 */- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ NSString *ID = @"person"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; } SLGroup *group = self.groups[indexPath.section]; NSArray *friends = group.friends; SLFriend *firendData = friends[indexPath.row]; cell.imageView.image = [UIImage imageNamed:firendData.icon]; cell.textLabel.text = firendData.name; cell.detailTextLabel.text = firendData.intro; return cell;}/** * 返回每一组的headerView */- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{ // 生成headerView SLHeaderView *headview = [SLHeaderView headviewWithTableView:tableView]; // 设置headview的代理为控制器,用来刷新数据 headview.delegate = self; // 传递模型 headview.group =self.groups[section]; // 返回view return headview;}#pragma mark - headerView的代理方法- (void)btnClickOnHeaderView:(SLHeaderView *)headerView{ [self.tableView reloadData];}@end
// View// SLHeaderView.h// 1108-QQ分组//// Created by 修修 on 15/11/8.// Copyright © 2015年 cn.Xsoft. All rights reserved.//#import <UIKit/UIKit.h>@class SLGroup, SLHeaderView;// 代理@protocol headerViewDelegate <NSObject>@optional/** * 当view上的按钮点击的时候,就会通知代理调用此方法 */- (void)btnClickOnHeaderView:(SLHeaderView *)headerView;@end@interface SLHeaderView : UITableViewHeaderFooterView/** * headerView上的Button */@property (nonatomic, weak) UIButton * headBtn;/** * 显示在线人数的Label */@property (nonatomic, weak) UILabel * numLabel;/** * 当前的分组模型,用来为控件设置数据 */@property (nonatomic, strong) SLGroup *group;/** * 代理,遵守相应的协议headerViewDelegate */@property (nonatomic, strong) id<headerViewDelegate> delegate;/** * 初始化headerView */+ (instancetype)headviewWithTableView:(UITableView *)tableView;@end//// SLHeaderView.m// 1108-QQ分组//// Created by 修修 on 15/11/8.// Copyright © 2015年 cn.Xsoft. All rights reserved.//#import "SLHeaderView.h"#import "SLGroup.h"@implementation SLHeaderView// setter方法,设置数据- (void)setGroup:(SLGroup *)group{ _group = group; [self.headBtn setTitle:group.name forState:UIControlStateNormal]; self.numLabel.text = [NSString stringWithFormat:@"%d/%ld", group.online, group.friends.count];}// 重写init方法,添加控件- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier{ self = [super initWithReuseIdentifier:reuseIdentifier]; if (self) { // 按钮 UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; [btn setImage:[UIImage imageNamed:@"buddy_header_arrow"] forState:UIControlStateNormal]; btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; btn.imageEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0); btn.titleEdgeInsets = UIEdgeInsetsMake(0, 20, 0, 0); [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [btn.titleLabel setFont:[UIFont systemFontOfSize:20]]; [btn setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg"] forState:UIControlStateNormal]; [btn setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg_highlighted"] forState:UIControlStateHighlighted]; // 监听按钮的点击事件 [btn addTarget:self action:@selector(headBtnClick) forControlEvents:UIControlEventTouchUpInside]; // 设置按钮内部的imageView的内容模式为居中 btn.imageView.contentMode = UIViewContentModeCenter; // 超出边框的内容不需要裁剪 btn.imageView.clipsToBounds = NO; [self.contentView addSubview:btn]; self.headBtn = btn; // 标签 UILabel *lab = [[UILabel alloc] init]; lab.textAlignment = NSTextAlignmentRight; lab.font = [UIFont systemFontOfSize:13]; lab.textColor = [UIColor grayColor]; [self.contentView addSubview:lab]; self.numLabel = lab; } return self;}+ (instancetype)headviewWithTableView:(UITableView *)tableView{ NSString *ID = @"head"; SLHeaderView *cell = [tableView dequeueReusableHeaderFooterViewWithIdentifier:ID]; if (cell == nil) { cell = [[self alloc] initWithReuseIdentifier:ID]; } return cell;}- (void)headBtnClick{ // 1.修改组模型的标记(状态取反) self.group.open = !self.group.isOpen; // 2.刷新表格 if ([self.delegate respondsToSelector:@selector(btnClickOnHeaderView:)]) { [self.delegate btnClickOnHeaderView:self]; }}/** * 当一个空间的frame发生改变时就会调用 * 一般在这里布局子控件(设置frame) */- (void)layoutSubviews{#warning 一定要调用父类,,,要不然就GG了 [super layoutSubviews]; self.headBtn.frame = self.bounds; CGFloat numLabelH = self.bounds.size.height; CGFloat numLabelY = 0; CGFloat numLabelW = 100; CGFloat numLabelX = self.bounds.size.width - 100 - 10; self.numLabel.frame = CGRectMake(numLabelX, numLabelY, numLabelW, numLabelH);}@end
// Model// SLFriend.h// 1108-QQ分组//// Created by 修修 on 15/11/8.// Copyright © 2015年 cn.Xsoft. All rights reserved.//#import <Foundation/Foundation.h>@interface SLFriend : NSObject/** * 好友头像 */@property (nonatomic, copy) NSString *icon;/** * 个性签名 */@property (nonatomic, copy) NSString *intro;/** * 昵称 */@property (nonatomic, copy) NSString *name;/** * 是否会员 */@property (nonatomic, assign) BOOL vip;- (instancetype)initWithDict:(NSDictionary *)dict;+ (instancetype)friendWithDict:(NSDictionary *)dict;@end//// SLFriend.m// 1108-QQ分组//// Created by 修修 on 15/11/8.// Copyright © 2015年 cn.Xsoft. All rights reserved.//#import "SLFriend.h"@implementation SLFriend- (instancetype)initWithDict:(NSDictionary *)dict{ if (self = [super init]) { [self setValuesForKeysWithDictionary:dict]; } return self;}+ (instancetype)friendWithDict:(NSDictionary *)dict{ return [[self alloc] initWithDict:dict];}@end//// SLGruop.h// 1108-QQ分组//// Created by 修修 on 15/11/8.// Copyright © 2015年 cn.Xsoft. All rights reserved.//#import <Foundation/Foundation.h>@class SLFriend;@interface SLGroup : NSObject/** * 分组名 */@property (nonatomic, copy) NSString *name;/** * 分组里的好友数组 */@property (nonatomic, strong) NSArray *friends;/** * 在线人数 */@property (nonatomic, assign) int online;/** * 分组是否打开 */@property (nonatomic, assign, getter=isOpen) BOOL open;- (instancetype)initWithDict:(NSDictionary *)dict;+ (instancetype)groupWithDict:(NSDictionary *)dict;@end//// SLGruop.m// 1108-QQ分组//// Created by 修修 on 15/11/8.// Copyright © 2015年 cn.Xsoft. All rights reserved.//#import "SLGroup.h"#import "SLFriend.h"@implementation SLGroup- (instancetype)initWithDict:(NSDictionary *)dict{ if (self = [super init]) { // 先将数据初始化 [self setValuesForKeysWithDictionary:dict]; // 在处理分组里的好友,从字典转到模型 NSMutableArray *tempMary = [NSMutableArray array]; for (NSDictionary *dict in self.friends) { SLFriend *friendData = [SLFriend friendWithDict:dict]; [tempMary addObject:friendData]; } self.friends = tempMary; } return self;}+ (instancetype)groupWithDict:(NSDictionary *)dict{ return [[self alloc] initWithDict:dict];}@end
0 0
- iOS学习08代码2
- iOS学习08代码1
- iOS学习:iOS代码规范
- ios学习--代码集锦
- ios学习--代码连接
- ios控件学习 代码实现
- IOS学习 零碎代码备忘
- ios控件学习 代码实现
- ios 基础学习之零基础代码控制实现2
- iOS/iPhone学习系列、代码教程
- iOS/iPhone学习系列、代码教程
- iOS/iPhone学习系列、代码教程
- IOS学习笔记-协议和代码块
- iOS - OpenCV 代码的一点学习记录
- iOS/iPhone学习系列、代码教程
- IOS学习整理---- 代码库下载网站
- 从ios源码学习代码规范
- iOS/iPhone学习系列、代码教程----~~~
- Android学习(1)---最新Android Studio 1.4.1开发环境搭建与HelloWorld
- 代理模式
- iOS POST 文件的上传
- 为cocos2d-x3.2版本增加protobuffer2.5.0支持
- linux下mysql表名大小写敏感问题
- iOS学习08代码2
- 虚拟机Ubuntu图形界面进入命令行快捷键
- 开机自启动软件设置
- [转载]iTOP-4412开发板搭建最小linux系统
- 让Mysql支持Emoji表情
- 001 Two Sum [Leetcode]
- UDP接收端缓冲区和丢包问题
- Tomcat数据源
- linux redis安装