这里预祝大家猴年,”开心 快乐“
粉友们 ,我回来了,这次给大家带来的是一个高仿企信的一个项目。
好久没有在简书里面话唠了。所以这里给大家分享点东西。先说下我为什么这次会高仿企信了。那是因为女票在每天在用企信工作,有次无意看到了。我想模仿一个就这么简单粗暴。下次跟她说这也太简单了吧 (哈哈)记得前些日子好多人在15到16年来临的时候做了好多新年愿望。我也好是羡慕,所以我今天也做下:
- 好好running
- 好好coding
以上两个是我在猴年最想把他做好的事,同时希望做出跟好的东西分享给大家。
话不多说了回到正题
以上效果是用一个第三方的
RESideMenu
具体RESideMenu源码的解读可以参考叶孤城的http://www.jianshu.com/p/99e8b3f6f377
+(RESideMenu *)rootViewController {
JFNavigationController *navigationController = [[JFNavigationController alloc] initWithRootViewController:[[JFHomeViewController alloc] init]];
JFLeftViewController *leftVC = [[JFLeftViewController alloc]init];
RESideMenu *sideMenuViewController = [[RESideMenu alloc] initWithContentViewController:navigationController
leftMenuViewController:leftVC
rightMenuViewController:nil];
sideMenuViewController.backgroundImage = [UIImage imageNamed:@"Stars"];
return sideMenuViewController;
}
以上是对侧边栏的一个抽取
在appdelegate里面只要一行搞定侧边栏就OK了
self.window.rootViewController = [SelectRootViewController rootViewController];
1.gif
以上这个界面我在动画(4)里面已经体现了可以看
http://www.jianshu.com/p/8d478d925743
里面已经讲的很详细了。如果还有问题我们可以探讨下 2.gif
这个聊天的界面,如果认真我的源码的话肯定会看出,我对MJ的即时通讯界面进行的重写
屏幕快照 2016-02-03 下午5.59.36.png主要的代码结构如上:
创建两个模型一个是数据模型,一个是frame模型,根据消息来计算出frame模型
- (void)setMessageFrame:(JFMessageFrame *)messageFrame
{
_messageFrame = messageFrame;
JFMessage *message = messageFrame.message;
// 1.时间
self.timeView.text = message.time;
self.timeView.frame = messageFrame.timeF;
// 2.头像
NSString *icon = (message.type == JFMessageTypeMe) ? @"icon_repairManChat" : @"icon_serviceGirlChat";
self.iconView.image = [UIImage imageNamed:icon];
self.iconView.frame = messageFrame.iconF;
// 3.正文
[self.textView setTitle:message.text forState:UIControlStateNormal];
self.textView.frame = messageFrame.textF;
// 4.正文的背景
if (message.type == JFMessageTypeMe) { // 自己发的,蓝色
[self.textView setBackgroundImage:[UIImage resizableImage:@"chat_send_nor"] forState:UIControlStateNormal];
} else { // 别人发的,白色
[self.textView setBackgroundImage:[UIImage resizableImage:@"chat_recive_nor"] forState:UIControlStateNormal];
// [self.textView setBackgroundImage:[UIImage resizableImage:@"chat_send_nor"] forState:UIControlStateNormal];
}
}
控制器的cell的创建和数据模型的传递
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// 1.创建cell
JFMessageCell *cell = [JFMessageCell cellWithTableView:tableView];
// 2.给cell传递模型
cell.messageFrame = self.messageFrames[indexPath.row];
// 3.返回cell
return cell;
}
具体细节请看源码。
4.gif以上是一个多级菜单选择 封装成JSDropDownMenu 对象 提供
@interface JSIndexPath : NSObject
@property (nonatomic, assign) NSInteger column;
@property (nonatomic, assign) NSInteger leftOrRight;
@property (nonatomic, assign) NSInteger leftRow;
@property (nonatomic, assign) NSInteger row;
- (instancetype)initWithColumn:(NSInteger)column leftOrRight:(NSInteger)leftOrRight leftRow:(NSInteger)leftRow row:(NSInteger)row;
+ (instancetype)indexPathWithCol:(NSInteger)col leftOrRight:(NSInteger)leftOrRight leftRow:(NSInteger)leftRow row:(NSInteger)row;
@end
#pragma mark - data source protocol
@class JSDropDownMenu;
@protocol JSDropDownMenuDataSource <NSObject>
@required
- (NSInteger)menu:(JSDropDownMenu *)menu numberOfRowsInColumn:(NSInteger)column leftOrRight:(NSInteger)leftOrRight leftRow:(NSInteger)leftRow;
- (NSString *)menu:(JSDropDownMenu *)menu titleForRowAtIndexPath:(JSIndexPath *)indexPath;
- (NSString *)menu:(JSDropDownMenu *)menu titleForColumn:(NSInteger)column;
/**
* 表视图显示时,左边表显示比例
*/
- (CGFloat)widthRatioOfLeftColumn:(NSInteger)column;
/**
* 表视图显示时,是否需要两个表显示
*/
- (BOOL)haveRightTableViewInColumn:(NSInteger)column;
/**
* 返回当前菜单左边表选中行
*/
- (NSInteger)currentLeftSelectedRow:(NSInteger)column;
@optional
//default value is 1
- (NSInteger)numberOfColumnsInMenu:(JSDropDownMenu *)menu;
/**
* 是否需要显示为UICollectionView 默认为否
*/
- (BOOL)displayByCollectionViewInColumn:(NSInteger)column;
@end
#pragma mark - delegate
@protocol JSDropDownMenuDelegate <NSObject>
@optional
- (void)menu:(JSDropDownMenu *)menu didSelectRowAtIndexPath:(JSIndexPath *)indexPath;
@end
#pragma mark - interface
@interface JSDropDownMenu : UIView <UITableViewDataSource, UITableViewDelegate, UICollectionViewDataSource, UICollectionViewDelegate,UICollectionViewDelegateFlowLayout>
@property (nonatomic, weak) id <JSDropDownMenuDataSource> dataSource;
@property (nonatomic, weak) id <JSDropDownMenuDelegate> delegate;
@property (nonatomic, strong) UIColor *indicatorColor;
@property (nonatomic, strong) UIColor *textColor;
@property (nonatomic, strong) UIColor *separatorColor;
/**
* the width of menu will be set to screen width defaultly
*
* @param origin the origin of this view's frame
* @param height menu's height
*
* @return menu
*/
- (instancetype)initWithOrigin:(CGPoint)origin andHeight:(CGFloat)height;
- (NSString *)titleForRowAtIndexPath:(JSIndexPath *)indexPath;
提供的属性和方法给外部用 如上,在控制器里面只要
NSArray *food = @[@"所有角色", @"马云", @"李彦宏", @"马化腾", @"雷军"];
NSArray *travel = @[@"所有员工", @"黄晓明", @"杨颖", @"李晨", @"范冰冰"];
_data1 = [NSMutableArray arrayWithObjects:@{@"title":@"老板", @"data":food}, @{@"title":@"员工", @"data":travel}, nil];
_data2 = [NSMutableArray arrayWithObjects:@"所有状态", @"进行中", @"待审核", @"已完成", @"已中止", nil];
_data3 = [NSMutableArray arrayWithObjects:@"所有程度", @"紧急任务", @"一般任务", @"学习任务", nil];
JSDropDownMenu *menu = [[JSDropDownMenu alloc] initWithOrigin:CGPointMake(0, 0) andHeight:45];
menu.indicatorColor = [UIColor colorWithRed:175.0f/255.0f green:175.0f/255.0f blue:175.0f/255.0f alpha:1.0];
menu.separatorColor = [UIColor colorWithRed:210.0f/255.0f green:210.0f/255.0f blue:210.0f/255.0f alpha:1.0];
menu.textColor = [UIColor colorWithRed:83.f/255.0f green:83.f/255.0f blue:83.f/255.0f alpha:1.0f];
menu.dataSource = self;
menu.delegate = self;
5.gif
上面这个效果我沿用的是以前封装的一个自定义日历表。细节请看:
http://www.jianshu.com/p/41408417979a 6.gif
这个效果的原理的和聊天界面是一样的。在图片浏览器里面用MJPhotoBrowser,用的这个框架有点老了。你可以尝试用新的框架试试看,如果好了 可以个跟我分享下我会很开心。主要的结构目录如下
屏幕快照 2016-02-03 下午6.16.12.png- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// 初始化9个子控件
for (int i = 0; i<9; i++) {
JFPhotoView *photoView = [[JFPhotoView alloc] init];
photoView.userInteractionEnabled = YES;
photoView.tag = i;
[photoView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(photoTap:)]];
[self addSubview:photoView];
}
}
return self;
}
- (void)photoTap:(UITapGestureRecognizer *)recognizer
{
// DXAlertView *alertView = [[DXAlertView alloc] initWithTitle:@"哈哈" contentText:@"废话速度快回家繁华的时刻分开后" leftButtonTitle:@"确定" rightButtonTitle:@"取消"];
// [alertView show];
//
NSInteger count = self.photos.count;
// 1.封装图片数据
NSMutableArray *myphotos = [NSMutableArray arrayWithCapacity:count];
for (int i = 0; i<count; i++) {
// 一个MJPhoto对应一张显示的图片
MJPhoto *mjphoto = [[MJPhoto alloc] init];
mjphoto.srcImageView = self.subviews[i]; // 来源于哪个UIImageView
/*用模型*/
// JFPhoto *iwphoto = self.photos[i];
// NSString *photoUrl = [iwphoto.thumbnail_pic stringByReplacingOccurrencesOfString:@"thumbnail" withString:@"bmiddle"];
/*用字典*/
NSString *photoUrl = self.photos[i][@"thumbnail_pic"];
mjphoto.url = [NSURL URLWithString:photoUrl]; // 图片路径
[myphotos addObject:mjphoto];
}
// 2.显示相册
MJPhotoBrowser *browser = [[MJPhotoBrowser alloc] init];
browser.currentPhotoIndex = recognizer.view.tag; // 弹出相册时显示的第一张图片是?
browser.photos = myphotos; // 设置所有的图片
[browser show];
}
- (void)setPhotos:(NSArray *)photos
{
_photos = photos;
for (int i = 0; i<self.subviews.count; i++) {
// 取出i位置对应的imageView
JFPhotoView *photoView = self.subviews[i];
// 判断这个imageView是否需要显示数据
if (i < photos.count) {
// 显示图片
photoView.hidden = NO;
// 传递模型数据
photoView.photo = photos[i];
// 设置子控件的frame
int maxColumns = (photos.count == 4) ? 2 : 3;
int col = i % maxColumns;
int row = i / maxColumns;
CGFloat photoX = col * (IWPhotoW + IWPhotoMargin);
CGFloat photoY = row * (IWPhotoH + IWPhotoMargin);
photoView.frame = CGRectMake(photoX, photoY, IWPhotoW, IWPhotoH);
// Aspect : 按照图片的原来宽高比进行缩
// UIViewContentModeScaleAspectFit : 按照图片的原来宽高比进行缩放(一定要看到整张图片)
// UIViewContentModeScaleAspectFill : 按照图片的原来宽高比进行缩放(只能图片最中间的内容)
// UIViewContentModeScaleToFill : 直接拉伸图片至填充整个imageView
if (photos.count == 1) {
photoView.contentMode = UIViewContentModeScaleAspectFit;
photoView.clipsToBounds = NO;
} else {
photoView.contentMode = UIViewContentModeScaleAspectFill;
photoView.clipsToBounds = YES;
}
} else { // 隐藏imageView
photoView.hidden = YES;
}
}
}
+ (CGSize)photosViewSizeWithPhotosCount:(int)count
{
// 一行最多有3列
int maxColumns = (count == 4) ? 2 : 3;
// 总行数
int rows = (count + maxColumns - 1) / maxColumns;
// 高度
CGFloat photosH = rows * IWPhotoH + (rows - 1) * IWPhotoMargin;
// 总列数
int cols = (count >= maxColumns) ? maxColumns : count;
// 宽度
CGFloat photosW = cols * IWPhotoW + (cols - 1) * IWPhotoMargin;
return CGSizeMake(photosW, photosH);
/**
一共60条数据 == count
一页10条 == size
总页数 == pages
pages = (count + size - 1)/size;
*/
}
这就是图片来浏览器的使用和控件的创建
7.gif接下来有个我最想说的就是类似微信里面的通讯录界面
屏幕快照 2016-02-03 下午6.22.09.png关键代码如下:这段也是在github上别人的分享,直接拿过来用了,不涉及到商业目的。
给一个模型根据拼音进行排序
+ (NSMutableArray *) getFriendListDataBy:(NSMutableArray *)array
{
NSMutableArray *ans = [[NSMutableArray alloc] init];
NSArray *serializeArray = [(NSArray *)array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { // 排序
int i;
NSString *strA = ((JFAddressBookModel *)obj1).pinyin;
NSString *strB = ((JFAddressBookModel *)obj2).pinyin;
for (i = 0; i < strA.length && i < strB.length; i ++) {
char a = [strA characterAtIndex:i];
char b = [strB characterAtIndex:i];
if (a > b) {
return (NSComparisonResult)NSOrderedDescending; // 上升
}
else if (a < b) {
return (NSComparisonResult)NSOrderedAscending; // 下降
}
}
if (strA.length > strB.length) {
return (NSComparisonResult)NSOrderedDescending;
}
else if (strA.length < strB.length){
return (NSComparisonResult)NSOrderedAscending;
}
return (NSComparisonResult)NSOrderedSame;
}];
char lastC = '1';
NSMutableArray *data;
NSMutableArray *oth = [[NSMutableArray alloc] init];
for (JFAddressBookModel *user in serializeArray) {
char c = [user.pinyin characterAtIndex:0];
if (!isalpha(c)) {
[oth addObject:user];
}
else if (c != lastC){
lastC = c;
if (data && data.count > 0) {
[ans addObject:data];
}
data = [[NSMutableArray alloc] init];
[data addObject:user];
}
else {
[data addObject:user];
}
}
if (data && data.count > 0) {
[ans addObject:data];
}
if (oth.count > 0) {
[ans addObject:oth];
}
return ans;
}
+ (NSMutableArray *)getFriendListSectionBy:(NSMutableArray *)array
{
NSMutableArray *section = [[NSMutableArray alloc] init];
[section addObject:UITableViewIndexSearch];
for (NSArray *item in array) {
JFAddressBookModel *user = [item objectAtIndex:0];
char c = [user.pinyin characterAtIndex:0];
if (!isalpha(c)) {
c = '#';
}
[section addObject:[NSString stringWithFormat:@"%c", toupper(c)]];
}
return section;
}
高仿企信四就到这里了,本项目继续更新中。。。
源码链接:https://github.com/tubie/JFQiXin
屏幕快照 2015-10-08 08.55.27.png有问题可以提出来我很乐意和大家一起分享。喜欢的话给我一个小星星我会很开心的。同时也希望你能够继续关注我。
网友评论
clang: error: linker command failed with exit code 1 (use -v to see invocation)
运行起来出行这个错误该怎么改?谢谢
可以这么写pch的路径 $(SRCROOT)/JFQiXin/Other/PublicClass/JFQixin.pch
就会自动匹配了, 望笑纳