IOS 严格秉承MVC模式, 即每个View的出现将有相应的Controller负责其逻辑事物, 因此IOS的UI设计中需要首先考虑MVC的问题. 在本博客中,在兼顾MVC的同时,考虑了两点设计中常用的问题。 

1. IOS中对可重用UI的处理(能重用的UI通过Controller特别封装, 提供给其它View进行重用) 

   UI涉及的一个非常重要的问题,跟程序设计也是一样, 如何管理冗余(即重复信息)的信息, 冗余度的处理实际上不单单是程序设计的死敌,同样是管理的死敌(冗余代码是Bug的温床,同样如此,雷同UI是用户体验的死敌)。

    对付重复性,我们这里一个小需求是, 如何实现一个类似于ListView的功能, 让所有的UI的小Item都能不断的加入到父面板中? UI如下:

   

ios ui入门 ios ui设计_UI

图:不断增加一个重复的UI

当然,也许有人说用UITableView可以做到, 但是更个性化的Item, 会很需要一个类似的结构来达成我们的目的。并且,你一定会面临这样的问题,相同的数据结构,需要用同一个UI展示。当你辛苦的设计好一个UI以及逻辑之后,发现在另外相似的情况下复用,已经痛不欲生,因此, 这里我们采用的一种方式是: 封装好一个小的UI. 然后随处可用。

a. 隔离

ios ui入门 ios ui设计_#import_02

图: 父面板实际上可以是任意的

ios ui入门 ios ui设计_UI_03

图:在任意需要的地方,调用这个小东西

b. 代码中加载


//
//  KEYI_ViewController.m
//  LoadPartView
//
//  Created by 尘 凡 on 12-12-28.
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//

#import "KEYI_ViewController.h"

@interface KEYI_ViewController ()

@end

@implementation KEYI_ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    //仅仅只是为了获取view的大小, 这个controller设置为autoRelease
    LiteController *tempControl = [[[LiteController alloc] initWithNibName:@"LiteController" bundle:nil] autorelease];
    UIView *liteView = tempControl.view;
    CGPoint point = liteView.center;
    
    CGSize  size = liteView.bounds.size;
    //不知道为什么, 需要代码初始化这个ScrollView, IB拖拉的方式构造界面,会无效
    UIScrollView *parentView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
    [self.view addSubview:parentView];
    
    int len = 75;
    for (int i = 0; i < len; i++) {
        CGFloat centX = point.x;
        CGFloat centY = point.y + i * size.height;
        NSString *string = [NSString stringWithFormat:@"%d",i]; 
        [self addItems:centX :centY:parentView:string];
    }
    parentView.contentSize = CGSizeMake(320, len* size.height);
    parentView.scrollEnabled = YES;
}

- (void) addItems:(CGFloat)centX:(CGFloat)centY:(UIScrollView *)parentView:(NSString*)title
{
    LiteController *contr = [[LiteController alloc] initWithNibName:@"LiteController" bundle:nil];
    UIView *aItem = contr.view;
    [contr.textLabel setText:title];
    aItem.center = CGPointMake(centX, centY);
    aItem.backgroundColor = [UIColor grayColor];
    [parentView addSubview:aItem];
    
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

- (void)dealloc {
    [super dealloc];
}
@end


2. IOS中对个性化页面的处理: 个性化中,公用UI进行提炼, 个性化的UI自己负责自己的Controller以及XIB文件

    下图是一个典型的个性化页面处理情况,点击4个Tab按钮将出现不同的UI.

     

ios ui入门 ios ui设计_bundle_04

   

ios ui入门 ios ui设计_ios ui入门_05

   

面对这样的个性化特征很强的界面, 按照程序设计的低耦合原则, 应该将可变化的部分, 安插在影响最小的位置,比如【注册】的UI/逻辑不能影响【登陆】的UI以及逻辑, 这里,我是按照这样的方式:

a. 公共部分, 如上层按钮, 放在一个controller中. 见下图:

ios ui入门 ios ui设计_ios ui入门_06

图: 一个全局的Controller, 相当PC中CPU的作用: 组装

 

b. 各个按钮对应的不同界面,各自建立Controller. 见下图:

ios ui入门 ios ui设计_ios ui入门_07

图: 【登陆】已经被封装到自己的Controller, 最小耦合度原则


ios ui入门 ios ui设计_UI_08

图: 【注册】已经被封装到自己的Controller, 最小耦合度原则

c. 关键的代码, 加载各自不同的Controller

头文件

//
//  ControllerUsrMgr.h
//  keyiApp
//
//  Created by 尘 凡 on 12-12-14.
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "ControllerMod.h"
#import "ControllerLogin.h"
#import "ControllerRegister.h"
#import "ControllerForget.h"
#import "ToolUI.h"

@interface ControllerUsrMgr : UIViewController
{
    
    IBOutlet UILabel *selTitle;
    IBOutlet UIButton *changeBtn;
    IBOutlet UIButton *forgotBtn;
    IBOutlet UIButton *regBtn;
    IBOutlet UIButton *loginBtn;
    IBOutlet UIView *parentView;
    IBOutlet UILabel *titleInfo;
    NSArray *btnArr;
    NSArray *selImgArr;
    NSArray *unSelImgArr;
    NSArray *upperTitle;
    NSArray *lowerTitle;
    ControllerLogin *loginCtr;
    ControllerRegister *registerCtrl;

    
}
- (IBAction)actionLogin:(UIButton *)sender;
- (IBAction)actionRegister:(UIButton *)sender;
- (IBAction)actionForgot:(UIButton *)sender;
- (IBAction)actionChange:(UIButton *)sender;

@end


源文件

//
//  ControllerUsrMgr.m
//  keyiApp
//
//  Created by 尘 凡 on 12-12-14.
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//

#import "ControllerUsrMgr.h"

@interface ControllerUsrMgr ()

@end

@implementation ControllerUsrMgr

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
        unSelImgArr = [[NSArray alloc] initWithObjects:@"usr_mgr_login_nosel.png",@"usr_mgr_reg_nosel.png",@"usr_mgr_mod_nosel.png",@"usr_mgr_login_nosel.png", nil];
        selImgArr = [[NSArray alloc] initWithObjects:@"usr_mgr_login_sel.png",@"usr_mgr_reg_sel.png",@"usr_mgr_mod_sel.png",@"usr_mgr_login_sel.png", nil];
        lowerTitle = [[NSArray alloc] initWithObjects:@"请填写登陆信息",@"请填写注册信息",@"请填写申诉信息",@"请填写修改信息", nil];
        upperTitle = [[NSArray alloc] initWithObjects:@"用户登陆",@"用户注册",@"忘记密码",@"修改密码", nil];
        loginCtr = [[ControllerLogin alloc]initWithNibName:@"ControllerLogin" bundle:nil];
        registerCtrl = [[ControllerRegister alloc]initWithNibName:@"ControllerRegister" bundle:nil];
        
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    btnArr = [[NSArray alloc] initWithObjects:loginBtn,regBtn,changeBtn,forgotBtn, nil] ;
    
    [self actionLogin:loginBtn];
}

- (void)viewDidUnload
{
    [loginBtn release];
    loginBtn = nil;
    [regBtn release];
    regBtn = nil;
    [forgotBtn release];
    forgotBtn = nil;
    [changeBtn release];
    changeBtn = nil;
    [parentView release];
    parentView = nil;
    [titleInfo release];
    titleInfo = nil;
    [selTitle release];
    selTitle = nil;
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

- (void)dealloc {
    [loginBtn release];
    [regBtn release];
    [forgotBtn release];
    [changeBtn release];
    [parentView release];
    [titleInfo release];
    [selTitle release];
    [super dealloc];
}

- (IBAction)actionLogin:(UIButton *)sender {
    [ToolUI removeSubView:parentView];
    [parentView addSubview:loginCtr.view];
    [self highLightButton:sender];    
}



- (IBAction)actionRegister:(UIButton *)sender {
    [ToolUI removeSubView:parentView];
    [parentView addSubview:registerCtrl.view];
    [self highLightButton:sender];

}

- (IBAction)actionForgot:(UIButton *)sender {
         [ToolUI removeSubView:parentView];
         [self highLightButton:sender];
}

- (void) pressOne:(UIButton *)curBtn {
    if (curBtn == loginBtn)
    {
        [curBtn performSelector:@selector(highLightButton:) withObject:curBtn afterDelay:0.1];
    }
}

- (void) highLightButton:(UIButton *)b{
    
    for (int i = 0; i < btnArr.count; i++) {
        UIButton *item = [btnArr objectAtIndex:i];
        NSString *unSel = [unSelImgArr objectAtIndex:i];
        NSString *sel = [selImgArr objectAtIndex:i];
        if (b == item) {
            [item setBackgroundImage:[UIImage imageNamed:sel] forState:UIControlStateNormal];
            [selTitle setText:[upperTitle objectAtIndex:i]];
            [titleInfo setText:[lowerTitle objectAtIndex:i]];
        }
        else {
            [item setBackgroundImage:[UIImage imageNamed:unSel] forState:UIControlStateNormal];
        }
    }
}

- (IBAction)actionChange:(UIButton *)sender {
        
        [ToolUI removeSubView:parentView];
        [self highLightButton:sender];
      
}
@end


附注:

参考 : 苹果教程: UIViewControler知识