在IOS6下制作IOS7风格的UISegmentedControl

作者 happyWang 日期 2014-02-18 浏览量
在IOS6下制作IOS7风格的UISegmentedControl

起因

现在 IOS 平台下的应用开发都已经趋向 IOS7 的风格,哪怕系统本身不是 IOS7 的。就比如我们这个应用,开始的时候使用按钮来实现类似 UISegmentedControl 的 UI 和功能,但是后期,需求一改,要求用原生的实现。整个应用都是 IOS7 风格的,在 IOS7 下,使用原生的倒也简单,但是在 IOS6 下面就困难了,立体化的控件是那样的突兀。

没办法,只好在一起走上 Google 之路,不过总算有个好结果。

设置 UISegmentedControl 的背景

在看下文之前,先看这里,没有这个在 stackoverflow 上面的精彩回答,也就不会有这篇文章了,万分感谢!

有了上面的基本技术知识储备,再上一张最终效果图,方便描述思路

最终效果图

从 stackoverflow 的那个回答,可以知道,自定义一个 UISegmentedControl 需要的素材有三种类型:选中时的按钮图片、没选中时候的按钮图片和两个按钮中间的图片(这里说的是只有左右两个按钮的情况)

在那个回答中,作者很耐心的给出了针对性的 5 张图片,但是在我的最终效果里面,中间的那个线是一直不变的,不管两边如何变化,所以我只需要三张图片

需要的素材

再然后就是复制修改代码了:

/* Unselected background */
UIImage *unselectedBackgroundImage = [[UIImage
imageNamed:@"segment-unselected-item.png"]
resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
[[UISegmentedControl appearance] setBackgroundImage:unselectedBackgroundImage
forState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];

/* Selected background */
UIImage *selectedBackgroundImage = [[UIImage
imageNamed:@"segment-selected-item.png"]
resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
[[UISegmentedControl appearance] setBackgroundImage:selectedBackgroundImage
forState:UIControlStateSelected
barMetrics:UIBarMetricsDefault];

/* Image between two unselected segments */
UIImage *bothUnselectedImage = [[UIImage
imageNamed:@"segment-middle.png"]
resizableImageWithCapInsets:UIEdgeInsetsMake(15, 0, 15, 0)];
[[UISegmentedControl appearance] setDividerImage:bothUnselectedImage
forLeftSegmentState:UIControlStateNormal
rightSegmentState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];

/* Image between segment selected on the left and unselected on the right */
UIImage *leftSelectedImage = [[UIImage
imageNamed:@"segment-middle.png"]
resizableImageWithCapInsets:UIEdgeInsetsMake(15, 0, 15, 0)];
[[UISegmentedControl appearance] setDividerImage:leftSelectedImage
forLeftSegmentState:UIControlStateSelected
rightSegmentState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];

/* Image between segment selected on the right and unselected on the left */
UIImage *rightSelectedImage = [[UIImage
imageNamed:@"segment-middle.png"]
resizableImageWithCapInsets:UIEdgeInsetsMake(15, 0, 15, 0)];
[[UISegmentedControl appearance] setDividerImage:rightSelectedImage
forLeftSegmentState:UIControlStateNormal
rightSegmentState:UIControlStateSelected
barMetrics:UIBarMetricsDefault];

在完成上述代码之后,运行,就能看到 UISegmentedControl 的背景已经成功的 IOS7 风格化了

完成UISegmentedControl的背景

但还是有些瑕疵,在选中的 segment 上,字体是白色的,很难识别,而且字体对中文的支持不友好,一大一小的,所以还需要一些美化工作

一些美化

万能的 stackoverflow,再次从它那边找到了完美方案。对于中文,使用 Helvetica 字体是一个不错的选择,然后可以选择性的去掉不好看的阴影,别的设定就是看个人需要,随意增删了。下面给出我的设定:

NSDictionary *selectedAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:@"Helvetica" size:14.0f], UITextAttributeFont,
[UIColor colorWithRed:11/255.0 green:96/255.0 blue:175/255.0 alpha:1],
UITextAttributeTextColor,
[UIColor clearColor], UITextAttributeTextShadowColor,
nil];
[segment setTitleTextAttributes:selectedAttributes forState:UIControlStateSelected];

NSDictionary *normalAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:@"Helvetica" size:14.0f], UITextAttributeFont,
[UIColor whiteColor], UITextAttributeTextColor,
[UIColor clearColor], UITextAttributeTextShadowColor,
nil];
[segment setTitleTextAttributes:normalAttributes forState:UIControlStateNormal];

好了,一个 IOS7 风格的 UISegmentedControl 完成了,下面看看实现的和真正原生的 IOS7 风格的 UISegmentedControl 有什么区别不

区别

边框的细线有点偏粗,字体偏大,圆角过小。这些还是明天再改吧,困了…

后续新增

  • 修改了 segment-unselected-item.png 的细线宽度,由 2px 改成 1px(@2x 的由 4px 改成 2px)
  • 字体尺寸修改为 12.0f
  • 修改 segment-unselected-item@2x.pngsegment-selected-item@2x.png 这两张图片的圆角,由 5px 增加为 10px(根据 IOS7 的风格,UISegmentedControl 的圆角弧度是 10px)

在上一张最终的结果比较

最终比较