您好!!
在这个信息化的时代里,我们也知道一些新闻客户端,比如说搜狐、今日头条。还有一些种种个性特色的新闻APP。
今日,小虾米做了一点小小的总结, 分享我最近搭建的一个基本网易框架。如果其中有什么不妥的地方,请大神提出您的意见。在这里我衷心谢谢。。。。。
大致思路:
1、设置一个根控制器。
2、设置一个继承UIView并创建六个按钮的左菜单
3、创建六个子控制器并赋有导航控制器
4、设置一个继承UIViewController的右菜单(里面业务比较多)
大致意图如下:
实现根控制器的代码如下:
//
// Created by cjj on 15-9-9.
// Copyright (c) 2015年 jh.chen. All rights reserved.
//
#import "JHMainViewController.h"
#import "JHLeftMenu.h"
#import "JHNewsViewController.h"
#import "JHNavigationController.h"
#import "JHTitleView.h"
#import "JHRightMenuController.h"
#define JHNavShowAnimDuration 0.25
@interface JHMainViewController () <JHLeftMenuDelegate>
/**
* 正在显示的导航控制器
*/
@property (nonatomic, weak) JHNavigationController *showingNavigationController;
@property (nonatomic, weak) JHLeftMenu *leftMenu;
@property (nonatomic, strong) JHRightMenuController *rightMenuVc;
@end
@implementation JHMainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// 1.创建子控制器
[self setupallChildVcs];
// 2.添加左菜单
[self setupLeftMenu];
// 3.添加右菜单
[self setupRightMenu];
}
-(void)setupallChildVcs
{
// 1.1.新闻控制器
JHNewsViewController *news = [[JHNewsViewController alloc] init];
[self setupVc:news title:@"新闻"];
// 1.2.订阅控制器
UIViewController *reading = [[UIViewController alloc] init];
[self setupVc:reading title:@"订阅"];
// 1.3.图片控制器
UIViewController *photo = [[UIViewController alloc] init];
[self setupVc:photo title:@"图片"];
// 1.4.视频控制器
UIViewController *video = [[UIViewController alloc] init];
[self setupVc:video title:@"视频"];
// 1.5.跟帖控制器
UIViewController *comment = [[UIViewController alloc] init];
[self setupVc:comment title:@"跟帖"];
// 1.6.电台控制器
UIViewController *radio = [[UIViewController alloc] init];
[self setupVc:radio title:@"电台"];
}
-(void)setupLeftMenu
{
JHLeftMenu *leftMenu = [[JHLeftMenu alloc] init];
leftMenu.delegate = self;
leftMenu.height = 300;
leftMenu.width = 200;
leftMenu.y = 60;
[self.view insertSubview:leftMenu atIndex:1];
self.leftMenu = leftMenu;
}
-(void)setupRightMenu
{
JHRightMenuController *rightMenuVc = [[JHRightMenuController alloc] init];
rightMenuVc.view.x = self.view.width - rightMenuVc.view.width;
rightMenuVc.view.y = 20;
[self.view insertSubview:rightMenuVc.view atIndex:1];
self.rightMenuVc = rightMenuVc;
}
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
/**
* 初始化一个控制器
*
* @param vc 需要初始化的控制器
* @param title 控制器的标题
*/
- (void)setupVc:(UIViewController *)vc title:(NSString *)title
{
// 1.设置背景色
vc.view.backgroundColor =[UIColor greenColor];
// 2.设置标题
JHTitleView *titleView = [[JHTitleView alloc] init];
titleView.title = title;
vc.navigationItem.titleView = titleView;
// 3.设置左右按钮
vc.navigationItem.leftBarButtonItem = [UIBarButtonItem itemWithImageName:@"top_navigation_menuicon" target:self action:@selector(leftMenuClick)];
vc.navigationItem.rightBarButtonItem = [UIBarButtonItem itemWithImageName:@"top_navigation_infoicon" target:self action:@selector(rightMenuClick)];
// 4.包装一个导航控制器
JHNavigationController *nav = [[JHNavigationController alloc] initWithRootViewController:vc];
// 让newsNav成为self(JHMainViewController)的子控制器,能保证:self在,newsNav就在
// 如果两个控制器互为父子关系,那么它们的view也应该互为父子关系
[self addChildViewController:nav];
}
#pragma mark - 监听导航栏按钮点击
- (void)leftMenuClick
{
NSLog(@"leftClick--");
self.leftMenu.hidden = NO;
self.rightMenuVc.view.hidden = YES;
[UIView animateWithDuration:JHNavShowAnimDuration animations:^{
// 取出正在显示的导航控制器的view
UIView *showingView = self.showingNavigationController.view;
// 缩放比例
CGFloat navH = [UIScreen mainScreen].bounds.size.height - 2 * 60;
CGFloat scale = navH / [UIScreen mainScreen].bounds.size.height;
// 菜单左边的间距
CGFloat leftMenuMargin = [UIScreen mainScreen].bounds.size.width * (1 - scale) * 0.5;
CGFloat translateX = 200 - leftMenuMargin;
CGFloat topMargin = [UIScreen mainScreen].bounds.size.height * (1 - scale) * 0.5;
CGFloat translateY = topMargin - 60;
// 缩放
CGAffineTransform scaleForm = CGAffineTransformMakeScale(scale, scale);
// 平移
CGAffineTransform translateForm = CGAffineTransformTranslate(scaleForm, translateX / scale, -translateY / scale);
showingView.transform = translateForm;
// 添加一个遮盖
UIButton *cover = [[UIButton alloc] init];
[cover addTarget:self action:@selector(coverClick:) forControlEvents:UIControlEventTouchUpInside];
cover.frame = showingView.bounds;
[showingView addSubview:cover];
}];
}
- (void)coverClick:(UIButton *)cover
{
[UIView animateWithDuration:JHNavShowAnimDuration animations:^{
self.showingNavigationController.view.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
[cover removeFromSuperview];
}];
}
- (void)rightMenuClick
{
NSLog(@"rightMenuClick");
self.leftMenu.hidden = YES;
self.rightMenuVc.view.hidden = NO;
[UIView animateWithDuration:JHNavShowAnimDuration animations:^{
// 取出正在显示的导航控制器的view
UIView *showingView = self.showingNavigationController.view;
// 缩放比例
CGFloat navH = [UIScreen mainScreen].bounds.size.height - 2 * 60;
CGFloat scale = navH / [UIScreen mainScreen].bounds.size.height;
// 菜单左边的间距
CGFloat leftMenuMargin = [UIScreen mainScreen].bounds.size.width * (1 - scale) * 0.5;
CGFloat translateX = self.rightMenuVc.view.width - leftMenuMargin;
CGFloat topMargin = [UIScreen mainScreen].bounds.size.height * (1 - scale) * 0.5;
CGFloat translateY = topMargin - 60;
// 缩放
CGAffineTransform scaleForm = CGAffineTransformMakeScale(scale, scale);
// 平移
CGAffineTransform translateForm = CGAffineTransformTranslate(scaleForm, -translateX / scale, -translateY / scale);
showingView.transform = translateForm;
// 添加一个遮盖
UIButton *cover = [[UIButton alloc] init];
[cover addTarget:self action:@selector(coverClick:) forControlEvents:UIControlEventTouchUpInside];
cover.frame = showingView.bounds;
[showingView addSubview:cover];
}completion:^(BOOL finished) {
[self.rightMenuVc didShow];
}];
}
#pragma mark - JHLeftMenuDelegate
- (void)leftMenu:(JHLeftMenu *)menu didSelectedButtonFromIndex:(int)fromIndex toIndex:(int)toIndex
{
NSLog(@"JHLeftMenuDelegate--");
// 0.移除旧控制器的view
JHNavigationController *oldNav = self.childViewControllers[fromIndex];
[oldNav.view removeFromSuperview];
// 1.显示新控制器的view
JHNavigationController *newNav = self.childViewControllers[toIndex];
[self.view addSubview:newNav.view];
// 设置新控制的transform跟旧控制器一样
newNav.view.transform = oldNav.view.transform;
// 设置阴影
newNav.view.layer.shadowColor = [UIColor blackColor].CGColor;
newNav.view.layer.shadowOffset = CGSizeMake(-3, 0);
newNav.view.layer.shadowOpacity = 0.2;
// 2.设置当前正在显示的控制器
self.showingNavigationController = newNav;
// 3.清空transform
[UIView animateWithDuration:JHNavShowAnimDuration animations:^{
newNav.view.transform = CGAffineTransformIdentity;
}];
}
@end
效果图如下
:
设置好了主控制器 如果我们要切换不同的控制器,所以我觉得在左侧菜单设置代理是必需的,通过按钮监听,通知代理,从而实现控制器的切换。
实现左菜单的代码如下:
//
// Created by cjj on 15-9-9.
// Copyright (c) 2015年 jh.chen. All rights reserved.
//
#import "JHLeftMenu.h"
@interface JHLeftMenu()
@property (nonatomic, weak) UIButton *selectedButton;
@end
@implementation JHLeftMenu
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor clearColor];
CGFloat alpha = 0.1;
[self setupBtnWithIcon:@"sidebar_nav_news" title:@"新闻" bgColor:HMColorRGBA(202, 68, 73, alpha)];
[self setupBtnWithIcon:@"sidebar_nav_reading" title:@"订阅" bgColor:HMColorRGBA(190, 111, 69, alpha)];
[self setupBtnWithIcon:@"sidebar_nav_photo" title:@"图片" bgColor:HMColorRGBA(76, 132, 190, alpha)];
[self setupBtnWithIcon:@"sidebar_nav_video" title:@"视频" bgColor:HMColorRGBA(101, 170, 78, alpha)];
[self setupBtnWithIcon:@"sidebar_nav_comment" title:@"跟贴" bgColor:HMColorRGBA(170, 172, 73, alpha)];
[self setupBtnWithIcon:@"sidebar_nav_radio" title:@"电台" bgColor:HMColorRGBA(190, 62, 119, alpha)];
}
return self;
}
-(void)setDelegate:(id<JHLeftMenuDelegate>)delegate
{
_delegate = delegate;
[self buttonClick:[self.subviews firstObject]];
}
-(UIButton *)setupBtnWithIcon:(NSString *)icon title:(NSString *)title bgColor:(UIColor *)bgColor
{
UIButton *btn = [[UIButton alloc] init];
btn.tag = self.subviews.count;
[btn addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:btn];
//设置图片和文字
[btn setImage:[UIImage imageNamed:icon] forState:UIControlStateNormal];
[btn setTitle:title forState:UIControlStateNormal];
[btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
btn.titleLabel.font = [UIFont systemFontOfSize:17];
// 设置按钮选中的背景色
[btn setBackgroundImage:[UIImage imageWithColor:bgColor] forState:UIControlStateSelected];
btn.adjustsImageWhenHighlighted = NO;
//设置按钮的内容左对齐
btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
// 设置间距
btn.contentEdgeInsets = UIEdgeInsetsMake(0, 20, 0, 0);
btn.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
//设置按钮的内容左对齐
btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
return btn;
}
-(void)layoutSubviews
{
[super layoutSubviews];
//设置按钮的frame
int btnCount=self.subviews.count;
CGFloat btnW = self.width;
CGFloat btnH = self.height / btnCount;
for (int i =0; i< btnCount; i++) {
UIButton *btn = self.subviews[i];
btn.width = btnW;
btn.height = btnH;
btn.y = i * btnH;
}
}
-(void)buttonClick:(UIButton *)button
{
// 0.通知代理
if ([self.delegate respondsToSelector:@selector(leftMenu:didSelectedButtonFromIndex:toIndex:)]) {
[self.delegate leftMenu:self didSelectedButtonFromIndex:self.selectedButton.tag toIndex:button.tag];
}
// 1.控制按钮的状态 点击一个按钮时 另一个消息
self.selectedButton.selected = NO;
button.selected = YES;
self.selectedButton = button;
}
@end
以上是左菜单的一些实现方法。
那让我们看看右侧菜单,我们能看到如下图标要实现一个3D的旋转(绕y轴旋转)。我们可以使用layer的transform属性,不过要嵌套两层动画来实现翻转,觉得没这必要
因为我们也可以运用转场动画CATransition,更简单。不过因所求而易吧。我会写下三种代码的不同实现。请看下。。。。
对于右侧菜单,虾米是根据代码 + xib实现的。我们需要把一些控件整成一个整体,如果有机会在别的项目里用得上,我们就可以拿出这部分来使用,也是有利于以后代码的维护性。在虾米看来代码 + xib 是不错的选择!! ^-^
右侧菜单实现代码如下:
//
// JHRightMenuController.m
// 原创网易ofJH
//
// Created by cjj on 15-9-12.
// Copyright (c) 2015年 jh.chen. All rights reserved.
//
#import "JHRightMenuController.h"
#import "JHRightMenuCenterViewRow.h"
@interface JHRightMenuController ()
@property (weak, nonatomic) IBOutlet UIImageView *iconView;
@property (weak, nonatomic) IBOutlet UIView *centerView;
@end
@implementation JHRightMenuController
- (void)viewDidLoad
{
[super viewDidLoad];
// 填充中间的内容
[self setupCenterView];
}
-(void)setupCenterView
{
JHRightMenuCenterViewRow *row = [self setupCenterViewRow:@"商城 能赚能花,土豪当家" icon:@"promoboard_icon_mall"];
[self setupCenterViewRow:@"活动 4.0发布会粉丝招募" icon:@"promoboard_icon_activities"];
[self setupCenterViewRow:@"应用 金币从来都是这送的" icon:@"promoboard_icon_apps"];
self.centerView.height = self.centerView.subviews.count * row.height;
}
-(JHRightMenuCenterViewRow *)setupCenterViewRow:(NSString *)title icon:(NSString *)icon
{
JHRightMenuCenterViewRow *row = [JHRightMenuCenterViewRow centerViewRow];
row.title = title;
row.icon = icon;
row.y = row.height * self.centerView.subviews.count;
[self.centerView addSubview:row];
return row;
}
-(void)didShow
{
// 让头像旋转
// [UIView animateWithDuration:1.0 animations:^{
// self.iconView.layer.transform = CATransform3DMakeRotation(M_PI_2, 0, 1, 0);
// }completion:^(BOOL finished) {
// self.iconView.image = [UIImage imageNamed:@"user_defaultgift"];
// [UIView animateWithDuration:1.0 animations:^{
// self.iconView.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0);
// }];
// }];
// CATransition *anim = [CATransition animation];
// anim.duration = 1.0;
// // cube = 方砖 rippleEffect = 水滴
// anim.type = @"rippleEffect";
// [self.iconView.layer addAnimation:anim forKey:nil];
[UIView transitionWithView:self.iconView duration:2.0 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{
self.iconView.image = [UIImage imageNamed:@"user_defaultgift"];
} completion:^(BOOL finished) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[UIView transitionWithView:self.iconView duration:2.0 options:UIViewAnimationOptionTransitionFlipFromRight animations:^{
self.iconView.image = [UIImage imageNamed:@"default_avatar"];
} completion:nil];
});
}];
}
@end
完整效果图如下:
如果有什么好的建议,请联系虾米,虾米感激不尽 蟹蟹 哈!!
虾米联系方式:
QQ:584837022
github:https://github.com/ios-cjh