前言
这周完成了网易云音乐的仿写,这篇博客来总结一下。网易云音乐主要实现的有三个界面,分别是“推荐”、“发现”、 “我的”,推荐页面主要是要在一个单元格上创建滚动视图并实现自动无限轮播,以及在一个单元格上实现滚动视图和数据视图的嵌套。发现页面的视图与推荐界面类似,但要实现一个换头像的功能,推出一个照片墙,实现两个视图之间的传值,并且要实现选中多张照片的判定。我的界面就是一个简单的数据视图,要实现一个夜间模式的功能,需要设置全局变量,并在视图间传值。
启动页
启动页就是页面加载出来之前展现的页面,只需要创建一个定时器,在一定时间后推出主页面即可
- (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:0 target:self selector:@selector(pressStart) userInfo:nil repeats:NO];
[self.window makeKeyAndVisible];
}
- (void)pressStart {
LoginViewController* loginViewController = [[LoginViewController alloc] init];
UINavigationController* navLoginViewController = [[UINavigationController alloc] initWithRootViewController:loginViewController];
self.window.rootViewController = navLoginViewController;
}
推荐页面
这里的整个页面本质上是一个数据视图,其中的每一行是一个单元格
从上至下一个一个讲。
首先是导航栏,导航栏要设置三个自定义的按钮,其中的文本输入框在弹出键盘后要能够收起,这里通过手势可以实现
//设置导航栏
UIImage* backgroundImage = [UIImage imageNamed:@"导航栏背景.jpg"];
UIImageView* backgroundImageView = [[UIImageView alloc] initWithImage:backgroundImage];
[self.navigationController.navigationBar addSubview:backgroundImageView];
backgroundImageView.translatesAutoresizingMaskIntoConstraints = NO;
[backgroundImageView.leadingAnchor constraintEqualToAnchor:self.navigationController.navigationBar.leadingAnchor].active = YES;
[backgroundImageView.topAnchor constraintEqualToAnchor:self.navigationController.navigationBar.topAnchor].active = YES;
[backgroundImageView.trailingAnchor constraintEqualToAnchor:self.navigationController.navigationBar.trailingAnchor].active = YES;
[backgroundImageView.bottomAnchor constraintEqualToAnchor:self.navigationController.navigationBar.bottomAnchor].active = YES;
然后是自动轮播图,自动轮播图与启动页类似,在轮播图的基础上添加定时器就可以实现。这里就不多赘述了
接下来的两个界面比较类似,都是在滚动视图上添加按钮,只是按钮的文字和图片的布局不同,这里给出其中一个单元格的示例。
self.button1 = [UIButton buttonWithType:UIButtonTypeCustom];
self.button1.frame = CGRectMake(10, 10, [UIScreen mainScreen].bounds.size.width / 3 - 10, 200);
[self.button1 setImage:[UIImage imageNamed:@"歌单1.jpg"] forState:UIControlStateNormal];
self.button1.imageView.contentMode = UIViewContentModeScaleAspectFit;
[self.button1 setTitle:@"00-09十年榜·台湾最强金曲榜" forState:UIControlStateNormal];
[self.button1 setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
self.button1.titleLabel.textAlignment = NSTextAlignmentLeft;
self.button1.titleLabel.font = [UIFont systemFontOfSize:14];
self.button1.titleLabel.numberOfLines = 2; // 设置标题为两行
self.button1.titleLabel.lineBreakMode = NSLineBreakByWordWrapping; // 设置换行模式
[self.button1 setImageEdgeInsets:UIEdgeInsetsMake(0, 0, 70, 0)];
[self.button1 setTitleEdgeInsets:UIEdgeInsetsMake(120, -120, 30, -10)];
[self.scrollView addSubview:self.button1];
这是推荐歌单单元格的其中一个按钮
接下来的视图是在单元格中创建一个滚动视图,并在滚动视图上在创建三个数据视图,也就是滚动视图与数据视图的嵌套。
self.button1 = [UIButton buttonWithType:UIButtonTypeCustom];
self.button1.frame = CGRectMake(10, 10, [UIScreen mainScreen].bounds.size.width / 3 - 10, 200);
[self.button1 setImage:[UIImage imageNamed:@"歌单1.jpg"] forState:UIControlStateNormal];
self.button1.imageView.contentMode = UIViewContentModeScaleAspectFit;
[self.button1 setTitle:@"00-09十年榜·台湾最强金曲榜" forState:UIControlStateNormal];
[self.button1 setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
self.button1.titleLabel.textAlignment = NSTextAlignmentLeft;
self.button1.titleLabel.font = [UIFont systemFontOfSize:14];
self.button1.titleLabel.numberOfLines = 2; // 设置标题为两行
self.button1.titleLabel.lineBreakMode = NSLineBreakByWordWrapping; // 设置换行模式
[self.button1 setImageEdgeInsets:UIEdgeInsetsMake(0, 0, 70, 0)];
[self.button1 setTitleEdgeInsets:UIEdgeInsetsMake(120, -120, 30, -10)];
[self.scrollView addSubview:self.button1];
这是滚动视图上一个数据视图的示例。
发现页面
这个页面的大部分视图都和之前页面或者zara的页面里的类似,这里主要讲一下换头像的功能。
首先,需要在点击单元格时推出一个界面,这个界面是照片墙,这里的照片墙是九个按钮,分别有两种状态,要对这两种状态进行统计,统计后再在按下完成按钮时对父视图控制器传值
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// 取消选中效果
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// 执行页面跳转逻辑
if (indexPath.row == 0) {
RegisterViewController *registerView = [[RegisterViewController alloc] init];
registerView.delegate = self;
[self.navigationController pushViewController:registerView animated:YES];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"照片";
self.sv = [[UIScrollView alloc] init];
self.sv.frame = CGRectMake(0, 20, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 20);
self.sv.contentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 20);
for (int i = 0; i < 3; i++) {
for (int j = 0;j < 3; j++) {
NSString* string = [NSString stringWithFormat:@"头像%d.jpg", i * 3 + (j + 1)];
NSString* string1 = [NSString stringWithFormat:@"点击头像%d.jpg", i * 3 + (j + 1)];
UIImage* image = [UIImage imageNamed:string];
UIImage* clickimage = [UIImage imageNamed:string1];
UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:image forState:UIControlStateNormal];
[button setImage:clickimage forState:UIControlStateSelected];
button.frame = CGRectMake(i * [UIScreen mainScreen].bounds.size.width / 3, 10 + 125 * j, [UIScreen mainScreen].bounds.size.width / 3, [UIScreen mainScreen].bounds.size.width / 3);
button.selected = NO;
[button addTarget:self action:@selector(pressTap:) forControlEvents:UIControlEventTouchUpInside];
[self.sv addSubview:button];
}
}
UIBarButtonItem* finish = [[UIBarButtonItem alloc] initWithTitle:@"完成" style:UIBarButtonItemStyleDone target:self action:@selector(finish)];
self.navigationItem.rightBarButtonItem = finish;
[self.view addSubview:self.sv];
}
- (void)pressTap:(UIButton*)button {
button.selected = !button.selected;
if (button.selected) {
self.photoCount++;
} else {
self.photoCount--;
}
}
- (void)finish {
if (self.photoCount == 1) {
for (UIView* subview in self.sv.subviews) {
if ([subview isKindOfClass:[UIButton class]]) {
UIButton* button =(UIButton*)subview;
if (button.selected) {
UIImage* image = [button imageForState:UIControlStateNormal];
[self.delegate PassImage:image];
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"修改成功!" message:@"头像修改成功!" preferredStyle:UIAlertControllerStyleAlert];
// 添加操作按钮
UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[self.navigationController popViewControllerAnimated:YES];
}];
//将确认按钮添加到我们的警告框中
[alertController addAction:action];
[self presentViewController:alertController animated:YES completion:nil];
button.selected = NO;
break;
}
}
}
} else {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"修改失败!" message:@"只能选择一张图片!" preferredStyle:UIAlertControllerStyleAlert];
// 添加操作按钮
UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
return;
}];
//将确认按钮添加到我们的警告框中
[alertController addAction:action];
[self presentViewController:alertController animated:YES completion:nil];
}
}
我的界面
这个界面的视图一样与先前的界面类似,这里主要讲一下夜间模式的实现,这里的夜间模式需要设置一个全局变量,通过全局变量来设置开关,通过全局变量来实现其他界面的夜间模式。
这里给出当前界面的实现方式,其他界面可以在viewwillappear中判断全局变量再实现颜色的改变
AppDelegate *appDelegate = (AppDelegate *)[UIApplicationsharedApplication].delegate;
tableCell.aswitch.frame = CGRectMake(330, 0, 35, 35);
[tableCell.aswitch setOn:appDelegate.isNightMode];
[tableCell.aswitch addTarget:self action:@selector(pressSwitch:) forControlEvents:UIControlEventValueChanged];
[tableCell.contentView addSubview:tableCell.aswitch];
cell.backgroundColor = [UIColor whiteColor];
if (appDelegate.isNightMode){
cell.backgroundColor = [UIColor grayColor];
}
- (void)pressSwitch:(UISwitch*)sw {
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.isNightMode = sw.isOn;
[self.tableView reloadData];
if (appDelegate.isNightMode) {
self.tableView.backgroundColor = [UIColor blackColor];
} else {
self.tableView.backgroundColor = [UIColor whiteColor];
}
[[NSNotificationCenter defaultCenter] postNotificationName:@"nightMode" object:nil];
}
总结
网易云音乐的仿写不算太难,用到了很多之前学过的知识,让我对这些知识的认识深刻了许多,也学到了许多新的知识,希望接下来可以继续进步。