[iOS微博项目 - 3.1] - 发微博界面

 
A.发微博界面:自定义UITextView
1.需求
  • 用UITextView做一个编写微博的输入框
  • 没有输入任何文本的时候显示占位文本
  • 统一占位文本和正文的字体
 
2.思路
  • 系统自带的输入控件有UITextField和UITextView两种
  • UITextField:自带占位文本属性,不能换行
  • UITextView:没有占位文本属性,能换行
  • 这里我们选择UITextView进行改造
  • 根据是否输入文本决定是否显示占位文本(placeholder),可能使用代理或通知机制来监听文本输入,这里我们使用通知。因为设置代理只有一个,设为view本身不合理,这样就不能设置控制器代理了。
  • 在UITextView中加入一个UILabel,专门用来显示placeholder
 
3.实现
自定义一个集成UITextView的控件
带有一个placeHolder属性
实现相关方法
 //
// HVWComposeTextView.h
// HVWWeibo
//
// Created by hellovoidworld on 15/2/6.
// Copyright (c) 2015年 hellovoidworld. All rights reserved.
// #import <UIKit/UIKit.h> @interface HVWComposeTextView : UITextView /** placeholder 占位文本 */
@property(nonatomic, copy) NSString *placeHolder; @end //
// HVWComposeTextView.m
// HVWWeibo
//
// Created by hellovoidworld on 15/2/6.
// Copyright (c) 2015年 hellovoidworld. All rights reserved.
// #import "HVWComposeTextView.h" @interface HVWComposeTextView() @property(nonatomic, strong) UILabel *placeHolderLabel; @end @implementation HVWComposeTextView - (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame]; if (self) {
// 可以拖曳
self.scrollEnabled = YES;
self.alwaysBounceVertical = YES; // 添加placeHolderLabel
[self setupPlaceHolder]; // 设置默认字体
[self setFont:[UIFont systemFontOfSize:]]; // 设置通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(inputtingText) name:UITextViewTextDidChangeNotification object:self];
} return self;
} /** 添加placeHolder */
- (void) setupPlaceHolder {
UILabel *placeHolderLabel = [[UILabel alloc] init];
self.placeHolderLabel = placeHolderLabel; placeHolderLabel.textColor = [UIColor lightGrayColor];
placeHolderLabel.userInteractionEnabled = NO;
placeHolderLabel.numberOfLines = ; // 自动换行
placeHolderLabel.backgroundColor = [UIColor clearColor]; [self addSubview:placeHolderLabel];
} /** 设置子控件frame */
- (void)layoutSubviews {
[super layoutSubviews]; self.placeHolderLabel.x = ;
self.placeHolderLabel.y = ; NSMutableDictionary *attr = [NSMutableDictionary dictionary];
attr[NSFontAttributeName] = self.placeHolderLabel.font;
CGFloat placeHolderWidth = self.width - * self.placeHolderLabel.x; CGRect tempRect = [self.placeHolderLabel.text boundingRectWithSize:CGSizeMake(placeHolderWidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:attr context:nil];
self.placeHolderLabel.size = tempRect.size;
} - (void)setPlaceHolder:(NSString *)placeHolder {
self.placeHolderLabel.text = placeHolder; // 重新计算frame,可能不会立即调用layoutSubviews
[self setNeedsLayout];
} /** 重写setFont,更改正文font的时候也更改placeHolder的font */
- (void)setFont:(UIFont *)font {
[super setFont:font];
self.placeHolderLabel.font = font; // 重新计算frame,可能不会立即调用layoutSubviews
[self setNeedsLayout];
} - (void)dealloc {
// 注销通知监听
[[NSNotificationCenter defaultCenter] removeObserver:self];
} /** 正在输入文本 */
- (void) inputtingText {
if (self.text.length) {
self.placeHolderLabel.hidden = YES;
} else {
self.placeHolderLabel.hidden = NO;
}
} @end
 
 
在控制器中使用
 //  HVWComposeViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view. // 初始化一些功能按钮
self.title = @"发微博"; self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"退出" style:UIBarButtonItemStylePlain target:self action:@selector(dismiss)]; // 添加自定义UITextView
HVWComposeTextView *composeView = [[HVWComposeTextView alloc] init];
self.composeView = composeView;
composeView.frame = self.view.bounds;
composeView.delegate = self; composeView.placeHolder = @"分享点滴精彩阿里山的会计法律考试大姐夫;拉可接受的;浪费空间阿斯顿;离开房间啊;数量的会计法律;阿克苏交电费;拉可接受的分;垃圾可适当;浪费就卡死;老地方就卡死;懒得看积分;阿里快速的减肥;拉等级考试..."; [self.view addSubview:composeView];
}
 
[iOS微博项目 - 3.1] - 发微博界面
 
 
B.使用代理监听UITextView的拖曳,缩回键盘
 //  HVWComposeViewController.m
#pragma mark - UIScrollViewDelegate
/** 开始拖曳 */
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
// 缩回键盘
[self.composeView resignFirstResponder];
}
 
[iOS微博项目 - 3.1] - 发微博界面
 
 
整理一下“发微博”控制器代码:
 //
// HVWComposeViewController.m
// HVWWeibo
//
// Created by hellovoidworld on 15/2/3.
// Copyright (c) 2015年 hellovoidworld. All rights reserved.
// #import "HVWComposeViewController.h"
#import "HVWComposeTextView.h" @interface HVWComposeViewController () <UITextViewDelegate, UIScrollViewDelegate> @property(nonatomic, strong) HVWComposeTextView *composeView; @end @implementation HVWComposeViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view. // 设置导航栏
[self setupNavigationBar]; // 添加自定义UITextView
[self setupTextView]; // 添加工具栏
[self setupToolBar];
} /** 设置工具栏 */
- (void) setupToolBar { } /** 设置输入控件 */
- (void) setupTextView {
HVWComposeTextView *composeView = [[HVWComposeTextView alloc] init];
self.composeView = composeView;
composeView.frame = self.view.bounds;
composeView.delegate = self; composeView.placeHolder = @"分享点滴精彩..."; [self.view addSubview:composeView];
} /** 设置导航栏 */
- (void) setupNavigationBar {
// 标题
self.title = @"发微博"; // 导航栏左方按钮
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"退出" style:UIBarButtonItemStylePlain target:self action:@selector(dismiss)];
} - (void)viewDidAppear:(BOOL)animated {
// 自动弹出键盘
[self.composeView becomeFirstResponder];
} - (void) dismiss {
[self.composeView resignFirstResponder];
[self dismissViewControllerAnimated:YES completion:nil]; } #pragma mark - UIScrollViewDelegate
/** 开始拖曳 */
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
// 缩回键盘
[self.composeView resignFirstResponder];
} @end
 
 
C.键盘上方的工具条
1.需求
紧贴在键盘上方的工具栏,可随键盘伸缩,始终可视
工具栏上的功能按钮有:照相机、相册、提到@、话题、表情
 
2.思路
自定义一个UIView,封装上述功能
使用代理监听按钮点击
监听键盘弹出缩回通知,使用transform移动工具条
 
3.实现
(1)自定义UIView
 //
// HVWComposeToolBar.h
// HVWWeibo
//
// Created by hellovoidworld on 15/2/7.
// Copyright (c) 2015年 hellovoidworld. All rights reserved.
// #import <UIKit/UIKit.h> typedef enum {
HVWComposeToolBarButtonTagCamera, // 照相机
HVWComposeToolBarButtonTagPhotoLib, // 相册
HVWComposeToolBarButtonTagMention, // 提到@
HVWComposeToolBarButtonTagTrend, // 话题
HVWComposeToolBarButtonTagEmotion // 表情
} HVWComposeToolBarButtonTag; @class HVWComposeToolBar;
@protocol HVWComposeToolBarDelegate <NSObject> @optional
- (void) composeToolBar:(HVWComposeToolBar *) composeToolBar didButtonClicked:(HVWComposeToolBarButtonTag) tag; @end @interface HVWComposeToolBar : UIView /** 代理 */
@property(nonatomic, weak) id<HVWComposeToolBarDelegate> delegate; @end
 
 //
// HVWComposeToolBar.m
// HVWWeibo
//
// Created by hellovoidworld on 15/2/7.
// Copyright (c) 2015年 hellovoidworld. All rights reserved.
// #import "HVWComposeToolBar.h" @implementation HVWComposeToolBar - (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame]; if (self) {
// 背景色
self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageWithNamed:@"compose_toolbar_background"]]; // 添加按钮
[self addButtonWithIcon:@"compose_camerabutton_background" highlightedIcon:@"compose_camerabutton_background_highlighted" tag:HVWComposeToolBarButtonTagCamera]; [self addButtonWithIcon:@"compose_toolbar_picture" highlightedIcon:@"compose_toolbar_picture_highlighted" tag:HVWComposeToolBarButtonTagPhotoLib]; [self addButtonWithIcon:@"compose_mentionbutton_background" highlightedIcon:@"compose_mentionbutton_background_highlighted" tag:HVWComposeToolBarButtonTagMention]; [self addButtonWithIcon:@"compose_trendbutton_background" highlightedIcon:@"compose_trendbutton_background_highlighted" tag:HVWComposeToolBarButtonTagTrend]; [self addButtonWithIcon:@"compose_emoticonbutton_background" highlightedIcon:@"compose_emoticonbutton_background_highlighted" tag:HVWComposeToolBarButtonTagEmotion];
} return self;
} /** 添加一个按钮 */
- (void) addButtonWithIcon:(NSString *) icon highlightedIcon:(NSString *) highlightedIcon tag:(HVWComposeToolBarButtonTag) tag {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageWithNamed:icon] forState:UIControlStateNormal];
[button setImage:[UIImage imageWithNamed:highlightedIcon] forState:UIControlStateHighlighted];
button.tag = tag; // 按钮点击事件
[button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:button];
} /** 设置frame */
- (void)layoutSubviews {
[super layoutSubviews]; CGFloat buttonWidth = self.width / self.subviews.count; // 设置每个按钮
for (int i=; i<self.subviews.count; i++) {
UIButton *button = self.subviews[i]; CGFloat buttonHeight = buttonWidth;
CGFloat buttonX = i * buttonWidth;
CGFloat buttonY = (self.height - buttonHeight) * 0.5;
button.frame = CGRectMake(buttonX, buttonY, buttonWidth, buttonHeight);
}
} /** 按钮点击 */
- (void) buttonClicked:(UIButton *) button {
// 通知代理
if ([self.delegate respondsToSelector:@selector(composeToolBar:didButtonClicked:)]) {
[self.delegate composeToolBar:self didButtonClicked:button.tag];
}
} @end
 
(2)在控制器上测试
 //  HVWComposeViewController.m
/** 设置工具栏 */
- (void) setupToolBar {
HVWComposeToolBar *toolBar = [[HVWComposeToolBar alloc] init];
toolBar.width = self.view.width;
toolBar.height = ;
toolBar.delegate = self; self.composeView.inputAccessoryView = toolBar;
}
 
[iOS微博项目 - 3.1] - 发微博界面
 
(3)在控制器中调整工具条的位置
不要直接加载键盘的inputAccessoryView上,因为需要在键盘退出之后仍然显示在底部
所以独立设置位置,使用transform随着键盘移动
 //  HVWComposeViewController.m
/** 设置工具栏 */
- (void) setupToolBar {
HVWComposeToolBar *toolBar = [[HVWComposeToolBar alloc] init];
self.toolBar = toolBar;
toolBar.width = self.view.width;
toolBar.height = ;
toolBar.delegate = self; toolBar.x = ;
// 在底部显示
toolBar.y = self.view.height - toolBar.height; [self.view addSubview:toolBar];
} /** 设置输入控件 */
- (void) setupTextView {
HVWComposeTextView *composeView = [[HVWComposeTextView alloc] init];
self.composeView = composeView;
composeView.frame = self.view.bounds;
composeView.delegate = self; composeView.placeHolder = @"分享点滴精彩..."; [self.view addSubview:composeView]; // 监听键盘通知
// 键盘将弹出
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; // 键盘将缩回
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; // 添加图片显示区
[self setupImageDisplayView];
} #pragma mark - 键盘通知处理
/** 键盘将弹出 */
- (void) keyboardWillShow:(NSNotification *) note {
// 键盘弹出需要时间
CGFloat duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; // 移动工具条
[UIView animateWithDuration:duration animations:^{
// 获取键盘高度
CGRect keyboardFrame = [note.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
CGFloat keyboardHeight = keyboardFrame.size.height; self.toolBar.transform = CGAffineTransformMakeTranslation(, - * keyboardHeight);
}];
} /** 键盘将缩回 */
- (void) keyboardWillHide:(NSNotification *) note {
// 键盘缩回需要时间
CGFloat duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; // 移动工具条
[UIView animateWithDuration:duration animations:^{
self.toolBar.transform = CGAffineTransformIdentity;
}];
}
 
[iOS微博项目 - 3.1] - 发微博界面
 
D.相机 & 相册 选择图片功能
1.需求
点击“相机”/“相册”进入相应界面,完成后把选择的图片显示在输入框
 
2.思路
使用UIImagePickerController打开相机/相册
使用picker的代理方法,在完成选择后获取图片
创建一个UIView用来装载图片,然后放在输入框内
 
3.实现
 //
// HVWComposeImageDisplayView.h
// HVWWeibo
//
// Created by hellovoidworld on 15/2/7.
// Copyright (c) 2015年 hellovoidworld. All rights reserved.
// #import <UIKit/UIKit.h> @interface HVWComposeImageDisplayView : UIView - (void) addImage:(UIImage *) image; @end
 
 //
// HVWComposeImageDisplayView.m
// HVWWeibo
//
// Created by hellovoidworld on 15/2/7.
// Copyright (c) 2015年 hellovoidworld. All rights reserved.
// #import "HVWComposeImageDisplayView.h" #define MaxColumn 4 @implementation HVWComposeImageDisplayView /** 添加图片 */
- (void) addImage:(UIImage *) image {
HVWLog(@"addImage");
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.contentMode = UIViewContentModeScaleAspectFit; [self addSubview:imageView]; [self setNeedsDisplay];
} /** 设置frame */
- (void)layoutSubviews {
[super layoutSubviews]; UIImageView *imageView = [self.subviews lastObject];
int index = self.subviews.count - ;
// 所在列
int column = index % MaxColumn;
// 所在行
int row = index / MaxColumn; CGFloat margin = ;
CGFloat imageWidth = (self.width - (MaxColumn + ) * margin) / MaxColumn;
CGFloat imageHeight = imageWidth;
CGFloat imageX = column * (imageWidth + margin) + margin;
CGFloat imageY = row * (imageHeight + margin); imageView.frame = CGRectMake(imageX, imageY, imageWidth, imageHeight);
} @end
 
 //
// HVWComposeViewController.m
// HVWWeibo
//
// Created by hellovoidworld on 15/2/3.
// Copyright (c) 2015年 hellovoidworld. All rights reserved.
// #import "HVWComposeViewController.h"
#import "HVWComposeTextView.h"
#import "HVWComposeToolBar.h"
#import "HVWComposeImageDisplayView.h" @interface HVWComposeViewController () <UITextViewDelegate, UIScrollViewDelegate, HVWComposeToolBarDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate> /** 输入框 */
@property(nonatomic, strong) HVWComposeTextView *composeView; /** 工具条 */
@property(nonatomic, strong) HVWComposeToolBar *toolBar; /** 图片显示区 */
@property(nonatomic, strong) HVWComposeImageDisplayView *imageDisplayView; @end @implementation HVWComposeViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view. // 设置导航栏
[self setupNavigationBar]; // 添加自定义UITextView
[self setupTextView]; // 添加工具栏
[self setupToolBar];
} /** 设置工具栏 */
- (void) setupToolBar {
HVWComposeToolBar *toolBar = [[HVWComposeToolBar alloc] init];
self.toolBar = toolBar;
toolBar.width = self.view.width;
toolBar.height = ;
toolBar.delegate = self; toolBar.x = ;
// 在底部显示
toolBar.y = self.view.height - toolBar.height; [self.view addSubview:toolBar];
} /** 设置输入控件 */
- (void) setupTextView {
HVWComposeTextView *composeView = [[HVWComposeTextView alloc] init];
self.composeView = composeView;
composeView.frame = self.view.bounds;
composeView.delegate = self; composeView.placeHolder = @"分享点滴精彩..."; [self.view addSubview:composeView]; // 监听键盘通知
// 键盘将弹出
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; // 键盘将缩回
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; // 添加图片显示区
[self setupImageDisplayView];
} /** 设置导航栏 */
- (void) setupNavigationBar {
// 标题
self.title = @"发微博"; // 导航栏左方按钮
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"退出" style:UIBarButtonItemStylePlain target:self action:@selector(dismiss)];
} /** 添加图片显示区 */
- (void) setupImageDisplayView {
HVWComposeImageDisplayView *imageDisplayView = [[HVWComposeImageDisplayView alloc] init];
imageDisplayView.size = self.composeView.size;
imageDisplayView.x = ;
imageDisplayView.y = ; self.imageDisplayView = imageDisplayView; [self.composeView addSubview:imageDisplayView];
} - (void)viewDidAppear:(BOOL)animated {
// 自动弹出键盘
[self.composeView becomeFirstResponder];
} - (void) dismiss {
[self.composeView resignFirstResponder];
[self dismissViewControllerAnimated:YES completion:nil]; } #pragma mark - UIScrollViewDelegate
/** 开始拖曳 */
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
// 缩回键盘
[self.composeView resignFirstResponder];
} #pragma mark - HVWComposeToolBarDelegate
/** 工具栏的按钮被点击了 */
- (void)composeToolBar:(HVWComposeToolBar *)composeToolBar didButtonClicked:(HVWComposeToolBarButtonTag)tag {
// 判断哪个按钮被点击
switch (tag) {
case HVWComposeToolBarButtonTagCamera: // 相机
[self openCamera];
break;
case HVWComposeToolBarButtonTagPhotoLib: // 相册
[self openAlbum];
break;
case HVWComposeToolBarButtonTagMention: // 提到@ break;
case HVWComposeToolBarButtonTagTrend: // 话题 break;
case HVWComposeToolBarButtonTagEmotion: // 表情 break;
default:
break;
}
} /** 打开相机 */
- (void) openCamera {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.delegate = self; [self presentViewController:picker animated:YES completion:nil];
} /** 打开相册 */
- (void) openAlbum {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
picker.delegate = self; [self presentViewController:picker animated:YES completion:nil];
} #pragma mark - UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
// 取得原图
UIImage *image = info[UIImagePickerControllerOriginalImage];
[self.imageDisplayView addImage:image]; [picker dismissViewControllerAnimated:YES completion:nil];
} #pragma mark - 键盘通知处理
/** 键盘将弹出 */
- (void) keyboardWillShow:(NSNotification *) note {
// 键盘弹出需要时间
CGFloat duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; // 移动工具条
[UIView animateWithDuration:duration animations:^{
// 获取键盘高度
CGRect keyboardFrame = [note.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
CGFloat keyboardHeight = keyboardFrame.size.height; self.toolBar.transform = CGAffineTransformMakeTranslation(, - * keyboardHeight);
}];
} /** 键盘将缩回 */
- (void) keyboardWillHide:(NSNotification *) note {
// 键盘缩回需要时间
CGFloat duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; // 移动工具条
[UIView animateWithDuration:duration animations:^{
self.toolBar.transform = CGAffineTransformIdentity;
}];
} @end
 
[iOS微博项目 - 3.1] - 发微博界面
 
 
 
 
 
 
 
上一篇:HDU 1242 -Rescue (双向BFS)&&( BFS+优先队列)


下一篇:八位彻底改变App Store的iOS开发者