往夜 -- 原来世界如此性感
来源:互联网 发布:视频剪辑软件 知乎 编辑:程序博客网 时间:2024/04/28 18:29
往夜 -- 原来世界如此性感
项目简介
- 项目为纯代码编写, 项目周期为14天。
- APP分为三个大模块
- 往夜模块
- 精选模块
- 专题模块
项目展示分析
整体结构
用到的三方轮子
项目时间轴
2017年2月7日
- 网络工具类编写
#import <Foundation/Foundation.h>@interface BaseNetManager : NSObject//GET+ (id)GET:(NSString *)path param:(NSDictionary *)param completionHandler:(void(^)(id obj, NSError *error))completionHandler;//POST+ (id)POST:(NSString *)path param:(NSDictionary *)param completionHandler:(void(^)(id obj, NSError *error))completionHandler;@end
//GET @implementation BaseNetManager+ (id)GET:(NSString *)path param:(NSDictionary *)param completionHandler:(void (^)(id, NSError *))completionHandler{ AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; manager.requestSerializer.timeoutInterval = 10; manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html", @"application/json", @"text/json", @"text/javascript", @"text/plain", nil]; return [manager GET:path parameters:param progress:^(NSProgress * _Nonnull downloadProgress) { } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSLog(@"%@", task.currentRequest.URL.absoluteString); !completionHandler ?: completionHandler(responseObject, nil); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"%@", error); }];}//POST+ (id)POST:(NSString *)path param:(NSDictionary *)param completionHandler:(void (^)(id, NSError *))completionHandler{ AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; manager.requestSerializer.timeoutInterval = 15; manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html", @"application/json", @"text/json", @"text/javascript", @"text/plain", nil]; return [manager POST:path parameters:param progress:^(NSProgress * _Nonnull uploadProgress) { } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSLog(@"%@", task.currentRequest.URL.absoluteString); !completionHandler ?: completionHandler(responseObject, nil); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"%@", error); !completionHandler ?: completionHandler(nil, error); }];}@end
2017年2月8日
#import "YGTabBarController.h"#import "YGHomeController.h"#import "YGEssenceController.h"#import "YGListController.h"#import "YGListFlowLayout.h"#import "YGPageController.h"@interface YGTabBarController ()@end@implementation YGTabBarController- (void)viewDidLoad { [super viewDidLoad]; [self allPropertySetup]; [self setupAllControllers];}#pragma mark - 全局属性- (void)allPropertySetup{ [UITabBar appearance].tintColor = YGRGBColor(67, 67, 67); [UINavigationBar appearance].tintColor = YGRGBColor(67, 67, 67); [[UITabBarItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName: YGRGBColor(67, 67, 67)} forState:UIControlStateSelected]; [UIImageView appearance].contentMode = UIViewContentModeScaleAspectFill; [UIImageView appearance].clipsToBounds = YES; [UICollectionView appearance].backgroundColor = YGBgColor; [UIImageView appearance].contentMode = UIViewContentModeScaleAspectFill; [UIImageView appearance].clipsToBounds = YES;}#pragma mark - 创建所有tabBar子控制器- (void)setupAllControllers{ YGPageController *pageVC = [[YGPageController alloc] init]; pageVC.tabBarItem.image = @"nav_ic_home_default".yg_image; pageVC.tabBarItem.selectedImage = @"nav_ic_home_selected".yg_image; pageVC.title = @"往夜"; UINavigationController *homeNavi = [[UINavigationController alloc] initWithRootViewController:pageVC]; YGEssenceController *essenceVC = [[YGEssenceController alloc] initWithStyle:UITableViewStylePlain]; essenceVC.title = @"精选"; essenceVC.tabBarItem.image = @"tab_btn_list_default".yg_image; essenceVC.tabBarItem.selectedImage = @"tab_btn_list_select".yg_image; UINavigationController *essenceNavi = [[UINavigationController alloc] initWithRootViewController:essenceVC]; YGListController *listVC = [[YGListController alloc] initWithCollectionViewLayout:[[YGListFlowLayout alloc] init]]; listVC.title = @"专题"; listVC.tabBarItem.image = @"nav_ic_columns_default".yg_image; listVC.tabBarItem.selectedImage = @"nav_ic_columns_selected".yg_image; UINavigationController *listNavi = [[UINavigationController alloc] initWithRootViewController:listVC]; self.viewControllers = @[homeNavi, essenceNavi, listNavi];}#pragma mark - 关闭设备自动旋转, 然后手动监测设备旋转方向来旋转avplayerView-(BOOL)shouldAutorotate{ return NO;}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}@end
2017年2月9日 - 2017年2月13日
往夜资讯, 我从稍微简单的页面入手 -- 精华模块
- 整体为TableViewController, 里面分为三种Cell
- 整体用masonry进行Layout布局
- 界面整体比较简单, 其中Cell自适应高度, 我使用的UITableView-FDTemplateLayoutCell进行高性能自适应高度, 前百度forkingdog团队, 现在的滴滴打车的iOS大神Sunnyxx发布的高性能Cell自动高度计算框架.
//高性能计算行高- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ YGEssenceResponseFeedsItem *feedsItem = self.essenceArr[indexPath.section]; if (feedsItem.type == 1) { return [tableView fd_heightForCellWithIdentifier:@"YGEssenceCommomCell" configuration:^(YGEssenceCommomCell *cell) { cell.iconIV.imageURL = feedsItem.image.yg_URL; }]; } if (feedsItem.type == 0) { return [tableView fd_heightForCellWithIdentifier:@"YGEssenceImageCell" configuration:^(YGEssenceImageCell *cell) { [cell.iconIV setImageWithURL:feedsItem.image.yg_URL options:YYWebImageOptionIgnoreAnimatedImage]; }]; } return [tableView fd_heightForCellWithIdentifier:@"YGEssenceBigCell" configuration:^(YGEssenceBigCell *cell) { cell.titleLB.text = feedsItem.post.title; cell.detailLB.text = feedsItem.post.des; [cell.iconIV setImageWithURL:feedsItem.image.yg_URL options:YYWebImageOptionIgnoreAnimatedImage]; }]; }
- 精华模块主要是资讯信息, 里面用到的是UIWebView来显示, 里面有一个退出按钮的小动画, 让我稍微琢磨了一小下。
#pragma mark - 创建悬浮按钮- (void)creatSuspendButton{ self.suspendBtn = [UIButton buttonWithType:UIButtonTypeCustom]; [self.suspendBtn setBackgroundImage:[UIImage imageNamed:@"homeBackButton"] forState:UIControlStateNormal]; self.suspendBtn.frame = CGRectMake(0, 0, 54, 54); [self.suspendBtn addTarget:self action:@selector(clickSuspendButton) forControlEvents:UIControlEventTouchUpInside]; //创建悬浮按钮的window self.buttonWin = [[UIView alloc] initWithFrame:CGRectMake(25, YGScreenH - 60, 54, 54)]; self.buttonWin.backgroundColor = [UIColor clearColor]; //将buttonWin显示出来 [self.view addSubview:self.buttonWin]; [self.buttonWin addSubview:self.suspendBtn]; }//点击悬浮按钮- (void)clickSuspendButton{ self.buttonWin.hidden = YES; self.buttonWin = nil; [self.navigationController popViewControllerAnimated:YES];}#pragma mark - viewWillAppear- (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; self.navigationController.navigationBarHidden = YES;}#pragma mark - viewViewDisappear- (void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:animated]; self.navigationController.navigationBarHidden = NO;}//按钮隐藏#pragma mark - <UIScrollViewDelegate>- (void)scrollViewDidScroll:(UIScrollView *)scrollView{ if (scrollView.contentOffset.y > _offsetY + 1) { [self suspensionWithAlpha:0]; } else if (scrollView.contentOffset.y < _offsetY) { [self suspensionWithAlpha:1]; }}//停止滚动式调用- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{ _offsetY = scrollView.contentOffset.y;}//设置悬浮按钮的透明度- (void)suspensionWithAlpha:(CGFloat)alpha{ [UIView animateWithDuration:0.3 animations:^{ [self.buttonWin setAlpha:alpha]; }];}
- 具体示例
2017年2月14日 - 2017年2月15日
栏目模块结构
- 专题模块分为三次跳转
- 第一个界面
UICollectionViewController
- 第二个界面
UITableViewController
- 第三个界面播放界面
UIViewController
- 第一个界面
- 专题模块 和 列表详细整体masonry布局
- 列表详细播放中的播放我采用的是
HcdCachePlayer
HcdCachePlayer
对于整体播放, 缓存有着良好的集成
#import "YGListDetailMovieController.h"@interface YGListDetailMovieController (){ //播放器 HcdCacheVideoPlayer *_play; }/** 背景 */@property(nonatomic, strong) UIImageView *bgView;/** 头像 */@property(nonatomic, strong) UIImageView *headView;/** 详细 */@property(nonatomic, strong) UILabel *detailLb;/** 影片简介 */@property(nonatomic, strong) UILabel *constLabel;/** 播放按钮 */@property(nonatomic, strong) UIButton *playBtn;// 计算属性, 屏幕大小@property (nonatomic, assign) CGSize screenSize;@end@implementation YGListDetailMovieController- (instancetype)initWithBgImageView:(NSString *)bgImageView titleView:(NSString *)titleView detailLabel:(NSString *)titleLabel url:(NSString *)url;{ self = [super init]; if (self) { self.titleView = titleView; self.bgImageView = bgImageView; self.detailLabel = titleLabel; self.url = url; self.hidesBottomBarWhenPushed = YES; } return self;}- (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; [self configUI];}//配置播放界面- (void)configUI{ self.bgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, YGScreenW, YGScreenH)]; self.bgView.userInteractionEnabled = YES; [self.bgView setImageURL:self.bgImageView.yg_URL]; [self.view addSubview:self.bgView]; self.headView = [[UIImageView alloc] init]; [self.headView setImageURL:self.titleView.yg_URL]; self.headView.userInteractionEnabled = YES; [self.bgView addSubview:self.headView]; [self.headView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.offset(0); make.top.offset(64); CGFloat scale = 27 / 32.0; make.height.mas_equalTo(self.headView.mas_width).multipliedBy(scale); }]; self.constLabel = [[UILabel alloc] init]; self.constLabel.font = [UIFont boldSystemFontOfSize:18]; self.constLabel.textColor = [UIColor whiteColor]; self.constLabel.text = @"影片简介:"; [self.bgView addSubview:self.constLabel]; [self.constLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.left.offset(10); make.top.mas_equalTo(self.headView.mas_bottom).offset(10); }]; self.detailLb = [[UILabel alloc] init]; self.detailLb.text = self.detailLabel; self.detailLb.textColor = [UIColor whiteColor]; self.detailLb.numberOfLines = 0; [self.bgView addSubview:self.detailLb]; [self.detailLb mas_makeConstraints:^(MASConstraintMaker *make) { make.left.offset(10); make.right.offset(-10); make.top.mas_equalTo(self.constLabel.mas_bottom).offset(10); }]; self.playBtn = [UIButton buttonWithType:UIButtonTypeSystem]; [self.playBtn setImage:[UIImage imageNamed:@"play_button"] forState:UIControlStateNormal]; [self.headView addSubview:self.playBtn]; [self.playBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.center.offset(0); make.size.mas_equalTo(60); }]; [self.playBtn addTarget:self action:@selector(playMovie) forControlEvents:UIControlEventTouchUpInside];}//播放视频- (void)playMovie{ self.headView.hidden = YES; // self.constLabel.hidden = YES; // self.detailLb.hidden = YES; //点击后创建播放界面 _play = [[HcdCacheVideoPlayer alloc] init]; UIView *videoView = [[UIView alloc] initWithFrame:CGRectMake(0, 64, YGScreenW, YGScreenW * 27 / 32.0)]; [self.view addSubview:videoView]; //播放 [_play playWithUrl:self.url.yg_URL showView:videoView andSuperView:self.view withCache:YES]; NSLog(@"%@", NSHomeDirectory()); NSLog(@"%f", [HcdCacheVideoPlayer allVideoCacheSize]); }- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}#pragma mark - 生命周期方法- (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; }- (void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:animated]; [_play stop];#warning WAIT TODO:在这里先清除全部缓存 [HcdCacheVideoPlayer clearAllVideoCache]; }- (CGSize)screenSize{ return [UIScreen mainScreen].bounds.size;}@end
- 视频展示
2017年2月16日
- 开始往夜模块编写
- 插曲
- 将Model层, View层全部写完, Controller层全部写完, 就差播放视频, 发现视频加密, 显示的全部垃圾广告。一晚白忙。此时凌晨3:35。
2017年2月17日 - 2月19日
往夜 “往” 模块分为两种Cell
- 一种Cell为资讯展示
- 一种Cell为视频展示
- 往夜 “夜” 模块
- ”夜“模块
- 第一个界面为TableviewController
- 点入”更多专题“为UICollectionViewController
- 点入专题详细列表, 表头为拉伸图片, 下面是tableview
- 更多专题中有显示图片的专题
- 我用的是
MWPhotoBrowser
这个框架
- 我用的是
2017年2月20日
- 收尾
整体分析
- 项目主要以展示资讯,新闻,影视短片为主。
- 项目架构简约,整体色调灰黑色。
- 整个项目没有xib 或者 sb参与
项目中细节梳理
- 头部无限轮播
- 使用
iCarousel
三方搭建。- 本来有考虑使用自己写的一个无限轮播 框架,但是我没有别的封装,仅仅只是实现了高性能轮播。所以我是用了
iCarousel
三方搭建。
- 本来有考虑使用自己写的一个无限轮播 框架,但是我没有别的封装,仅仅只是实现了高性能轮播。所以我是用了
#pragma mark - <ic Delegate>- (NSInteger)numberOfItemsInCarousel:(iCarousel *)carousel{ return self.loopArr.count;}- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view{ if (!view) { view = [[UIView alloc] initWithFrame:carousel.bounds]; UIImageView *iconIV = [[UIImageView alloc] init]; [view addSubview:iconIV]; [iconIV mas_makeConstraints:^(MASConstraintMaker *make) { make.top.left.right.offset(0); CGFloat scale = 38 / 64.0; make.height.mas_equalTo(iconIV.mas_width).multipliedBy(scale); }]; iconIV.tag = 100; } YYAnimatedImageView *iconIV = [view viewWithTag:100]; [iconIV setImageWithURL:[NSURL URLWithString:self.loopArr[index]] options:YYWebImageOptionIgnoreAnimatedImage]; return view;}//只有变化时候才会来到这个方法- (void)carouselCurrentItemIndexDidChange:(iCarousel *)carousel{ self.titleLb.text = self.bannersArr[carousel.currentItemIndex].post.title; self.pc.currentPage = carousel.currentItemIndex;}- (void)carousel:(iCarousel *)carousel didSelectItemAtIndex:(NSInteger)index{ YGEssenceWebController *webVC = [[YGEssenceWebController alloc] initWithAppView:self.bannersArr[index].post.appview]; [self.navigationController pushViewController:webVC animated:YES];}- (CGFloat)carousel:(iCarousel *)carousel valueForOption:(iCarouselOption)option withDefault:(CGFloat)value{ if (option == iCarouselOptionWrap) { value = YES; } return value;}
- “往夜”模块头部横向滚动
- 使用的是一款
WMPageController
的三方控件
- 使用的是一款
@interface YGPageController ()@end@implementation YGPageController//初始化方法- (instancetype)init{ if (self = [super init]) { self.menuBGColor = YGRGBColor(249, 249, 249); self.menuViewStyle = WMMenuViewStyleLine; self.menuViewLayoutMode = WMMenuViewLayoutModeCenter; self.titleSizeNormal = 20; self.titleSizeSelected = self.titleSizeNormal; self.titleColorSelected = self.titleColorNormal; self.automaticallyCalculatesItemWidths = YES; //根据题目的内容自动算宽度 self.itemMargin = 30; //题目的间距 self.menuHeight = 44; self.showOnNavigationBar = YES; } return self;}- (NSArray<NSString *> *)titles{ return @[@"往", @"夜"];}- (NSInteger)numbersOfChildControllersInPageController:(WMPageController *)pageController{ return self.titles.count;}- (UIViewController *)pageController:(WMPageController *)pageController viewControllerAtIndex:(NSInteger)index{ if (index == 0) { YGHomeController *homeVC = [[YGHomeController alloc] init]; return homeVC; } YGCategoryController *cateVC = [[YGCategoryController alloc] init]; return cateVC;}- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view.}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}
YG -- 阳光
业余时间的作品,每天晚上11点开始码代码,平均凌晨4点左右结束,早上9点还要忙自己的事情。
如果觉得写得还不错请给予一颗小⭐️⭐️
GitHub地址
博客园地址
往夜 项目地址
0 0
- 往夜 -- 原来世界如此性感
- 往夜 -- 原来世界如此性感
- 往夜 -- 原来世界如此性感
- 往夜 -- 原来世界如此性感
- 往夜 -- 原来世界如此性感
- 往夜 -- 原来世界如此性感
- 原来世界如此宁静
- 原来,如此
- lena,知识从未如此性感
- 原来问题如此简单
- 原来lucene如此简单
- 原来英语单词如此简单!
- 原来生命可以如此张扬
- 原来爱情是如此温暖
- 原来天空竟如此刺眼
- 如此娇媚性感的容颜卖C++相关介绍
- 另一个世界原来近在咫尺
- Java的世界如此美妙
- tomcat Could not load the Tomcat server configuration at \Servers\Tomcat v8.0 Server at localhost-co
- Oracle bulk into clause
- Google Guava 类库简介
- pt-online-schema-change在线修改MYSQL表结构
- struts2拦截器
- 往夜 -- 原来世界如此性感
- php原生态与百度echarts联合制作数据图表
- Jackson框架:Java与Json互转
- http协议301、302的原理和实现
- C语言发展史
- Android assets文件夹之位置放置和作用
- 关于中南大学数据结构/C++课设题目的一点思考(一·简单题)
- Imitation: Seahorse genome
- python 为元组中的每个元素命名,提高程序可读性