高仿企信

作者: 土鳖不土 | 来源:发表于2016-02-03 16:55 被阅读3792次

这里预祝大家猴年,”开心 快乐“

粉友们 ,我回来了,这次给大家带来的是一个高仿企信的一个项目。

好久没有在简书里面话唠了。所以这里给大家分享点东西。先说下我为什么这次会高仿企信了。那是因为女票在每天在用企信工作,有次无意看到了。我想模仿一个就这么简单粗暴。下次跟她说这也太简单了吧 (哈哈)记得前些日子好多人在15到16年来临的时候做了好多新年愿望。我也好是羡慕,所以我今天也做下:

  1. 好好running
  2. 好好coding

以上两个是我在猴年最想把他做好的事,同时希望做出跟好的东西分享给大家。
话不多说了回到正题

3.gif
以上效果是用一个第三方的 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

有问题可以提出来我很乐意和大家一起分享。喜欢的话给我一个小星星我会很开心的。同时也希望你能够继续关注我。

相关文章

网友评论

  • JoeWcc:不错不错
  • 阿拉斯加的狗:楼主请问你的聊天那个界面 你打开键盘聊天 退出后台 再进入 里面直接出现键盘高度的限制 不知道是什么原因 解决了吗!
  • 507292774991:你的工作圈文件中JFHomeWorkViewController有问题
  • 9b5a645c220b:ld: library not found for -lAFNetworking
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    运行起来出行这个错误该怎么改?谢谢
  • bcee5dd5dd26:精力旺盛,不错
  • 工藤新er:你是李明杰的学生吗 微博页面写的一毛一样 还有JFHomeWorkWorldViewController这个类怎么没了 没有同步到github
    土鳖不土:@工藤新er 我不是MJ的学生。你说的是工作圈是吧?
  • 小宝宝爱吃棒棒糖:有没有设计思路图,从哪里开始写,新手,思路不清晰
    土鳖不土:@iOS爱好者huan 你可以下载一个企信app看下就知道了。
  • rxdxxxx:作者你好, 下载后发现你的pch路径是绝对路径, 有的同学下载后可能会有找不到pch的问题.
    可以这么写pch的路径 $(SRCROOT)/JFQiXin/Other/PublicClass/JFQixin.pch
    就会自动匹配了, 望笑纳
    土鳖不土:@Jason_Ding 已经修复 非常感谢 :smile:
  • MrFanRG:在github下载你的demo,一运行就报错
    土鳖不土:@ios码农学生 我这边运行事没问题的。是不是你打开的文件错误。
    MrFanRG: @tubiebutu 就是pch文件找不到
    土鳖不土:@ios码农学生 能看下 你报的什么错误吗?
  • 左左1990:朋友在这公司做开发:pray:
    土鳖不土:@eecc560b595c 欢迎你的朋友指教
  • Sheepy:叼叼叼
  • DevinWu:顶顶,给楼主大大的赞👍
    土鳖不土: @DevinWu 谢谢
  • Gaivn:不是一般的叼叼
    土鳖不土: @Gavin_ldh 谢谢
  • 昨夜雨轻栏:有下载地址吗?
    土鳖不土:@昨夜雨轻栏 已经贴出来了
  • smalldu:各种高仿,叼叼叼
    土鳖不土:@大石头布 互相学习 哈哈 :smile:

本文标题:高仿企信

本文链接:https://www.haomeiwen.com/subject/mrdekttx.html