IOS开发系列--无限循环的图片浏览器

这篇博客探讨了如何在iOS中实现无限循环的图片浏览器。首先介绍了UIView的autoresizingMask和transform属性,讲解了屏幕旋转时的处理以及如何进行形变。然后转向UIScrollView,阐述了contentSize、contentInset和contentOffset的概念,并通过示意图展示了它们之间的关系。博客还提到了iOS的内存管理,特别是ARC的作用。最后,通过实际示例详细说明了如何利用ScrollView和UIImageView实现图片的无限循环滚动,以及如何优化性能,避免一次性加载过多图片导致内存消耗过大。
摘要由CSDN通过智能技术生成
--UIKit之UIScrollView

概述

UIKit框架中有大量的控件供开发者使用,在iOS开发中不仅可以直接使用这些控件还可以在这些控件的基础上进行扩展打造自己的控件。在这个系列中如果每个控件都介绍一遍确实没有必要,所谓授人以鱼不如授人以渔,这里会尽可能让大家明白其中的原理,找一些典型的控件进行说明,这样一来大家就可以触类旁通。今天我们主要来看一下UIScrollView的内容:

  1. UIView
  2. UIScrollView
  3. 实战--图片浏览器

UIView

在熟悉UIScrollView之前很有必要说一下UIView的内容。在上一篇文章也简单的对UIView进行了介绍,但是由于那篇文章的主要内容是给大家一个iOS开发的总体印象,因此并没有系统的介绍。另外由于UIScrollView的父类是UIView,所有在讨论UIScrollView之前也很有必要把UIView的知识给补充上,这样大家在使用UIScrollView的某些方法时也不至于无从下手。

既然UIView是所有控件的父类,那么对于一些常用的方法我们很有必要弄清楚,其实在Xcode中要了解一个类有哪些属性和方法特别简单,只要按住apple键点击类名就可以定位到这个类中查看相关定义(在日后的开发中我们会经常这么来做,毕竟要记住iOS开发中所有的API是不现实的,有些API我们可以通过这种方法来查找),例如我们可以查看这个类的内容:

UIViewSourceCode

当然UIView的定义文件(.h文件)也是相当长的,我们如果全部截图也没有意义。这里列出常用的属性和方法。

属性 说明
@property(nonatomic) CGRect            frame; 控件的位置和大小,所有的控件必须指定这个属性,否则即使有控件也无法显示
@property(nonatomic) CGRect            bounds; 当前控件位置和大小,但是和frame不同的是它的位置是确定的(0,0)
@property(nonatomic) CGPoint           center; 控件的中心位置,一般用户进行控件定位
@property(nonatomic) CGAffineTransform transform; 控件矩阵变化,包括平移、缩放、旋转,默认为CGAffineTransformIdentity
@property(nonatomic) UIViewAutoresizing autoresizingMask; 控件旋转时大小自动伸缩,默认为UIViewAutoresizingNone
@property(nonatomic,readonly) UIView       *superview; 当前控件的父控件
@property(nonatomic,readonly,copy) NSArray *subviews; 当前控件的所有一级子控件,注意其子控件的子控件并不包括在内
@property(nonatomic,getter=isHidden) BOOL              hidden; 是否隐藏,默认为NO
@property(nonatomic)                 UIViewContentMode contentMode;  内容模式,主要用于指定控件内容(注意不是子控件)如何填充,一般UIImageView经常使用,默认为UIViewContentModeScaleToFill
@property(nonatomic)                                 NSInteger tag; 控件的标示,可以存储一些和当前控件有关的信息(但是注意只能是整形),默认为0
方法   说明
- (void)addSubview:(UIView *)view; 添加子控件
- (void)removeFromSuperview; 从父控件中移除当前控件
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index; 在指定位置插入子控件
+ (void)beginAnimations:(NSString *)animationID context:(void *)context; 开始一段动画
+ (void)commitAnimations;
结束一段动画,注意在开始和结束之间如果控件的某些属性发生变化iOS将以动画方式进行改变
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations NS_AVAILABLE_IOS(4_0); 以block的形式执行一段动画,注意这个方法有几种相关的重载
- (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer NS_AVAILABLE_IOS(3_2); 添加手势操作
- (void)removeGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer NS_AVAILABLE_IOS(3_2); 移除手势操作

注意上面所有的位置属性都是相对于其父控件而言(不是相对于屏幕而言),多数属性比较简单这里不再详细解释,我们重点解释一下autoresizingMask、transform属性。

autoresizingMask

autoresizingMask这个属性一般我们进行屏幕旋转的时候经常用到,它的值是一个枚举类型:

typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
    UIViewAutoresizingNone                 = 0,      //不进行自动调整
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0, //自动调整与superview左侧距离,右侧距离保持不变
    UIViewAutoresizingFlexibleWidth        = 1 << 1, //自动调整控件自身宽度,保证与superview左右距离不变
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2, //自动调整与superview右侧距离,左侧距离保持不变
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3, //自动调整与superview顶部距离,底部距离保持不变
    UIViewAutoresizingFlexibleHeight       = 1 << 4, //自动调整控件自身高度,保证与superview上下距离不变
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5  //自动调整与superview底部距离,顶部距离保持不变
};

通过注释大家应该大概了解每个枚举值的意义,但是我们知道枚举经常进行按位或操作(“|”),例如如果autoresizingMask=UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleLeftMargin那么iOS如何处理呢?此时会自动调整左边的距离和控件自身宽度,右侧距离不变,同时保证左侧距离和控件宽度同等比例的调整(延长或缩短)。例如在iPhone 5中,如果一个按钮假设自身宽度为200,左右侧距离均为60(左侧和宽度比例3:10),当从竖屏旋转到横屏的时候(此时宽度由320变为568,注意如果有状态栏则宽度变为568-20=548),由于右侧边距不变为60,根据比例左侧边距应该是(568-60)*(3/13)=117,宽度为:(568-60)*(10/13)=391。

请看下面的代码(下面例子通过纯代码方式创建iOS应用,并且自定义一个KCMainViewController):

AppDelegate.m

//
//  AppDelegate.m
//  UIViewAndUIScrollView
//
//  Created by Kenshin Cui on 14-2-23.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import "AppDelegate.h"
#import "KCMainViewController.h"
#import "KCTransformViewController.h"

@interface AppDelegate ()

@end

@implementation AppDelegate
            

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    self.window=[[UIWindow alloc]initWithFrame:[UIScreen mainScreen].applicationFrame];
    
    KCMainViewController *mainController=[[KCMainViewController alloc]init];
    self.window.rootViewController=mainController;
    self.window.backgroundColor=[UIColor colorWithRed:249/255.0 green:249/255.0 blue:249/255.0 alpha:1];

    [self.window makeKeyAndVisible];
    
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

- (void)applicationWillTerminate:(UIApplication *)application {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

@end

KCMainViewController.m

//
//  KCMainViewController.m
//  UIViewAndUIScrollView
//
//  Created by Kenshin Cui on 14-2-23.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import "KCMainViewController.h"

@interface KCMainViewController (){
    UIButton *_btn; //私有变量
}

@end

@implementation KCMainViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //添加一个Button
    _btn=[[UIButton alloc]initWithFrame:CGRectMake(60, 100, 200, 50)];
    _btn.backgroundColor=[UIColor orangeColor];
    [_btn setTitle:@"Hello,world!" forState:UIControlStateNormal];
    _btn.autoresizingMask=UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleLeftMargin;
    [self.view addSubview:_btn];
    
}

#pragma mark 屏幕旋转事件
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
    NSLog(@"%@",NSStringFromCGRect(_btn.frame));
}
@end

在上面的代码中设置了window的背景为灰色,虽然上面有一个UIView但是我们可以看到最终效果是灰色的,这说明UIView默认是透明的。另外定义了一个私有成员变量_btn,这种定义方式大家以后会经常用到。

运行效果:

竖屏

autoSize_portrait

横屏

autoSize_landscape

 

注意上面执行前请先隐藏iOS状态栏目,全局隐藏iO状态栏的方法:

1.在info.plist 中设置Status bar is initially hidden为YES

2.在info.plist中设置View controller-based status bar appearance 为NO

 

transform

transform我们一般称为形变属性,其本质是通过矩阵变化改变控件的大小、位置、角度等,这里我们通过一个例子来

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值