一、ZARA仿写
本次仿写完成了ZARA的首页、分类和我的页面。实现了滚动视图的无限轮播、结合分栏控件和无限滚动视图、自定义cell和cell的复用以及UItableView的相关协议。
1.1 首页
1.1.1 无限轮播视图
首页视图先创建了一个UIScrollView并设定好相关属性。接下来为该滚动视图添加图片,为了实现无限轮播功能,在我们要加入的图片的第一张前增添一张我们要加入的图片的最后一张,同样的,在我们要加入的图片的最后一张之后增添一张我们要加入的图片的第一张。然后遵守一下UIScrollViewDelegate协议并设置滚动视图的代理为当前视图,这样我们就能调用视图滚动是的函数。在视图滚动时的函数中,计算出每张图片的偏移值并除以相应的宽度得到每张图片的页的序号。在图片的序号到最后一张时,使用setContentOffset方法将滚动视图移到第一张图片的位置,相同的,当图片的序号在第一张的时候,将滚动视图移动到最后一张的位置,从而实现滚动视图的循环。
代码实现:
使用按钮控制的视图滚动:
- (void)scrollChange: (UIButton*) btn {
//定义一个变量来记录当前所在的页数
//currentPage方法返回的是当前页面控件的页数
NSInteger page3 = _page.currentPage + 1;
//对按钮的tag值进行判断
if (btn.tag == 111) {
//当选择向左滑按钮,且滚动视图位于第一张图片时,按下按钮就将页数跳到最后一张图片
if (page3 == 1) {
page3 = 8;
[self.ScrollView setContentOffset:CGPointMake(0, 0) animated:YES];
[self.ScrollView setContentOffset:CGPointMake(9 * 334, 0)];
} else {
//滚动视图不在第一张图片的时候,每次按下按钮,页数就光是向前跳一张
page3--;
[self.ScrollView setContentOffset:CGPointMake(page3 * 334, 0) animated:YES];
}
}
if (btn.tag == 222) {
//当选择向右按钮的时候,且滚动视图位于最后一张图片的时候,按下按钮就将页数跳到第一章图片
if (page3 == 8) {
page3 = 0;
[self.ScrollView setContentOffset:CGPointMake(9 * 334, 0) animated:YES];
[self.ScrollView setContentOffset:CGPointMake(0, 0)];
} else {
//当滚动视图不在最后一张图片的时候,按下按钮就光是页数向后跳一张
page3++;
[self.ScrollView setContentOffset:CGPointMake(page3 * 334, 0) animated:YES];
}
}
//根据上方代码确定的页数,将当前视图跳转到指定的位置
//setContentOffset方法的功能是跳转到你指定内容的坐标
}
使用滑动屏幕控制滚动:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
NSInteger pageX = self.ScrollView.contentOffset.x/167;
NSLog(@"%f",self.ScrollView.contentOffset.x);
if (pageX == 18) {
[self.ScrollView setContentOffset:CGPointMake(334, 0)];
}
if (pageX == 0) {
[self.ScrollView setContentOffset:CGPointMake(334 * 8, 0)];
}
}
页面效果:
1.1.2 UIPageControl:页面控件
该控件由N个小圆点组成,每个圆点表示一个页面,可以通过滑动等与用户交互,并且监测当前值的变化,继而调用自定义的方法来实现界面的切换。
相关方法:
//创建一个页面控件
self.page = [[UIPageControl alloc] init];
//将页面控件的页面数置为8,是我们添加的图片数
self.page.numberOfPages = 8;
//将页面控件一开始的位置置于页面为0的位置
self.page.currentPage = 0;
//设置页面控件的小圆点的位置
self.page.frame = CGRectMake(50, 700, 300, 20);
//设置页面控件的小圆点的颜色
self.page.currentPageIndicatorTintColor = [UIColor whiteColor];
UIView层次切换
[A bringSubviewToFront: B]:将B视图显示在A视图前面
[A sendSubviewToBack: B]: 将B视图显示在A视图后面
1.2 分类
在该页面加入一个分栏控件和一个滚动视图控件。这个页面要求使用分栏控件控制滚动视图,并且滚动视图也可以滑动屏幕控制,并且滚动视图无限轮播。其实思路和上面那个一样,就是使用视图滚动时的函数,得到视图的页的序号,然后为分栏控件添加事件函数,当分栏控件的索引是某个数时,就将滚动视图移动到相应的视图,同样的当滑动屏幕到某个视图时,也要将分栏控件的索引改为当前索引。无限滚动视图部分和上面相同。
代码实现:
分栏控件部分:
- (void)viewDidLoad {
[super viewDidLoad];
......
[self.segment insertSegmentWithTitle:@"男士" atIndex:0 animated:YES];
[self.segment insertSegmentWithTitle:@"女士" atIndex:1 animated:YES];
[self.segment insertSegmentWithTitle:@"儿童" atIndex:2 animated:YES];
self.segment.selectedSegmentIndex = 0;
[self.segment addTarget:self action:@selector(indexChange:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:self.segment];
......
}
- (void)indexChange: (UISegmentedControl*)segment {
if (segment.selectedSegmentIndex == 0) {
[self.scrollView setContentOffset:CGPointMake(334, 0) animated:YES];
}
if (segment.selectedSegmentIndex == 1) {
[self.scrollView setContentOffset:CGPointMake(334 * 2, 0) animated:YES];
}
if (segment.selectedSegmentIndex == 2) {
[self.scrollView setContentOffset:CGPointMake(334 * 3, 0) animated:YES];
}
}
滑动函数部分:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSInteger pageX = self.scrollView.contentOffset.x/167;
self.segment.selectedSegmentIndex = (pageX - 1)/2;
self.page.currentPage = self.segment.selectedSegmentIndex;
NSLog(@"%ld",pageX);
if (pageX == 8) {
[self.scrollView setContentOffset:CGPointMake(334, 0)];
}
if (pageX == 0) {
[self.scrollView setContentOffset:CGPointMake(1160, 0)];
}
}
这里的页数是视图偏移量除以原视图宽度的一半,对其进行判断的时候也要对判断的页数乘以2.
1.3 我的
该页面主要实现了cell的复用、自定义cell以及UITableView的相关协议。在该界面,首先使用注册的方法复用cell(前几篇博客写过),然后自定义cell部分,我自定义了两个cell,一个是负责设定头像ID等内容,一个是负责设定选项内容的。完成了UITableView的创建相关后,设定了cell的点击函数,点击函数push出一个新视图。
二、网易云音乐仿写
网易云音乐主要完成了启动页、自定义滚动视图cell、无限轮播图、夜间模式以及导航栏控件的设定等。写了三个界面,分别是发现、我的和设置。
2.1 启动页
启动页的实现是先新建一个启动页视图,并为视图中添加启动页相关的图片等,然后在SceneDelegate文件中定义一个定时器。先将window的根视图控制器设为启动页的视图控制器,为定时器设定时间和事件,当定时器启动后执行定时器事件:将window的根视图控制器设为首页的视图控制器,并且在设置定时器时记得将定时器的重复执行关闭。
代码实现:
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
self.window.frame = [UIScreen mainScreen].bounds;
StartViewController *start = [[StartViewController alloc] init];
self.window.rootViewController = start;
self.timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(pressStart) userInfo:nil repeats:NO];
[self.window makeKeyAndVisible];
}
- (void)pressStart {
UITabBarController *tabbar = [[UITabBarController alloc] init];
ShouYeViewController *shouye = [[ShouYeViewController alloc] init];
WoDeViewController *wode = [[WoDeViewController alloc] init];
FaXianViewController *faxian = [[FaXianViewController alloc] init];
wode.title = @"我的";
UITabBarItem *btn = [[UITabBarItem alloc] initWithTitle:@"设置" image:[UIImage imageNamed:@"shouye.png"] tag:101];
shouye.tabBarItem = btn;
UITabBarItem *btn2 = [[UITabBarItem alloc] initWithTitle:@"我的" image:[UIImage imageNamed:@"icon-home.png"] tag:103];
wode.tabBarItem = btn2;
UITabBarItem *btnFaxian = [[UITabBarItem alloc] initWithTitle:@"发现" image:[UIImage imageNamed:@"compass.png"] tag: 102];
faxian.tabBarItem = btnFaxian;
UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:wode];
UINavigationController *faxianNavigation = [[UINavigationController alloc] initWithRootViewController:faxian];
NSArray *arr = [NSArray arrayWithObjects:faxianNavigation, navigation, shouye, nil];
tabbar.viewControllers = arr;
tabbar.tabBar.translucent = YES;
tabbar.tabBar.backgroundColor = [UIColor whiteColor];
self.window.rootViewController = tabbar;
tabbar.tabBar.tintColor = [UIColor redColor];
[self.window makeKeyAndVisible];
}
2.2 发现
在发现界面中为导航栏添加了两个按钮和一个输入框,在主视图添加了一个UITableView并且使用了自定义cell给cell中添加了滚动视图。在第一个cell为滚动视图添加了定时器,使其实现自动无限轮播。
代码实现:
为导航栏添加控件:
UIBarButtonItem *moreButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"gengduo-2.png"] style:UIBarButtonItemStylePlain target:self action:@selector(pressMore)];
moreButton.tintColor = [UIColor redColor];
UIBarButtonItem *textItem = [[UIBarButtonItem alloc] initWithCustomView:self.textField];
NSArray *arr = [NSArray arrayWithObjects:moreButton,textItem, nil];
self.navigationItem.leftBarButtonItems = arr;
UIBarButtonItem *musicButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"maikefeng.png"] style:UIBarButtonItemStylePlain target:self action:@selector(pressMusic)];
musicButton.tintColor = [UIColor redColor];
self.navigationItem.rightBarButtonItem = musicButton;
定时器实现无限轮播视图:
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
self.scroll = [[UIScrollView alloc] init];
self.scroll.contentSize = CGSizeMake(370 * 6, 180);
self.scroll.delegate = self;
self.scroll.pagingEnabled = YES;
self.scroll.showsHorizontalScrollIndicator = NO;
for (int i = 0; i < 5; i++) {
if (i == 0) {
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"xxp4.jpg"]];
imageView.frame = CGRectMake(0, 0, 370, 180);
[self.scroll addSubview:imageView];
} else {
NSString *str = [NSString stringWithFormat:@"xxp%d.jpg",i];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:str]];
imageView.frame = CGRectMake(370 * i, 0, 370, 180);
[self.scroll addSubview:imageView];
}
}
self.timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(pressPic:) userInfo:nil repeats:YES];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"xxp1.jpg"]];
imageView.frame = CGRectMake(370 * 5, 0, 370, 180);
[self.scroll addSubview:imageView];
[self.scroll setContentOffset:CGPointMake(370, 0)];
[self.contentView addSubview:self.page];
[self.contentView addSubview:self.scroll];
[self.scroll sendSubviewToBack:self.page];
return self;
}
- (void)layoutSubviews {
self.scroll.frame = CGRectMake(10, 0, 370, 180);
self.page.frame = CGRectMake(160, 120, 100, 20);
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSInteger thePage = self.scroll.contentOffset.x / 370;
if (thePage == 0) {
[self.scroll setContentOffset:CGPointMake(370 * 5, 0) animated:NO];
}
}
- (void)pressPic: (TuPianTableViewCell*) cell {
NSInteger pageX = self.scroll.contentOffset.x / 370;
self.page.currentPage = pageX;
if (pageX == 5) {
[self.scroll setContentOffset:CGPointMake(370, 0) animated:NO];
[self.scroll setContentOffset:CGPointMake(370 * 2, 0) animated:YES];
pageX = 2;
} else {
[self.scroll setContentOffset:CGPointMake(370 * (pageX + 1), 0) animated:YES];
}
}
2.3 我的
我的界面主要也是做了cell的复用和自定义cell等,关于cell的相关设置已经了解了许多,详情可见之前的博客,这里就不细说具体的代码内容了。
2.4 设置
该页面主要实现的重要功能是夜间模式,即单元格中的开关开启时,将当前视图的单元格和背景颜色都改为深色,这里可以使用代理传值,也可以使用属性传值,我这里是用的属性传值,通过在UITableView所在的视图控制器中定义相关的判断单元格中夜间模式开关状态的属性(BOOL),然后为开关添加开关事件,开关触发事件后将当前开关的开关状态赋值给我们定义的那个BOOL值,然后更新UITableView的数据。在创建单元格的函数中对这个BOOL值进行判断,如果为YES(开关开启状态)就将单元格以及背景颜色设置为深色,并且将新单元格的开关状态设置为YES;反之如果为NO(开关关闭状态),就将单元格以及背景颜色设置为浅色,并且将新单元格的开关状态设置为NO。仅仅通过属性传值的话,夜间模式只能将当前页面的颜色设置为深色,如果想要所有页面的颜色都为深色,就需要用到代理传值,由于在仿写网易云的时候代理传值我还没有很懂,因此在暑期第二周的3GShare项目中我会再详细说代理传值的用法。
代码实现:
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
FirstTableViewCell *cell1 = [self.tab dequeueReusableCellWithIdentifier:str1];
SecondTableViewCell *cell2 = [self.tab dequeueReusableCellWithIdentifier:str2];
ThirdTableViewCell *cell3 = [self.tab dequeueReusableCellWithIdentifier:str3];
NightTableViewCell *cell4 = [self.tab dequeueReusableCellWithIdentifier:str4];
//NightTableViewCell是自定义的夜间模式cell
//self.SwitchValue是定义的判断开关状态的BOOL值
if (self.SwitchValue == 1) {
cell4.switch1.on = YES;
cell1.backgroundColor = [UIColor grayColor];
cell2.backgroundColor = [UIColor grayColor];
cell3.backgroundColor = [UIColor grayColor];
cell4.backgroundColor = [UIColor grayColor];
self.view.backgroundColor = [UIColor blackColor];
self.tab.backgroundColor = [UIColor darkGrayColor];
self.tabBarController.tabBar.backgroundColor = [UIColor blackColor];
} else {
cell4.switch1.on = NO;
cell1.backgroundColor = [UIColor whiteColor];
cell2.backgroundColor = [UIColor whiteColor];
cell3.backgroundColor = [UIColor whiteColor];
cell4.backgroundColor = [UIColor whiteColor];
self.view.backgroundColor = [UIColor whiteColor];
self.tab.backgroundColor = [UIColor whiteColor];
self.tabBarController.tabBar.backgroundColor = [UIColor whiteColor];
}
......
if (indexPath.row == 1) {
cell4.label.text = @"夜间模式";
cell4.imageV.image = [UIImage imageNamed:@"yueliang.png"];
[cell4.switch1 addTarget:self action:@selector(pressNight:) forControlEvents:UIControlEventValueChanged];
return cell4;
}
......
}
- (void)pressNight: (UISwitch*) SwitchOn {
self.SwitchValue = SwitchOn.isOn;
//reloadData更新单元格
[self.tab reloadData];
}