高仿美團<二>

親愛的粉友們我又回來了。

繼上一次高仿美團主界面之后我說我會持續(xù)更新的,還說重要的事情說三遍瀑晒。由于最近項目比較緊就很比較難擠出時間去coding;
不話癆了:上次就想給大家分享一個項目的最初搭建但是,由于太匆忙就沒上徘意,今天補上 哈哈苔悦!先分析一下項目的目錄結(jié)構(gòu)吧:
其他的文件夾就不多說了,主要的類都在Class里面按照功能模塊建一個文件夾椎咧,最好建一個工具類玖详,和分類這樣業(yè)務(wù)更加分明。其中工具類把整個項目都用到的功能抽取出來勤讽。比如說快速加載XIB,plist,網(wǎng)絡(luò)等等蟋座。


屏幕快照 2015-08-30 15.55.25.png

接下來在每個功能模塊的文件夾里面放MVC。

屏幕快照 2015-08-30 16.01.12.png

這些都只是個人習慣脚牍,個人覺得比較爽比較舒服向臀,沒有好壞之分。
有圖有真相:

主界面-首頁
上門
商家
我的
更多
運行效果

接下來我按一個功能模塊一個模塊講解整個項目

首頁

首先先聲明下本項目中的下啦刷新用的是MJRefresh,還有的第三方框架有MJExtension,AFN,SDWebImage(順便個MJ打個廣告)
#pragma mark - 設(shè)置下啦刷新
-(void)setRefreshIntableView{
[self.firstTableView addGifHeaderWithRefreshingTarget:self refreshingAction:@selector(refreshData)];`

//設(shè)置普通狀態(tài)的動畫圖片
NSMutableArray *idleImages = [NSMutableArray array];
for (NSUInteger i = 1; i<=60; ++i) {
    UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"dropdown_anim__000%zd",i]];
    [idleImages addObject:image];
}
[self.firstTableView.gifHeader setImages:idleImages forState:MJRefreshHeaderStateIdle];

//設(shè)置即將刷新狀態(tài)的動畫圖片
NSMutableArray *refreshingImages = [NSMutableArray array];
for (NSInteger i = 1; i<=3; i++) {
    UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"dropdown_loading_0%zd",i]];
    [refreshingImages addObject:image];
}
[self.firstTableView.gifHeader setImages:refreshingImages forState:MJRefreshHeaderStatePulling];

//設(shè)置正在刷新是的動畫圖片
[self.firstTableView.gifHeader setImages:refreshingImages forState:MJRefreshHeaderStateRefreshing];

//馬上進入刷新狀態(tài)
[self.firstTableView.gifHeader beginRefreshing];

}
解釋如上代碼注釋诸狭,已經(jīng)非常清楚了券膀,就是給當前的tableView君纫, [self.firstTableView addGifHeaderWithRefreshingTarget:self refreshingAction:@selector(refreshData)];
然后將所需要的動畫圖放在一個數(shù)組里面。然后設(shè)置三種狀態(tài)的刷新芹彬。
說白了首頁就是一個tableView蓄髓。這個tableView分為5個section.
每個section里面的cell進行自定義。就是這么簡單粗暴舒帮。

再說下怎么封裝tableViewCell会喝,為什么我們要封裝他呢?為什么要封裝他会前,原因通俗一點就是好乐,cell是個視圖,視圖怎么創(chuàng)建cell自己最清楚瓦宜。沒必要讓控制器知道蔚万。
送大家我之前說我的一句話:

控制器知道的越少越好,否則你將死的很慘!!!临庇。

舉個例子:
1.創(chuàng)建自定義的tableViewCell要不要XIB隨你(我這個例子用XIB)反璃。

#import <UIKit/UIKit.h>
@class JFHotQueueModel;
@interface JFHotQueueCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UIImageView *hotQueueImageView;
@property (weak, nonatomic) IBOutlet UILabel *mianLabel;
@property (weak, nonatomic) IBOutlet UILabel *subtitleLabel;
//提供一個模型的set方法
@property (nonatomic, strong)JFHotQueueModel *hotQueueModel;
//提供一個類方法傳一個tableView快速創(chuàng)建一個cell
+ (instancetype)cellWithTableView:(UITableView *)tableView;

這個地方再送你一句話:tableView,collectionView,地圖標注等都可以這個干假夺,(舉一返三淮蜈,這是一個能力)幾百萬個項目,每個項目N種做法已卷,難到我們都要敲一遍梧田?(SB才這個干)起初我們可以模仿,在模仿中總結(jié)侧蘸。一步一個腳印裁眯。我去扯的優(yōu)點遠了.

tableViewcell.m里面的實現(xiàn)

+ (instancetype)cellWithTableView:(UITableView *)tableView
{
    static NSString *ID = @"hotqueue";
    JFHotQueueCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if (cell == nil) {
        // 從xib中加載cell
        cell = [[[NSBundle mainBundle] loadNibNamed:@"JFHotQueueCell" owner:nil options:nil] lastObject];
    }
    return cell;
}
#重寫model的set方法,給XIB里面的控件賦值
-(void)setHotQueueModel:(JFHotQueueModel *)hotQueueModel{
    _hotQueueModel = hotQueueModel;
    NSURL *urlStr = [NSURL URLWithString:hotQueueModel.imageUrl];
    [self.hotQueueImageView sd_setImageWithURL:urlStr  placeholderImage:nil];
    self.mianLabel.text = hotQueueModel.title;
    self.subtitleLabel.text = hotQueueModel.comment;
}

好了第二個界面:

上門

這個界面主要講下,這么封裝圖片輪播器

cell上的輪播器

毫無疑問這個輪播器在cell上面讳癌。
只要將cell創(chuàng)建好后將封裝好的輪播器加在上面就完事了
自定義輪播器的視圖
.h文件

@interface JFImageScrollView : UIView
@property (nonatomic, strong)UIScrollView *scrollView;
@property (nonatomic, strong)UIPageControl *pageControl;
@property (nonatomic, strong)NSArray *imgArray;
-(void)setImageArray:(NSArray *)imageArray;
/**
 *  創(chuàng)建一個ScrollView
 *
 *  @param frame      供外界提供一個frame
 *  @param imageArray 供外界提供一個圖片數(shù)組
 *
 *  @return 返回一個自定義的ScrollView
 */
-(JFImageScrollView * )initWithFrame:(CGRect)frame imageArray:(NSArray *)imageArray;

.m文件

@interface JFImageScrollView ()<UIScrollViewDelegate>{
    NSTimer *_timer;
    int _pageNumber;
}
@end
@implementation JFImageScrollView
-(JFImageScrollView * )initWithFrame:(CGRect)frame imageArray:(NSArray *)imageArray{
    self = [super initWithFrame:frame];
    if (self) {
        self.scrollView = [[UIScrollView alloc]initWithFrame:frame];
        self.scrollView.contentSize = CGSizeMake(4 * SCREENWIDTH, frame.size.height);
        self.scrollView.pagingEnabled = YES;
        self.scrollView.delegate = self;
        self.scrollView.showsHorizontalScrollIndicator = NO;
        //添加圖片
        for(int i = 0 ; i < 10; i++){
            UIImageView *imageView = [[UIImageView alloc] init];
            imageView.frame = CGRectMake(i*SCREENWIDTH, 0, SCREENWIDTH, frame.size.height);
            imageView.tag = i+10;
           // UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(OnTapImage:)];
            //[imageView addGestureRecognizer:tap];
            imageView.userInteractionEnabled = YES;
            [self.scrollView addSubview:imageView];
        }
        [self addSubview:self.scrollView];
        
        //
        self.pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(SCREENWIDTH/2-40, frame.size.height-40, 80, 30)];
        self.pageControl.currentPage = 0;
        self.pageControl.numberOfPages = 6;
        [self addSubview:self.pageControl];
        
        [self addTimer];

        
    }
    return self;

}

-(void)setImageArray:(NSArray *)imageArray{
    _pageNumber = (int)imageArray.count;
    self.scrollView.contentSize = CGSizeMake(imageArray.count * SCREENWIDTH, self.frame.size.height);
    self.pageControl.numberOfPages = imageArray.count;
    //添加圖片
    for(int i = 0 ; i < imageArray.count; i++){
        UIImageView *imageView = (UIImageView *)[self.scrollView viewWithTag:i+10];
        imageView.backgroundColor = [UIColor redColor];

        NSString *imageName =[NSString stringWithFormat:@"%@",imageArray[i]];
        NSLog(@"%@",imageName);
        [imageView sd_setImageWithURL:[NSURL URLWithString:imageName] placeholderImage:[UIImage imageNamed:@"bg_customReview_image_default"]];        
    }
}
//添加計時器
-(void)addTimer{
    _timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(netxPage) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
}
//移除計時器
-(void)removeTimer{
    [_timer invalidate];
    _timer = nil;
}
//計時器每一秒的響應(yīng)方法
-(void)netxPage{
    int page = (int)self.pageControl.currentPage;
    if (page == _pageNumber-1) {
        page = 0;
    }else{
        page++;
    }
    //滾動scrollview
    CGFloat x = page * self.scrollView.frame.size.width;
    self.scrollView.contentOffset = CGPointMake(x, 0);
}

#pragma mark - UIScrollViewDelegate
//滑動時scrollView代理方法穿稳,計算出當前滑動到哪里。加上視圖寬度的一半晌坤,再整除滾動視圖寬度逢艘,算出第幾頁。
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
    CGFloat scrollViewW = scrollView.frame.size.width;
    CGFloat x = scrollView.contentOffset.x;
    int page = (x + scrollViewW/2)/scrollViewW;
    self.pageControl.currentPage = page;
}
//開始拖動時骤菠,就關(guān)閉計時器它改,因為這個時候用戶在交互。
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
    [self removeTimer];
}
//結(jié)束拖動的時候就立馬再加上計時器
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
    [self addTimer];
}

/**
 *  移除定時器
 */
-(void)dealloc{
    [self removeTimer];
}

接下來:就是創(chuàng)建八個視圖給每個視圖加手勢商乎,之前已經(jīng)說過了搔课,就不贅述。


八個視圖

商家

分類

這個界面主要講下這個自定義視圖怎么自定義的
如圖所示很明顯就是兩個tableVew.
上代碼:
.h

@protocol JFMerchantFilterViewDelegate <NSObject>

@optional
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath withId:(NSNumber *)ID ;

@end
@interface JFMerchantFilterView : UIView
/**
 *  全部分類的tableView
 */
@property(nonatomic, strong) UITableView *tableViewOfGroup;
/**
 *  每組詳情的tableView
 */
@property(nonatomic, strong) UITableView *tableViewOfDetail;
@property (nonatomic, weak) id <JFMerchantFilterViewDelegate> delegate;

.m
既然是兩個tableView那么就提供兩個數(shù)據(jù)源,兩個下標爬泥,用來識別那個tableView被點擊了哪一行柬讨。

@interface JFMerchantFilterView ()<UITableViewDataSource, UITableViewDelegate>
{
    NSMutableArray *_bigGroupArray;//左邊分組tableview的數(shù)據(jù)源
    NSMutableArray *_smallGroupArray;//右邊分組tableview的數(shù)據(jù)源
    NSInteger _bigSelectedIndex;
    NSInteger _smallSelectedIndex;
}
@end
@implementation JFMerchantFilterView
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/
-(instancetype)initWithFrame:(CGRect)frame{
    self =[super initWithFrame:frame];
    if (self) {
        _bigGroupArray = [[NSMutableArray alloc] init];
        _smallGroupArray = [[NSMutableArray alloc] init];
        [self initViews];
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [self getCateListData];
        });
    }
    return self;
}

-(void)initViews{
    for (int i = 0 ; i < 2; i ++) {
        
        UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(i *TableViewW/2,  0, TableViewW/2, TableViewH) style:UITableViewStylePlain];
        tableView.tag = 10 + i ;
        tableView.delegate = self;
        tableView.dataSource = self;
        if (i == 0 ) {
            self.tableViewOfGroup =tableView;
            self.tableViewOfGroup.backgroundColor = [UIColor whiteColor];

        }else{
            self.tableViewOfDetail =tableView;
            self.tableViewOfDetail.backgroundColor = RGB(242, 242, 242);

        }
        tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
        [self addSubview:tableView];

    }

}

-(void)getCateListData{
    NSString *urlStr = [[GetUrlString sharedManager]urlWithCateListStr];
    [NetWork sendGetUrl:urlStr withParams:nil success:^(id responseBody) {
        JFLog(@"%@", responseBody);
        NSMutableArray *dataArray = [responseBody objectForKey:@"data"];
        for (int i = 0; i < dataArray.count; i++) {
            JFMerchantCataGroupModel *cateModel = [JFMerchantCataGroupModel objectWithKeyValues:dataArray[i]];
            [_bigGroupArray addObject:cateModel];
        }
        [self.tableViewOfGroup reloadData];
    } failure:^(NSError *error) {
        
    }];
}

#pragma mark - UITableViewDataSource
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    if (tableView.tag == 10) {
        return _bigGroupArray.count;
    }else{
        if (_bigGroupArray.count == 0) {
            return 0;
        }
        JFMerchantCataGroupModel *subclassCateM = (JFMerchantCataGroupModel *)_bigGroupArray[_bigSelectedIndex];
        if (subclassCateM.list == nil) {
            return 0;
        }else{
            return subclassCateM.list.count;
        }
    }
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return 42;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    if (tableView.tag == 10) {
        JFKindFilterCell *cell = [JFKindFilterCell cellWithTableView:tableView];
        cell.merchantCataGroupModel = _bigGroupArray[indexPath.row];
        return cell;
    }else{
         JFMerchantCataGroupModel *cateModel = (JFMerchantCataGroupModel *)_bigGroupArray[_bigSelectedIndex];
        JFKindSubclassFilterCell *cell = [JFKindSubclassFilterCell cellWithTableView:tableView indexPath:indexPath model:cateModel];
        return cell;
    }
    
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    if (tableView.tag == 10) {
        _bigSelectedIndex = indexPath.row;
        JFMerchantCataGroupModel *cataModel =  _bigGroupArray[_bigSelectedIndex];
        [self.tableViewOfDetail reloadData];
        if (cataModel.list == nil) {
            [self.tableViewOfDetail reloadData];
            [self.delegate tableView:tableView didSelectRowAtIndexPath:indexPath withId:cataModel.id];
        }else{
            [self.tableViewOfDetail reloadData];
        }
    }else{
        _smallSelectedIndex = indexPath.row;
        JFMerchantCataGroupModel *cataModel =  _bigGroupArray[_bigSelectedIndex];
        NSDictionary *dict =  cataModel.list[_smallSelectedIndex];
        NSNumber *ID = [dict objectForKey:@"id"];
//        NSString *name = [dic objectForKey:@"name"];
        [self.delegate tableView:tableView didSelectRowAtIndexPath:indexPath withId:ID ];
        
    }
}

我的和更多

最后兩個界面都是比較簡單的就不多說了。
如果不懂的話可以直接簡信袍啡,或者直接評論踩官,我會一一解答。
有好的建議我會非常感謝境输。
完整的項目源碼會在 會下一次放在github上蔗牡。(這次就不放了哦,下一次會是一個比較完整的JF團購 呈現(xiàn)給大家)

希望你可以繼續(xù)關(guān)注我嗅剖。

最后重申一下本項目持續(xù)更新中辩越。。信粮。

2015 - 08 - 30

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末黔攒,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子强缘,更是在濱河造成了極大的恐慌督惰,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件旅掂,死亡現(xiàn)場離奇詭異赏胚,居然都是意外死亡,警方通過查閱死者的電腦和手機商虐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門觉阅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人秘车,你說我怎么就攤上這事典勇。” “怎么了鲫尊?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵痴柔,是天一觀的道長沦偎。 經(jīng)常有香客問我疫向,道長,這世上最難降的妖魔是什么豪嚎? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任搔驼,我火速辦了婚禮,結(jié)果婚禮上侈询,老公的妹妹穿的比我還像新娘舌涨。我一直安慰自己,他們只是感情好扔字,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布囊嘉。 她就那樣靜靜地躺著温技,像睡著了一般。 火紅的嫁衣襯著肌膚如雪扭粱。 梳的紋絲不亂的頭發(fā)上舵鳞,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天,我揣著相機與錄音琢蛤,去河邊找鬼蜓堕。 笑死,一個胖子當著我的面吹牛博其,可吹牛的內(nèi)容都是我干的套才。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼慕淡,長吁一口氣:“原來是場噩夢啊……” “哼背伴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起儡率,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤挂据,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后儿普,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體崎逃,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年眉孩,在試婚紗的時候發(fā)現(xiàn)自己被綠了个绍。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡浪汪,死狀恐怖巴柿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情死遭,我是刑警寧澤广恢,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站呀潭,受9級特大地震影響钉迷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜钠署,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一糠聪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谐鼎,春花似錦舰蟆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽味悄。三九已至,卻和暖如春塌鸯,著一層夾襖步出監(jiān)牢的瞬間傍菇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工界赔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留丢习,地道東北人。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓淮悼,卻偏偏與公主長得像咐低,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子袜腥,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫见擦、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,058評論 4 62
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,128評論 29 470
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,734評論 25 707
  • 在邏輯學(xué)中羹令,邏輯門的工作方式非常簡單 ---- 讓電流通過或者阻止電流通過 布爾表達式可以在電路中實現(xiàn)鲤屡,這個等價關(guān)...
    錢塘閱讀 307評論 0 0
  • 你在跑,我在追 小阿妹啊小阿妹 忘記了天黑
    小小仲馬閱讀 101評論 0 2