最终效果图:

iPad中重要的屏幕适配技巧,
先添加一个contentView占位,
并且只在viewDidLoad方法中设置frame,
因为iPad中无论横屏还是竖屏,W都是窄的那一条边,
因此,先添加一个contentView到主控制器的右侧,
并让它随着主控制器宽高自动伸缩,
而子控制器的view只需添加到contentView中即可,x 0 y 0宽高就是contentView的bounds
代码片段:
//
// MainViewController.m
// 帅哥_团购
//
// Created by beyond on 14-8-13.
// Copyright (c) 2014年 com.beyond. All rights reserved.
// 主控制器,左侧是dock,右侧是子控制器
#import "MainViewController.h"
#import "Dock.h"
#import "DockDelegate.h"
// 自定义的导航器
#import "BeyondNavigationController.h"
// dock上面的【四个】按钮对应的控制器
#import "DealListController.h"
#import "MapController.h"
#import "CollectionController.h"
#import "MineController.h"
@interface MainViewController ()<DockDelegate>
{
// 重要的屏幕适配技巧,先添加一个contentView占位,并且只在viewDidLoad方法中设置frame,因为iPad中无论横屏还是竖屏,W都是窄的那一条边,因此,先添加一个contentView到主控制器的右侧,并让它随着主控制器宽高自动伸缩,而子控制器的view只需添加到contentView中即可,x 0 y 0 宽高就是contentView的bounds
UIView *_contentView;
}
@end
@implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
log(@"%@",NSStringFromCGRect(self.view.frame));
self.view.backgroundColor = [UIColor whiteColor];
// 1.添加Dock到主控制器
[self addDock];
// 2.重要的屏幕适配技巧,先添加一个contentView占位,并且只在viewDidLoad方法中设置frame,因为iPad中无论横屏还是竖屏,W都是窄的那一条边,因此,先添加一个contentView到主控制器的右侧,并让它随着主控制器宽高自动伸缩,而子控制器的view只需添加到contentView中即可,x 0 y 0 宽高就是contentView的bounds
[self addContentView];
// 3.添加所有的子控制器,共4个,与dock里面的最上面4个tab按钮相对应
[self addAllChildControllers];
}
// 1.添加Dock到主控制器
- (void)addDock
{
Dock *dock = [[Dock alloc] init];
// dock内部设置了高度和右间距,自动拉伸,宽度也重写了setFrame固定为100
dock.frame = CGRectMake(0, 0, 0, self.view.frame.size.height);
// dock内部的栏目被点击的时候,可以调用代理的方法(block效果也一样)
dock.delegate = self;
[self.view addSubview:dock];
}
// 1-1,实现dock的代理方法
- (void)dock:(Dock *)dock tabChangeFromIndex:(int)fromIndex toIndex:(int)toIndex
{
log(@"%d--点击了-%d",fromIndex,toIndex);
// 1.先移除旧的子控制器(导航包装了的)
UIViewController *oldVC = self.childViewControllers[fromIndex];
[oldVC.view removeFromSuperview];
// 2.添加新的子控制器(导航包装了的)
UIViewController *newVC = self.childViewControllers[toIndex];
// 3.子控制器的view直接添加到了contentView,并宽高自动伸缩,占满contentView,即可完成竖屏与横屏适配
newVC.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
// 占满contentView,即可完成竖屏与横屏适配
newVC.view.frame = _contentView.bounds;
[_contentView addSubview:newVC.view];
}
// 2.重要的屏幕适配技巧,先添加一个contentView占位,并且只在viewDidLoad方法中设置frame,因为iPad中无论横屏还是竖屏,W都是窄的那一条边,因此,先添加一个contentView到主控制器的右侧,并让它随着主控制器宽高自动伸缩,而子控制器的view只需添加到contentView中即可,x 0 y 0 宽高就是contentView的bounds
- (void)addContentView
{
// 添加contentview到主控制器的右侧
_contentView = [[UIView alloc] init];
// 宽为主控制器的宽 - dock宽
CGFloat contentViewW = self.view.frame.size.width - kDockItemW;
// 高度为控制器的高
CGFloat contentViewH = self.view.frame.size.height;
// 重要,宽和高都自动伸缩
_contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
// 仅要在view Did Load时候,设置一次contentView的frame即可
_contentView.frame = CGRectMake(kDockItemW, 0, contentViewW, contentViewH);
[self.view addSubview:_contentView];
}
// 3.添加所有的子控制器,共4个,与dock里面的最上面4个tab按钮相对应
- (void)addAllChildControllers
{
// 1.团购_子控制器
DealListController *dealVC = [[DealListController alloc] init];
dealVC.view.backgroundColor = [UIColor purpleColor];
BeyondNavigationController *nav = [[BeyondNavigationController alloc] initWithRootViewController:dealVC];
[self addChildViewController:nav];
// 2.地图_子控制器
MapController *mapVC = [[MapController alloc] init];
mapVC.view.backgroundColor = [UIColor yellowColor];
nav = [[BeyondNavigationController alloc] initWithRootViewController:mapVC];
[self addChildViewController:nav];
// 3.收藏_子控制器
CollectionController *collectionVC = [[CollectionController alloc] init];
collectionVC.view.backgroundColor = [UIColor greenColor];
nav = [[BeyondNavigationController alloc] initWithRootViewController:collectionVC];
[self addChildViewController:nav];
// 4.我的_子控制器
MineController *mineVC = [[MineController alloc] init];
mineVC.view.backgroundColor = [UIColor blueColor];
nav = [[BeyondNavigationController alloc] initWithRootViewController:mineVC];
[self addChildViewController:nav];
// 5.并手动调用dock的代理方法,默认选中团购_子控制器
[self dock:nil tabChangeFromIndex:0 toIndex:0];
}
@end
//
// BeyondNavigationController.m
// 帅哥_团购
//
// Created by beyond on 14-8-14.
// Copyright (c) 2014年 com.beyond. All rights reserved.
//
#import "BeyondNavigationController.h"
@interface BeyondNavigationController ()
@end
@implementation BeyondNavigationController
// 优化,第一次使用该类,实例化对象的时候调用,且只会调用一次
+ (void)initialize
{
// 1.appearance方法返回一个导航栏的全局的外观对象
// 修改了这个外观对象,相当于修改了整个项目中的外观
UINavigationBar *naviBar = [UINavigationBar appearance];
// 2.设置导航栏的背景图片(从中心拉伸一个像素)
[naviBar setBackgroundImage:[UIImage imageStretchedWithName:@"bg_navigation.png"] forBarMetrics:UIBarMetricsDefault];
// 3.设置导航栏文字的主题
[naviBar setTitleTextAttributes:@{
NSForegroundColorAttributeName : [UIColor blackColor],
NSShadowAttributeName : [NSValue valueWithUIOffset:UIOffsetZero]
}];
// 4.同理,修改所有UIBarButtonItem的全局外观
UIBarButtonItem *barBtnItem = [UIBarButtonItem appearance];
// 修改item的背景图片
[barBtnItem setBackgroundImage:[UIImage imageStretchedWithName:@"bg_navigation_right.png"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[barBtnItem setBackgroundImage:[UIImage imageStretchedWithName:@"bg_navigation_right_hl.png"] forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
// 修改item上面的文字样式
NSDictionary *dict = @{
NSForegroundColorAttributeName : [UIColor darkGrayColor],
NSShadowAttributeName : [NSValue valueWithUIOffset:UIOffsetZero],
NSFontAttributeName : [UIFont systemFontOfSize:16]
};
[barBtnItem setTitleTextAttributes:dict forState:UIControlStateNormal];
[barBtnItem setTitleTextAttributes:dict forState:UIControlStateHighlighted];
// 5.设置状态栏样式
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
}
@end
//
// Dock.m
// 帅哥_团购
//
// Created by beyond on 14-8-13.
// Copyright (c) 2014年 com.beyond. All rights reserved.
// 主控制器左侧是dock,右侧是与dock栏目相对应的子控制器
#import "Dock.h"
// dock最下方的更多按钮
#import "DockItemMore.h"
// dock下面倒数第2个【定位】按钮
#import "DockItemLocation.h"
// dock最上方的四个按钮(团购,地图,收藏,我的)都使用本类的实例
#import "DockItemTab.h"
#include "DockDelegate.h"
@interface Dock()
{
// dock最上方的四个按钮(团购,地图,收藏,我的)中被点亮变白色的那一个(即被选中的那一个,图片设置是disable状态为白色)
DockItemTab *_currentTab;
}
@end
@implementation Dock
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// 1,设置dock永远在主控制器的左侧,以及背景
[self setDockPositionAndBg];
// 2.添加dock顶部的团购Logo
[self addLogo];
// 3.添加dock最下面的【更多】按钮
[self addMoreBtn];
// 4.添加dock下面倒数第2个【定位】按钮
[self addLocationBtn];
// 5.添加dock最上方的四个按钮(团购,地图,收藏,我的)
[self addFourTabBtn];
}
return self;
}
// 1,设置dock永远在主控制器的左侧,以及背景
- (void)setDockPositionAndBg
{
// 1.让dock可以自动伸缩(高度 + 右边间距)
self.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleRightMargin;
// 2.设置dock背景颜色,用图片进行平铺
self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"bg_tabbar.png"]];
}
// 2.添加dock顶部的团购Logo
- (void)addLogo
{
UIImageView *logo = [[UIImageView alloc] init];
logo.image = [UIImage imageNamed:@"ic_logo.png"];
// 设置尺寸
CGFloat scale = 0.65;
CGFloat logoW = logo.image.size.width * scale;
CGFloat logoH = logo.image.size.height * scale;
// 居中,先设置宽高,再设置中心点XY
logo.bounds = CGRectMake(0, 0, logoW, logoH);
// 设置位置
logo.center = CGPointMake(kDockItemW*0.5, kDockItemH*0.5);
[self addSubview:logo];
}
// 3.添加dock最下面的【更多】按钮
- (void)addMoreBtn
{
DockItemMore *moreBtn = [[DockItemMore alloc] init];
CGFloat y = self.frame.size.height - kDockItemH;
// 因为moreBtn按钮是自动伸缩的,一直在dock的最底部,并且其父类已经在内部固定好了宽高
moreBtn.frame = CGRectMake(0, y, 0, 0);
[self addSubview:moreBtn];
}
// 4.添加dock下面倒数第2个【定位】按钮
- (void)addLocationBtn
{
DockItemLocation *locBtn = [[DockItemLocation alloc] init];
// 因为locBtn按钮是自动伸缩的,一直在dock的底部的倒数第2个,并且其父类已经在内部固定好了宽高
CGFloat y = self.frame.size.height - kDockItemH * 2;
locBtn.frame = CGRectMake(0, y, 0, 0);
// loc.enabled = NO;
[self addSubview:locBtn];
}
// 5.添加dock最上方的四个按钮(团购0,地图1,收藏2,我的3)
-(void)addFourTabBtn
{
// 1.使用抽取的方法添加一个TabBtn(团购)
[self addOneTabBtn:@"ic_deal.png" selectedIcon:@"ic_deal_hl.png" index:0];
// 2.使用抽取的方法添加一个TabBtn(地图)
[self addOneTabBtn:@"ic_map.png" selectedIcon:@"ic_map_hl.png" index:1];
// 3.使用抽取的方法添加一个TabBtn(收藏)
[self addOneTabBtn:@"ic_collect.png" selectedIcon:@"ic_collect_hl.png" index:2];
// 4.使用抽取的方法添加一个TabBtn(我的)
[self addOneTabBtn:@"ic_mine.png" selectedIcon:@"ic_mine_hl.png" index:3];
// 5.添加标签底部的分隔线
UIImageView *dividerImgView = [[UIImageView alloc] init];
dividerImgView.frame = CGRectMake(0, kDockItemH * 5, kDockItemW, 2);
dividerImgView.image = [UIImage imageNamed:@"separator_tabbar_item.png"];
[self addSubview:dividerImgView];
}
// 5-1,使用抽取的方法添加一个TabBtn(团购0,地图1,收藏2,我的3),参数index决定y值
- (void)addOneTabBtn:(NSString *)iconName selectedIcon:(NSString *)selectedIconName index:(int)index
{
// (团购,地图,收藏,我的)TabBtn使用同一个父类,它们只是Y值不同
DockItemTab *tab = [[DockItemTab alloc] init];
// 设置按钮背景和选中的图片
[tab setIcon:iconName selectedIcon:selectedIconName];
tab.frame = CGRectMake(0, kDockItemH * (index+1), 0, 0);
// 因为是选项卡,只要用户手指tap一下就触发
[tab addTarget:self action:@selector(tabBtnClick:) forControlEvents:UIControlEventTouchDown];
// tag 0 1 2 3 (团购0,地图1,收藏2,我的3)
tab.tag = index;
[self addSubview:tab];
// 默认选中index == 0的这个 (团购0,地图1,收藏2,我的3)
if (index == 0) {
[self tabBtnClick:tab];
}
}
// 5-2,因为是dock添加了tab,所以dock担当起监听tab的点击的任务,同时,又是主控制器添加了dock,所以主控制器就必须成为dock的代理,dock通知其代理,告诉代理,它内部的tab被人点击了
- (void)tabBtnClick:(DockItemTab *)tab
{
// 0.因为要传两个tag,必须先通知dock的代理(因为dock是添加到了主控制器,所以dock的代理就是主控制器)
if ([_delegate respondsToSelector:@selector(dock:tabChangeFromIndex:toIndex:)]) {
// 调用代理的方法,相当于通知代理,self dock里面的按钮从哪一个切换到了哪一个
[_delegate dock:self tabChangeFromIndex:_currentTab.tag toIndex:tab.tag];
}
// 1.控制状态
// 先把上一个置灰,因为图片设置是enable状态是黑色
_currentTab.enabled = YES;
// 再把被点的这一个置白,图片设置是disable状态下为高亮白色
tab.enabled = NO;
// 最后把这一个被点击的按钮置为当前
_currentTab = tab;
}
#pragma mark 1,重写setFrame方法:内定自己的宽度,防止外部更改宽高
- (void)setFrame:(CGRect)frame
{
frame.size.width = kDockItemW;
[super setFrame:frame];
}
@end
iOS_21团购_iPad中子控制器的屏幕适配,布布扣,bubuko.com
原文:http://blog.csdn.net/pre_eminent/article/details/38556325