高仿企信

作者: 土鳖不土 | 来源:发表于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