相信大家在iOS界面开发中经常会用到UITabBar and UINavigationController
今天就给大家写个简单的方法实现这个功能
这里我会用到一个类和一个plist文件
首先我们可以先创建5个界面出来
这是我创建的5个界面
然后我们再创建一个plist文件
具体方法
这样就可以创建一个plist文件,然后我们在里面写入以下内容
接下来我们再创建一个叫做ConfigCenter的类
然后再ConfigCenter.h中定义一些属性和方法
@interface JConfigCenter :NSObject
@property (nonatomic,retain)NSMutableDictionary *config;
@property (nonatomic,copy)NSString *path;
+(id)getConfigWithKey:(NSString *)key;
+(id)getRootViewControllers;
@end
接下来我们再在ConfigCenter.m中实现
#import "JConfigCenter.h"
@implementation JConfigCenter
+(id)getRootViewControllers
{
return [selfgetConfigWithKey:kROOT_VIEW_CONTROLLERS];
}
+(id)getConfigWithKey:(NSString *)key
{
return [[selfgetConfig] objectForKey:key];
}
+(id)getConfig
{
static NSDictionary *config;
if (!config) {
NSString * path = [[NSBundlemainBundle] pathForResource:@"config"ofType:@"plist"];
config = [NSDictionarydictionaryWithContentsOfFile:path];
}
return config;
}
@end
#import "JAppDelegate.h"
#import "JConfigCenter.h"
@implementation JAppDelegate
- (void)dealloc
{
[_windowrelease];
[superdealloc];
}
-(void)buildLayout
{
UITabBarController *tbc = [[UITabBarControlleralloc] init];
NSArray *controllers = [JConfigCentergetRootViewControllers];
for (NSString *controllerin controllers) {
UIViewController *vc = [[NSClassFromString(controller)alloc] init];
UINavigationController *nav = [[UINavigationControlleralloc] initWithRootViewController:vc];
[tbc addChildViewController:nav];
}
self.window.rootViewController = tbc;
}
#pragma mark -
#pragma mark JAppDelegate lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindowalloc] initWithFrame:[[UIScreenmainScreen] bounds]]autorelease];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColorwhiteColor];
[selfbuildLayout];
[self.windowmakeKeyAndVisible];
return YES;
}
@end
效果就如图:
希望这个方法可以帮到大家!
接下来还会继续实现各个界面的真正功能,希望大家能够支持!
前篇:《MyGui笔记(2)控件类型和皮肤》
本篇:创建控件的方法要传入控件对齐方式,创建根控件还需传入将被创建到哪一层的名称。
环境:MyGui3.2.0(OpenGL平台)
控件的对齐方式,定义在Align里面,所定义的方式如下:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
HCenter = MYGUI_FLAG_NONE, /**< 水平居中 */
VCenter = MYGUI_FLAG_NONE, /**< 垂直居中 */
Center = HCenter | VCenter, /**< 中心居中 */
Left = MYGUI_FLAG(1), /**< 居左 (并且垂直居中) */
Right = MYGUI_FLAG(2), /**< 居右 (并且垂直居中) */
HStretch = Left | Right, /**< 按与父窗口的比例进行水平拉伸 (并且垂直居中) */
Top = MYGUI_FLAG(3), /**< 居上 (并且水平居中) */
Bottom = MYGUI_FLAG(4), /**< 居下 (并且水平居中) */
VStretch = Top | Bottom, /**< 按与父窗口的比例进行垂直拉伸 (并且水平居中) */
Stretch = HStretch | VStretch, /**< 按与父窗口的比例进行拉伸 */
Default = Left | Top /**< 默认值 (居左和居上) */
};
并不仅这些方式,还可以自己进行组合,如:
2
HStretch | Bottom /**< 按与父窗口的比例进行水平拉伸和居下 */
每当父窗口进行位置或者大小改变,都会对其子控件进行重新计算位置和大小,代码如下:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//_newSize 父控件新的大小
void Widget::_setAlign(const IntSize& _oldsize, const IntSize& _newSize)
{
const IntSize& size = _newSize;//getParentSize();
bool need_move = false;
bool need_size = false;
IntCoord coord = mCoord;
// 对齐方式
if (mAlign.isHStretch())
{
// 拉伸
coord.width = mCoord.width + (size.width - _oldsize.width);
need_size = true;
}
else if (mAlign.isRight())
{
// 向右移动
coord.left = mCoord.left + (size.width - _oldsize.width);
need_move = true;
}
else if (mAlign.isHCenter())
{
// 没有拉伸的水平对齐
coord.left = (size.width - mCoord.width) / 2;
need_move = true;
}
if (mAlign.isVStretch())
{
// 拉伸
coord.height = mCoord.height + (size.height - _oldsize.height);
need_size = true;
}
else if (mAlign.isBottom())
{
// 向下移动
coord.top = mCoord.top + (size.height - _oldsize.height);
need_move = true;
}
else if (mAlign.isVCenter())
{
// 没有拉伸的垂直居中
coord.top = (size.height - mCoord.height) / 2;
need_move = true;
}
if (need_move)
{
if (need_size)
setCoord(coord);
else
setPosition(coord.point());
}
else if (need_size)
{
setSize(coord.size());
}
else
{
_updateView(); // 无需移动和改变大小
}
}
每个根控件创建的时候,需要指定其所在层,所有的层定义在MyGUI_Layers.xml文件,这个文件内容为:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<MyGUI type="Layer" version="1.2">
<Layer type="SharedLayer" name="Wallpaper">
<Property key="Pick" value="false"/>
</Layer>
<Layer type="SharedLayer" name="Back">
<Property key="Pick" value="true"/>
</Layer>
<Layer type="OverlappedLayer" name="Overlapped">
<Property key="Pick" value="true"/>
</Layer>
<Layer type="SharedLayer" name="Middle">
<Property key="Pick" value="true"/>
</Layer>
<Layer type="OverlappedLayer" name="Modal">
<Property key="Pick" value="true"/>
</Layer>
<Layer type="SharedLayer" name="Main">
<Property key="Pick" value="true"/>
</Layer>
<Layer type="OverlappedLayer" name="Popup">
<Property key="Pick" value="true"/>
</Layer>
<Layer type="SharedLayer" name="FadeMiddle">
<Property key="Pick" value="false"/>
</Layer>
<Layer type="OverlappedLayer" name="Info">
<Property key="Pick" value="true"/>
</Layer>
<Layer type="SharedLayer" name="ToolTip">
<Property key="Pick" value="false"/>
</Layer>
<Layer type="SharedLayer" name="DragAndDrop">
<Property key="Pick" value="false"/>
</Layer>
<Layer type="SharedLayer" name="FadeBusy">
<Property key="Pick" value="false"/>
</Layer>
<Layer type="SharedLayer" name="Pointer">
<Property key="Pick" value="false"/>
</Layer>
<Layer type="SharedLayer" name="Fade">
<Property key="Pick" value="false"/>
</Layer>
<Layer type="SharedLayer" name="Statistic">
<Property key="Pick" value="false"/>
</Layer>
</MyGUI>
可以看到层类型分为两种:SharedLayer和OverlappedLayer。
-
SharedLayer :SharedLayer为简单无重叠的层,重叠的控件可能会出现绘制顺序不正确,整个SharedLayer在一个批次中进行渲染。
-
OverlappedLayer :当在一个层(例如:窗口)中含有重叠的控件,那么应该使用OverlappedLayer 。每个根控件进行批次渲染,所以如果层上的控件没有打算进行彼此重叠的话,那么使用SharedLayer。
层的名称标识符,用在皮肤、布局和代码里。Pick属性设置控件是否能够响应鼠标消息,如果设置为false,鼠标指针会忽略这个层上的所有控件,直接穿透到下一层。创建根控件调用代码如下:
2
3
4
5
6
7
8
9
10
11
12
{
Widget* widget = WidgetManager::getInstance().createWidget(_style, _type, _skin, _coord, /*_align, */nullptr, nullptr, _name);
mWidgetChild.push_back(widget);
widget->setAlign(_align);
// 附加控件到层上
if (!_layer.empty())
LayerManager::getInstance().attachToLayerNode(_layer, widget);
return widget;
}
层管理器LayerManager负责将控件添加到相应的层上,attachToLayerNode代码为:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
MYGUI_ASSERT(nullptr != _item, "pointer must be valid");
MYGUI_ASSERT(_item->isRootWidget(), "attached widget must be root");
// 从原先的层分离
_item->detachFromLayer();
// 附加到新的层上
for (VectorLayer::iterator iter = mLayerNodes.begin(); iter != mLayerNodes.end(); ++iter)
{
if (_name == (*iter)->getName())
{
ILayerNode* node = (*iter)->createChildItemNode();
node->attachLayerItem(_item);
return;
}
}
MYGUI_LOG(Error, "Layer '" << _name << "' is not found");
//MYGUI_EXCEPT("Layer '" << _name << "' is not found");
}
可以看到限制了控件必须为根控件,如果控件原先有附加到其他层上,则必须先分离。接着遍历mLayerNodes,它存储着MyGUI_Layers.xml里面所有的层信息,找到对应的层名称,根据相应的层类型来创建一个子节点,将控件添加到这个子节点上。代码如下:
2
3
4
5
6
7
{
mLayerItems.push_back(_item);
_item->attachItemToNode(mLayer, this);
mOutOfDate = true;
}
可以看到这个控件加入到mLayerItems列表里面,mLayerItems存放着所有的控件指针,对于重叠层来说,这里面只存放一个。接着控件调用attachItemToNode方法,这个方法代码如下:
2
3
4
5
6
7
{
mLayer = _layer;
mLayerNode = _node;
attachToLayerItemNode(_node, true);
}
继续调用方法attachToLayerItemNode,代码如下:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
MYGUI_DEBUG_ASSERT(nullptr != _item, "attached item must be valid");
mLayerNode = _item;
for (VectorSubWidget::iterator skin = mDrawItems.begin(); skin != mDrawItems.end(); ++skin)
{
(*skin)->createDrawItem(mTexture, _item);
}
for (VectorLayerItem::iterator item = mLayerItems.begin(); item != mLayerItems.end(); ++item)
{
(*item)->attachToLayerItemNode(_item, _deep);
}
for (VectorLayerItem::iterator item = mLayerNodes.begin(); item != mLayerNodes.end(); ++item)
{
if (_deep)
{
ILayerNode* child_node = _item->createChildItemNode();
(*item)->attachToLayerItemNode(child_node, _deep);
}
}
}
更多资料:
1.MyGUI layers http://www.ogre3d.org/tikiwiki/tiki-index.php?page=MyGUI+layers
想知道,iOS里面默认初始设置的bool类型的变量是yes还是no??就把它打印出来看看。。
Oc风格BOOL 具有 YES 和 NO。实用8位存储空间。从最低位算起。 YES定义为1,NO定义为0。iOS里面默认初始设置的bool类型的变量是yes
c语言风格 bool 具有true和false 而非0的全都是true,0是false。
BOOL isDirectory;
NSLog(@"%hhd",isDirectory);
打印:
2013-10-18 10:18:38.128 Ch07_FileManagement[545:a0b] 1
-----------------------
BOOL isDirectory;
NSLog(@"isDirectory value: %@" ,isDirectory?@"YES":@"NO");
打印:
2013-10-18 10:21:42.734 Ch07_FileManagement[559:a0b] isDirectory value: YES
------------------------
BOOL isDirectory;
NSLog(@"%hhd",isDirectory);
NSLog(@"isDirectory value: %@" ,isDirectory?@"YES":@"NO");
打印:
2013-10-18 10:21:42.080 Ch07_FileManagement[559:a0b] -65 这里打印出来的-65是什么意思呢???嗯。。。。。
2013-10-18 10:21:42.734 Ch07_FileManagement[559:a0b] isDirectory value: YES