iOS开发-电商app首页模块 较复杂视图界面

iOS开发-电商app首页模块 较复杂视图界面

前言

iOS开发中关于电商平台的首页需要做的精细一点,才能吸引用户,因此app首页部分做了一个顶部banner+各种分类item,滚动有悬停的分栏列表的效果。

效果

在这里插入图片描述

大概思路

  • 顶部的banner 是一个普通的视图
  • 整体
  • 使用一个tableView,向下偏移一个banner和item距离。如下
    在这里插入图片描述
  • 分栏列表
  • 是嵌套多个ViewController完成的
    在这里插入图片描述

上代码

主视图

  • HomeViewController.m
#import "HomeViewController.h"
#import "HomeMainView.h"
#import "HomeBannerBottomModel.h"

#import "HomeSubBaseViewController.h"
#import "BestSaleViewController.h"//畅销产品
#import "NewProductViewController.h"//本月新品
#import "PromotSaleViewController.h"//本月促销
#import "DiscountSaleViewController.h"//临期折扣

@interface HomeViewController () <HomeMainViewDelegate>

@property(nonatomic, strong) HomeMainView *homeMainView;

@property(nonatomic, strong) NSMutableArray *categoryArray;
@property(nonatomic, strong) NSMutableArray *titleArray;

@end

@implementation HomeViewController

- (void)viewDidLoad {
    
    
    [super viewDidLoad];
    
    [self setNavigationHidden:YES];
    self.view.backgroundColor = [UIColor colorWithRed:241/255.0 green:240/255.0 blue:240/255.0 alpha:1];
    [self setHomeMainViewUI];
}

- (void)setHomeMainViewUI {
    
    
    [self.view addSubview:self.homeMainView];
    __weak typeof(self) weakSelf = self;
    [self.homeMainView setBlock:^(BOOL canScroll) {
    
    
        [weakSelf subTabViewCanScroll:canScroll];
    }];
    [self.homeMainView setBannerBottomItem:[HomeBannerBottomModel getHomeBottomViewData]];
    
}

- (HomeMainView *)homeMainView {
    
    
    if(_homeMainView == nil) {
    
    
        _homeMainView = [[HomeMainView alloc]initWithFrame:self.view.bounds withVC:self withVCarr:self.categoryArray titleArr:self.titleArray];
        _homeMainView.delegate = self;
    }
    return _homeMainView;
}

- (NSMutableArray *)titleArray {
    
    
    if (_titleArray == nil) {
    
    
        _titleArray = [NSMutableArray arrayWithObjects:@"category1",@"category2",@"category3",@"category4", nil];
    }
    return _titleArray;
}

- (NSMutableArray *)categoryArray {
    
    
    if (_categoryArray == nil) {
    
    
        _categoryArray = [NSMutableArray array];
        BestSaleViewController *bestSaleViewController = [[BestSaleViewController alloc] init];
        [bestSaleViewController setType:self.titleArray[0]];
        [_categoryArray addObject:bestSaleViewController];
        
        NewProductViewController *newProductViewController = [[NewProductViewController alloc] init];
        [newProductViewController setType:self.titleArray[1]];
        [_categoryArray addObject:newProductViewController];
        
        PromotSaleViewController *promotSaleViewController = [[PromotSaleViewController alloc] init];
        [promotSaleViewController setType:self.titleArray[2]];
        [_categoryArray addObject:promotSaleViewController];
        
        DiscountSaleViewController *discountSaleViewController = [[DiscountSaleViewController alloc] init];
        [discountSaleViewController setType:self.titleArray[3]];
        [_categoryArray addObject:discountSaleViewController];
    }
    return _categoryArray;
}

- (void)subTabViewCanScroll:(BOOL)canScroll {
    
    
    for (HomeSubBaseViewController *subViewController in self.categoryArray) {
    
    
        [subViewController setTableViewCanscroll:canScroll];
        if (!canScroll) {
    
    
            [subViewController setTableViewConset:CGPointZero];
        }
    }
}

#pragma mark - HomeMainViewDelegate

- (void)clickBottomCollectionViewItem:(NSIndexPath *)index {
    
    //葡萄酒,啤酒,饮料,矿泉水
    
}

- (void)bannerClickImage:(NSIndexPath *)index {
    
    //滚动图片的点击

}

- (void)beginClickSearch:(UITextField *)textField {
    
    //开始搜索
    
}

- (void)locationClick {
    
    //地理位置的点击

}

- (void)shareClick {
    
    //分享的点击
    
}

- (void)segmentIndex:(NSInteger)index {
    
    

}

@end

  • HomeMainView.h
#import <UIKit/UIKit.h>

@class HomeBannerBottomModel;
@protocol HomeMainViewDelegate <NSObject>
@optional
- (void)clickBottomCollectionViewItem:(NSIndexPath *)index;
- (void)bannerClickImage:(NSIndexPath *)index;
- (void)beginClickSearch:(UITextField *)textField;
- (void)locationClick;
- (void)shareClick;
- (void)segmentIndex:(NSInteger)index;

@end
@interface HomeMainView : UIView <HomeMainViewDelegate>
@property(nonatomic, weak) id<HomeMainViewDelegate> delegate;

@property(nonatomic, copy) void(^block)(BOOL canScroll);
- (instancetype)initWithFrame:(CGRect)frame withVC:(UIViewController *)vc withVCarr:(NSMutableArray *)vcarr titleArr:(NSMutableArray *)titleArr;

- (void)setBannerBottomItem:(NSMutableArray<HomeBannerBottomModel *> *)arr;

@end
  • HomeMainView.m
#import "HomeMainView.h"
#import "HomeTopNaviView.h"
#import "BannerView.h"
#import "SegmentView.h"
#import "SegMainScrollView.h"
#import "BaseTableView.h"
#import "HomeHeaderRefresh.h"

#import "HomeBannerBottomView.h"
#import "HomeBannerBottomModel.h"

#define BANNER_HEIGHT LYWidth(300)
#define BANNERBOTTOM LYWidth(131)

static NSString *const kHomeMainCell = @"kHomeMainCell";
@interface HomeMainView () <UITableViewDelegate,UITableViewDataSource,HomeBannerBottomViewDelegate,HomeTopNaviViewDelegate>

@property(nonatomic, strong) UIViewController *viewController;

@property(nonatomic, strong) HomeTopNaviView *homeTopNaviView;
@property(nonatomic, strong) HomeBannerBottomView *homeBannerBottomView;
@property(nonatomic, strong) BaseTableView *tableView;
@property(nonatomic, strong) SegmentView *segView;
@property(nonatomic, assign) BOOL canScroll;

@property(nonatomic, strong) NSMutableArray *segArray;
@property(nonatomic, strong) NSMutableArray *titleArray;

@end

@implementation HomeMainView

- (instancetype)initWithFrame:(CGRect)frame withVC:(UIViewController *)vc withVCarr:(NSMutableArray *)vcarr titleArr:(NSMutableArray *)titleArr {
    
    
    if(self = [super initWithFrame:frame]) {
    
    
        self.viewController = vc;
        self.segArray = vcarr;
        self.titleArray = titleArr;
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notification) name:@"tabNoti" object:nil];
        self.canScroll = YES;
        [self setSubViews];
        
//        UISwipeGestureRecognizer *swipeGestureRecognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeGestureRecognizer:)];
//        [self addGestureRecognizer:swipeGestureRecognizer];
    }
    return self;
}

- (void)notification {
    
    
    self.canScroll = YES;
    if(self.block) {
    
    
        self.block(NO);
    }
}
- (void)dealloc {
    
    
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)setSubViews {
    
    
    [self addSubview:self.tableView];
    
    //banner图
    NSArray *images = @[@"top_banner",@"top_banner",@"top_banner"];
    __weak typeof(self) weakSelf = self;
    [BannerView showBannerWithFrame:CGRectMake(0, - BANNER_HEIGHT - BANNERBOTTOM, SCREEN_WIDTH, BANNER_HEIGHT) images:images superView:self.tableView tapBlock:^(NSInteger index) {
    
    
        //NSLog(@"点击了第%ld张",index);
        [weakSelf performSelector:@selector(bannerImageClick:) withObject:[NSIndexPath indexPathWithIndex:index]];
    }];
    
    [self.tableView addSubview:self.homeBannerBottomView];
    [self addSubview:self.homeTopNaviView];
}

- (HomeTopNaviView *)homeTopNaviView {
    
    
    if(_homeTopNaviView == nil) {
    
    
        _homeTopNaviView = [[HomeTopNaviView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, LYWidth(98))];//LYWidth(98)UI长度
        _homeTopNaviView.delegate = self;
    }
    return _homeTopNaviView;
}

- (HomeBannerBottomView *)homeBannerBottomView {
    
    
    if(_homeBannerBottomView == nil) {
    
    
        _homeBannerBottomView = [[HomeBannerBottomView alloc]initWithFrame:CGRectMake(0, - BANNERBOTTOM, SCREEN_WIDTH, BANNERBOTTOM)];
        _homeBannerBottomView.delegate = self;
    }
    return _homeBannerBottomView;
}

- (SegmentView *)segView {
    
    //分栏控制器
    if(_segView == nil) {
    
    
        CGRect frame = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);//40
        _segView = [[SegmentView alloc]initWithFrame:frame items:self.titleArray pageView:self.segArray parentVC:self.viewController];
        _segView.firstSelectPage = 0;
        __weak typeof(self) weakSelf = self;
        _segView.segmentBlock = ^(NSInteger selectIndex) {
    
    
            //NSLog(@"%@",self.titleArray[selectIndex]);
            if(weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(segmentIndex:)]) {
    
    
                [weakSelf.delegate segmentIndex:selectIndex];
            }
        };
    }
    return _segView;
}

#pragma mark - TableViewController

- (BaseTableView *)tableView {
    
    
    if (_tableView == nil) {
    
    
        _tableView = [[BaseTableView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) style:UITableViewStylePlain];
        if (@available(iOS 11.0,*)) {
    
    
            _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
        } else {
    
    
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
            self.viewController.automaticallyAdjustsScrollViewInsets = NO;
#pragma clang diagnostic pop
        }
        _tableView.backgroundColor = self.superview.backgroundColor;
        _tableView.delegate = self;
        _tableView.dataSource = self;
        _tableView.estimatedRowHeight = 0;
        _tableView.contentInset = UIEdgeInsetsMake(BANNER_HEIGHT + BANNERBOTTOM, 0, 0, 0);
        __weak typeof(self) weakSelf = self;
        _tableView.mj_header = [HomeHeaderRefresh headerWithRefreshingBlock:^{
    
    
            [weakSelf endRefresh];
        }];
        [_tableView.mj_header beginRefreshing];
    }
    return _tableView;
}

- (void)endRefresh {
    
    
    [self.tableView.mj_header endRefreshing];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    
    
    return 1;
}

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

- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kHomeMainCell];
    if (cell == nil) {
    
    
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kHomeMainCell];
    }
    [cell.contentView addSubview:self.segView];
    return cell;
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    
    
    CGFloat naviH = TOP_AND_SYSTEM_HEIGHT;
    if (scrollView.contentOffset.y > -naviH) {
    
    
        scrollView.contentOffset = CGPointMake(0, - naviH);
        if (self.canScroll) {
    
    
            self.canScroll = NO;
            if(self.block) {
    
    
                self.block(YES);
            }
        }
    } else {
    
    
        if (!self.canScroll) {
    
    
            scrollView.contentOffset = CGPointMake(0, - naviH);
        }
    }
    CGFloat alpha = (scrollView.contentOffset.y + BANNER_HEIGHT + BANNERBOTTOM) / (BANNERBOTTOM + BANNER_HEIGHT - naviH);
    [self.homeTopNaviView setHomeTopNaviViewAlpha:alpha];//topNavi的变化
}

#pragma mark - HomeTopNaviViewDelegate

- (void)rightBtnBackClick {
    
    
    [self.tableView setContentOffset:CGPointMake(0, - BANNER_HEIGHT - BANNERBOTTOM) animated:YES];
    self.canScroll = YES;
    if(self.block) {
    
    
        self.block(NO);
    }
    //self.segView.scrollview.scrollEnabled = YES;
}

#pragma mark - swipeGestureRecognizer

//- (void)swipeGestureRecognizer:(UISwipeGestureRecognizer *)tap {
    
    
//    if(tap.direction == UISwipeGestureRecognizerDirectionRight && !self.canScroll && self.segView.index == 0) {
    
    
//        self.segView.scrollview.scrollEnabled = NO;
//        [self rightBtnBackClick];
//    } else {
    
    
//        return;
//    }
//}

#pragma mark - setsetBannerBottomItemData

- (void)setBannerBottomItem:(NSMutableArray<HomeBannerBottomModel *> *)arr {
    
    
    [self.homeBannerBottomView setHomeBannerBottomModel:arr];
}

#pragma mark - HomeBannerBottomViewDelegate

- (void)clickCollectionViewItem:(NSIndexPath *)index {
    
    
    if(_delegate && [_delegate respondsToSelector:@selector(clickBottomCollectionViewItem:)]) {
    
    
        [_delegate clickBottomCollectionViewItem:index];
    }
}

- (void)bannerImageClick:(NSIndexPath *)index {
    
    
    if(_delegate && [_delegate respondsToSelector:@selector(bannerClickImage:)]) {
    
    
        [_delegate bannerClickImage:index];
    }
}

- (void)homeTopNaviViewSearchChange:(UITextField *)textField {
    
    
    if(_delegate && [_delegate respondsToSelector:@selector(beginClickSearch:)]) {
    
    
        [_delegate beginClickSearch:textField];
    }
}

- (void)homeTopNaviViewLocationClick {
    
    
    if(_delegate && [_delegate respondsToSelector:@selector(locationClick)]) {
    
    
        [_delegate locationClick];
    }
}

- (void)homeTopNaviViewShareClick {
    
    
    if(_delegate && [_delegate respondsToSelector:@selector(shareClick)]) {
    
    
        [_delegate shareClick];
    }
}

@end
  • 顶部往下滑动的渐变效果
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    
    
    CGFloat naviH = TOP_AND_SYSTEM_HEIGHT;
    if (scrollView.contentOffset.y > -naviH) {
    
    
        scrollView.contentOffset = CGPointMake(0, - naviH);
        if (self.canScroll) {
    
    
            self.canScroll = NO;
            if(self.block) {
    
    
                self.block(YES);
            }
        }
    } else {
    
    
        if (!self.canScroll) {
    
    
            scrollView.contentOffset = CGPointMake(0, - naviH);
        }
    }
    CGFloat alpha = (scrollView.contentOffset.y + BANNER_HEIGHT + BANNERBOTTOM) / (BANNERBOTTOM + BANNER_HEIGHT - naviH);
    [self.homeTopNaviView setHomeTopNaviViewAlpha:alpha];//topNavi的变化
}

主要问题

  • 两个tableView的手势冲突问题,解决办法就是在向下滚动到item+banner的距离的时候,禁止底部tableView滑动的手势,开启子控制器的滑动手势。
  • 解决的代码 BaseTableView.m
#import "BaseTableView.h"

@interface BaseTableView () <UIGestureRecognizerDelegate>

@end

@implementation BaseTableView

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    
    //YES 识别两个手势
    return YES;
}

@end

Demo

Demo地址

猜你喜欢

转载自blog.csdn.net/weixin_41732253/article/details/109952732