阻止UIScrollView的横向或纵向滚动

介绍UIScrollView的滚动原理和禁止横向或者纵向滚动的方法。

原理

UIScrollView的滚动,真正滚动的不是scrollView本身,而是它的content。scrollView根据自身的frame.size和它的content的size,从而计算content的滚动。正常情况下,content的size是大雨scrollView的,这样就能够任意的滚动

任意滚动

所以在scrollView的content的宽度小于或等于scrollView.frame.size.width的时候,没有办法做横向的滚动,因为content已经全部展示在scrollView中了,没有滚动的必要。

禁止了横向滚动

同理,在scrollView的content的高度小于或等于scrollView.frame.size.height的时候,没有办法做纵向的滚动。

禁止了纵向滚动

实现

现在咱们要做的就是在代码里面针对性的进行修改,以禁止竖向滚动为例:

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 使得contentSize的height等于_scroller的高度,就能禁用纵向滚动
    self.scroller.contentSize = CGSizeMake(640, _scroller.frame.size.height);
    _scroller.delegate = self;
}

参考文献

UIScrollView Class Reference

Disabling vertical scrolling in UIScrollView

关于CSS Media Queries的一些总结

收集整理了从多个网站上面看到的关于Media Queries的一些知识,还有关于屏幕的几种参数的区分

这篇文章主要是自己需要通过Media Queries完成一些工作时候,Google到的一些基本知识储备。所以总结的大部分会是一个链接,指向别的网站。

起因

昨天,因为工作的需要,在文章页底部留白用来展示广告,而广告是第三方的,会根据iPad和iPhone的不同而有不同的尺寸,所以对应的底部留白也需要不同的尺寸。

关于语法

请大家移步到这个博客一看,里面对Media Queries的语法描述的还是很不错的。

总结起来有以下几个要关注的:

  • 语法结构 @media [media_query] media_type and media_feature
  • [media_query] 有not和only两种,但是是可选项
  • media_type 因为现在大多数开发都是基于屏幕设备进行的,所以一般来说写screen
  • and media_feature 这个补充的关于设备的一些描述是可以重复添加的

文章中虽然也说明了Media Queries的一些兼容性问题,不过说的不是很全面,介意是到Can I Use这个网址去看看

后面将基于这个语法进行一些深入的了解

关于屏幕的一些概念

在设定media_feature的时候,device-width到底是什么,这个让我纠结了很久,后面总算是有点突破。其中的概念的区分,主要得益于这两篇文章:“The Relationship Between Screen Size and Resolution”和“width versus device-width”。

一般关于屏幕,有三种说法

Screen Size(屏幕尺寸)

按对角线的方式测量屏幕得到的,一般咱们说的4英寸屏幕、5英寸屏幕,说的就是这个

Screen Resolution(屏幕分辨率)

屏幕尺寸要表达的意思是类似的。是描述这个屏幕的实际宽高,一般都是用px作为单位,比如iPhone4的320×480,iPhone5的320×560

Resolution(分辨率)

这个概念就比较麻烦一点,因为牵扯到了Screen Resolution。比如iPhone4的屏幕分辨率是320×480,而它的分辨率是640×960。这是因为iPhone的retina屏的缘故,使得在实际宽度为320像素的屏幕上,一行能显示640个像素点。这样能够使得显示的画面在同样尺寸上面比一般的屏幕更加精致。

而CSS中使用Media Queries的时候,device-width指的是Screen Resolution——屏幕分辨率

针对iPhone2G-4s,iPhone5,iPad几个设备进行区分的Media Queries

关于区分设备的Media Queries,在上面提到的width versus device-width这篇文章中已经有了一些说明。但是“CSS Media Queries for
iPads & iPhones
”这篇文章实在是很齐全,很明晰,而且页面设计的超赞!

不过对他使用min-device-width和max-device-width的方式感觉有些不是很理解。比如iPhone4,屏幕分辨率是320×480,通过min-device-width:320px和max-device-width:480px就能确定到iPhone4。按我的理解是这样的做法考虑到了横屏和竖屏两种情况,可是在作者专门为iPhone4横屏情况下写的Media Queries的min-device-width和max-device-width还是没有变化,这就让我很是不理解。

不过代码是的确很有用,先记着,等随后有时间再来测试一下看看。当然如果有明白的,也希望能告知一下

在IOS6下制作IOS7风格的UISegmentedControl

通过UISegmentedControl的setBackgroundImage:forState:barMetrics:方法和setDividerImage:forLeftSegmentState:rightSegmentState:barMetrics:方法,以及一点点Photoshop的基本功,就能在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.png和segment-selected-item@2x.png这两张图片的圆角,由5px增加为10px(根据IOS7的风格,UISegmentedControl的圆角弧度是10px)

在上一张最终的结果比较

最终比较