问题虽小,你可知晓?

在iOS开发过程中,你是不是经常遇到这样的问题:有些UI效果,明明可以通过属性配置可以实现,却因为不知道而大费周章;某个功能明明实现过,但因为忘记了如何实现而重来一遍。

然而,这些问题往往都是些小问题,明明不应该花费那么多时间,但是我经常被这折腾的够呛。所以,我决定记录一下。以备下次再用。

  • UIBar
  • UINavigationBar
  • UITabBar
  • UITableview
  • 文本
  • 键盘

还记得当初iOS7刚出来的那会儿,对于扁平化与拟物化之间争议的血雨腥风。然而现在大家都已经习惯了扁平化的设计,看到拟物设计时,倒是要吐槽一下了。

对于工程师而言,来不及感叹世事变化太快,这些都是设计师们的事儿,我们还是老老实实做好iOS6、iOS7的适配工作吧。现在扁平化大行其道,我们需要跟iOS6系统本身自带的很多效果say goodbye。

UIBar

UINavigationBar,UITabBar,UIToolBar都是UIBar,下面我们看看iOS6与iOS7之间的差别。

iOSUIBar

很多时候,iOS6自带的那种拟物的立体的效果,会让整个页面非常不协调,我想每位iOS开发工程师都懂的。所以,我们需要把它“拍扁”。

拍扁有两种方式,一种设置背景色,一种设置背景图片。

1.设置背景色:

首先定义一个UIColor的宏

1
#define ColorWithHexValue(hexValue) [UIColor colorWithRed:((float)((hexValue & 0xFF0000) >> 16))/255.0 green:((float)((hexValue & 0xFF00) >> 8))/255.0 blue:((float)(hexValue & 0xFF))/255.0 alpha:1.0]

然后设置UIBar的背景色,需要区分系统版本

1
2
3
4
5
6
7
8
9
10
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1)
{
	[[UINavigationBar appearance] setBarTintColor:ColorWithHexValue(0x289BBE)];
	[[UITabBar appearance] setBarTintColor:ColorWithHexValue(0x289BBE)];
}
else
{
	[[UINavigationBar appearance] setTintColor:ColorWithHexValue(0x289BBE)];
	[[UITabBar appearance] setTintColor:ColorWithHexValue(0x289BBE)];
}

iOS6拍扁后的效果图:

UINavigationBar UITabBar

2.设置背景图片:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//--- 创建一张图片 ---
//--- 此方法可以添加到UIImage的Category方法中 ---
CGRect rect = CGRectMake(0, 0, 1, 1);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
    
CGContextSetFillColorWithColor(context, [UIColor yellowColor].CGColor);
CGContextFillRect(context, rect);
    
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

//--- 拍扁 拍扁 ---
[[UINavigationBar appearance] setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];

[[UITabBar appearance] setBackgroundImage:image];

iOS6拍扁后的效果图

UINavigationBar UITabBar

我们看一下,iOS6中拍扁之后的效果,客观您按需索取吧。总的来说,后面的方法更加扁平。在iOS7中的效果是一样的,您随意选择。

3.在iOS7下所有的UIBar还有毛玻璃效果,属性为translucent

NavigationBar禁用毛玻璃效果:

1
self.navigationController.navigationBar.translucent = NO;

TabBar禁用毛玻璃效果:

1
self.tabBarController.tabBar.translucent = NO;

UINavigationBar

我们来看iOS6与iOS7之间,导航栏的区别,如图:

NavigationBariOS6

NavigationBariOS7

1.首先,我们来解决Back按钮的问题

1
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
//--- 统一设置UIBarButtonItem的文字属性,包括返回按钮 ---
NSDictionary *titleAttributes = @{UITextAttributeFont: [UIFont systemFontOfSize:16],
                                  UITextAttributeTextColor: [UIColor whiteColor]
                                      };
[[UIBarButtonItem appearance] setTitleTextAttributes:titleAttributes
                                            forState:UIControlStateNormal];

//设置图片拉升的区域,根据需要自己设置
UIEdgeInsets edgeInsets = UIEdgeInsetsMake(0, 18, 0, 0);    
UIImage *backImage = [[UIImage imageNamed:@"back"] resizableImageWithCapInsets:edgeInsets];
        
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backImage
                                                  forState:UIControlStateNormal
                                                barMetrics:UIBarMetricsDefault];

//----- 按照系统版本 设置返回按钮 -----
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1)
{
	//设置返回按钮文字的位置,根据需要自己设置
	[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(-5, 0) forBarMetrics:UIBarMetricsDefault];
}
else
{
	//设置返回按钮文字的位置,根据需要自己设置
	[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(3, 1)
                                                         forBarMetrics:UIBarMetricsDefault];
}

测试结果,在模拟环境下iOS7中有点问题,第一次push的时候,back按钮箭头不可见,在真机上没问题。

在iOS7环境下,还有另外一个方法能设置返回按钮

1
2
3
4
UIImage *backImage = [UIImage imageNamed:@"back"];

[[UINavigationBar appearance] setBackIndicatorImage:backImage];
[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:backImage];

2.然后,我们来解决NavigationBar的title

1
2
3
4
NSDictionary *navTitleAttributes = @{NSForegroundColorAttributeName: [UIColor whiteColor],
                                     NSFontAttributeName: [UIFont boldSystemFontOfSize:18]};
    
[[UINavigationBar appearance] setTitleTextAttributes:navTitleAttributes];

3.最后,来设置一下状态栏

1
[[UINavigationBar appearance] setBarStyle:UIBarStyleBlack];

OK,看一下,设置完后的效果:

iOS6导航栏

iOS7导航栏

UITabBar

针对UITabBar,它的拍扁问题,在前面已经解决了,下面我们再看几个问题。

1.设置图标与文本

1
2
3
vc.tabBarItem.title = @"我的客厅";
vc.tabBarItem.image = [UIImage imageNamed:@"icon_home_nm"];
vc.tabBarItem.selectedImage = [UIImage imageNamed:@"icon_home_hl"];

2.设置文字与图标之间的距离

1
vc.tabBarItem.titlePositionAdjustment = UIOffsetMake(0, -3);

3.设置角标

1
vc.tabBarItem.badgeValue = @"5";

我们来看一下效果:

iOS6中的TabBar

iOS7中的TabBar

UITableview

1.关于原点

iOS7系统下,原点在屏幕的左上角,但是我们给UITableview的原点设置成{0,0}时,又感觉它的原点在{0, 64}的位置呢?是因为iOS7下,ViewController有一个automaticallyAdjustsScrollViewInsets属性,默认为YES。

1
self.automaticallyAdjustsScrollViewInsets = NO;

假如UINavigationBar的毛玻璃效果设置成NO,也能打到相同的效果

1
self.navigationController.navigationBar.translucent = NO;

2.cell的选中效果

很多时候都需要用到自定义的cell,cell选中的效果也需要自定义。

如果给cell的中加一个Button,来体现点击的效果,就感觉比较low了,关键效果也不乐观。使用系统自带的cell的Selected效果感觉就比较好了。

1
2
3
4
5
6
//selectedView可以设置圆角,大小等
UIView *selectedView = [UIView alloc] init];
selectedView.backgroundColor = [UIColor lightGrayColor];

//self为cell
self.selectedBackgroundView = selectBgView;

3.cell的分割线

UITableviewCell自带的分割线,基本上无法满足设计师的要求,所以我们还需要自己来画一条分割线。

1
2
3
UIView *sepLine = [UIView alloc] initWithFrame:frame];
sepLine.backgroundColor = [UIColor lightGrayColor];
[cell addSubview:sepLine];

添加完分割线后,发现选中时分割线不见了。我们可以用另外一种方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//--- 创建一张图片 ---
CGRect rect = CGRectMake(0, 0, 1, 1);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
    
CGContextSetFillColorWithColor(context, [UIColor yellowColor].CGColor);
CGContextFillRect(context, rect);
    
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext(); 

//设置分割线
UIImageView *lineImgv = [[UIImageView alloc] initWithFrame:frame];
lineImgv.image = image;
[cell addSubview:lineImgv];

这里以分割线为例,其他设置成背景色的情况也是一样的。

文本

我们有时候需要实现这样的需求:对文本中的部分文字改变样式(加粗、改变字体大小、改变文字颜色);文本需要识别手机号码、邮箱;文本前面几个字不可编辑等等。

1.对文本中的部分文字改变样式

1
2
3
4
5
6
7
8
9
NSString *string = @"海风呼啸,海浪涛涛!";

NSDictionary *attributes = @{NSFontAttributeName: [UIFont boldSystemFontOfSize:16],
                             NSForegroundColorAttributeName: [UIColor redColor]};
NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:string];
[attributeString setAttributes:attributes
                         range:NSMakeRange(0, 2)];

label.attributedText = attributeString;

NSMutableAttributedString对象的Attributes对象是NSDictionary类型,它的key可以在UIKit中的NSAttributedString.h文件中找,按需所取。

这里以UILabel为例,UITextView也有attributedText属性。

效果如图:

改变部分文字的样式

2.文本需要识别手机号码、邮箱

1
textView.dataDetectorTypes = UIDataDetectorTypeAll;

通过设置这个属性,就能自动识别手机号码、日期、链接了。

3.文本前面几个字不可编辑

应用场景:回复某条信息的时候,往往会有个前缀“回复xxx:”,但是这段如果不特殊处理,用户很容易误操作把它删掉,我们从程序上保证前缀的这几个文字不能被删掉。

我们需要实现一个UITextView的委托。

1
2
3
4
5
6
7
8
9
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    if (range.location < 6)	//位置的大小,根据需要自己设置
    {
        return NO;
    }
    
    return YES;
}

键盘

有时候键盘上面需要加一条,完成诸如隐藏键盘等功能,如图:

键盘

这里需要用到UITextView/UITextField的一个属性inputAccessoryView

1
2
3
4
5
6
//此View自行玩弄
UIView *accessoryView = [[UIView alloc] init];
...

//关键是这句
textField.inputAccessoryView = accessoryView;
iOS
iOS