iOS中基本控件和使用

1. UIView属性

Controller的viewDidLoad方法:当所有控件加载完毕后调用,相当于Android中View的onFinishInflate方法;

UIView superview 获得自己的父控件对象;

NSArray subview 获得自己的子控件对象,用数组NSArray保存;

NSInteger tag 控件的ID标示,父控件可以通过tag来找到对应的子控件;

CGRect fram 控件所在矩形框的位置和尺寸(以父控件的左上角为坐标原点);

CGRect bounds 控件所在矩形框的位置和尺寸(以自己左上角为坐标原点,所以bounds的x\y永远为0);

CGPoint center 控件中点的位置(以父控件 的左上角为坐标原点);

CGAffineTransform transform 控件的形变属性(可以设置旋转角度、比例缩放、平移等属性);

UIColor backgroundColor 背景颜色

BOOL hidden 设置是否隐藏

CGFloat alpha 透明度(0~1)

CGFloat opaque 不透明度(0~1)

BOOL userInteractionEnabled 默认YES,是否可以和用户交互(相当于android enable)

UIViewContentMode contentMode 内容显示的模式(android:gravity =”center_vertical”)

另外UIView中有很多扩展协议,用来处理控件的属性

修改UIView的尺寸(宽高):frame、bounds

修改UIView的位置:frame(左上角的位置)、center(中点的位置)

2. UIView方法

addSubview 添加子控件,被添加到最上面(subviews中的最后面)

removeFromSuperview 将自己从父控件中移除

viewWithTag 父控件可以根据这个tag标示找到对应的子控件(遍历所有的子控件)findViewById

insertSubview:atIndext 添加子控件到指定的位置

beginAnimations: context: 执行动画

/…需要执行动画的代码…/

commitAnimations

利用代码块block执行动画

> /*
> 
> *duration 动画持续时间
> 
> *animations 存放需要执行动画的代码
> 
> *completion 存放动画执行完毕后需要执行的代码
> 
> */+ (void)animateWithDuration:(NSTimeInterval) duration animations:(void(^)(void))animations completion:(void(^)(BOOLfinished))completion

3. UIControl

只要继承了UIControl就能简单处理一些事件(点击事件、值改变事件);

继承了UIControl的子类有:UIButton、UISlider、UISwitch、UIDatePicker等等;

当需要监听一个子控件的事件的时候,先要看它是否继承自UIControl,再看它内部是否有delegate属性(代理);

常用属性:

enable 是否处理事

contentVerticalAlignment 内容在垂直方向上的排布方式

contentHorizontalAlignment 内容在水平方向上的排布方式

常用方法

addTarget 添加事件监听器(参数:监听器对象、事件触发回调方法、事件类型)

removeTarget 删除事件监听器

allTargets 获取所有的监听器对象集合

常用控件

1. UIImageView 图片显示控件(android ImageView)

> @property(weak,nonatomic)IBOutletUIImageView*imageView;self.imageView.image= [UIImageimageNamed:@“icon.png"];

设置图片展示模式(android ImageView 的scaleType属性): 

[图片上传失败...(image-a7eb8-1542002718992)]

2. UISlider可拖动的进度条 (android SeekBar

> @property(weak,nonatomic)IBOutletUISlider *slider;//设置最大值self.slider.maximumValue=self.imageDate.count;//设置最小值self.slider.minimumValue=1;//设置当前值self.slider.value=1;

3. UIButton按钮

常用属性

titleLable 获取内部的UILabel对象

imageView 获取内部的UIImageView对象

常见方法

setTitle:forState: 设置背部UILable显示的文本内容(不能写btn.titleLabel.text = @"123")

setTileColor:forState 设置内部UILabel文字颜色

setTileShaowColor:forState 设置内部UILabel文字的阴影颜色

setImage:forState 设置内部UIImageView的图片(不能写btn.iamgeView.image =[ UIImage imagedName:@"0.png"])

setTileShaowColor:forState 设置内部UILabel文字的阴影颜色

setBackgroundImage:forState 设置背景图片

下面方法可以获取不同状态下的一些属性值:

titleForState 获取某个状态下显示文字

titleColorForState 获取某个状态下文字颜色

titleShadowColorForState 获取某个状态下文字阴影颜色

imageForState 获取某个状态下图片

backgroundImageForState 获取某个状态下背景图片

下面两个方法需要交给子类重写(继承UIButton):

titleRectForContentRect 返回内部UILabel的frame(位置和尺寸)

imageRectForContentRect 返回内部UIImageView的frame(位置和尺寸)

示例代码

普通按钮custom

> //创建按钮
> 
> UIButton*orangeBtn = [[UIButtonalloc]init];
> 
> orangeBtn.tag=kOrangeTag;
> 
> //设置按钮的frame(位置和尺寸)
> 
> orangeBtn.frame=CGRectMake(100,100,100,100);
> 
> //设置背景色
> 
> orangeBtn.backgroundColor= [UIColororangeColor];
> 
> //设置按钮文字
> 
> [orangeBtnsetTitle:@"普通"forState:UIControlStateNormal];[orangeBtnsetTitle:@"按下"forState:UIControlStateHighlighted];
> 
> //设置按钮按下时文字颜色
> 
> [orangeBtnsetTitleColor:[UIColorredColor]forState:UIControlStateHighlighted];UIButton*btn = [[UIButtonalloc]init];
> 
> //添加按钮的唯一标示
> 
> btn.tag=1;
> 
> //根据图片名称去项文件系统中加载图片对象
> 
> UIImage*imageNormal = [UIImageimageNamed:@"sub_black_prev.png"]];UIImage*imagePress = [UIImageimageNamed:@"sub_blue_prev.png"]];
> 
> //设置按钮背景图片
> 
> [btnsetBackgroundImage:imageNormalforState:UIControlStateNormal];[btnsetBackgroundImage:imagePressforState:UIControlStateHighlighted];
> 
> //设置按钮的frame(位置和尺寸)
> 
> //btn.frame = CGRectMake(point.x, point.y, imageNormal.size.width, imageNormal.size.height);/*
> 
>     struct CGRect {
> 
>     CGPoint origin;
> 
>     CGSize size;
> 
>     };
> 
>     */btn.frame= (CGRect){point, imageNormal.size};
> 
> //绑定监听
> 
> [btn addTarget:selfaction:@selector(directionBtnClick:) forControlEvents:UIControlEventTouchUpInside];
> 
> //根据按钮的tag获取子控件
> 
> UIButton*orangeBtn = [self.viewviewWithTag:kOrangeTag];CGPointcenter = orangeBtn.center;staticCGFloatDELETE =50;center.y+= DELETE;
> 
> //重新赋值按钮的中点orangeBtn.center= center;

根据系统自带样式类型创建

//创建一个加号的按钮UIButton*btn = [UIButtonbuttonWithType:UIButtonTypeContactAdd];btn.center= CGPointMake(100,100);

4. UILable 文本 (android TextView)

常用属性:

text 显示文本内容

textColor 文字颜色

font 字体

shadowColor 文字的阴影颜色

shadowOffset 阴影的偏差距离(width水平方向的偏差距离,整数右边;height垂直方向上的偏差距离,正数下边)

textAlignment 设置文字的排列方式(偏左、偏右、居中)

numberOfLines 允许文字最多几行(默认1,如果是0,自动换行)

5. UIText 文本输入框(android EditText)

6. UISwitch 开关

#pragma mark 开关值改变监听-(IBAction)switchChanged:(UISwitch *)sender {NSLog(@"开关值%d", sender.isOn);self.view.backgroundColor= sender.isOn?[UIColordarkGrayColor]:[UIColorwhiteColor];}

7. UIDatePicker日期控件

> -(void) viewDidLoad{   
> 
> [superviewDidLoad];   
> 
> UIDatePicker *picker = [[UIDatePicker alloc] init];
> 
> //设置区域picker.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"];
> 
> //设置模式(显示日期还是时间)picker.datePickerMode = UIDatePickerModeDate;}#pragma mark 拖动时间改变后监听
> 
> -(IBAction)dateChanged:(UIDatePicker *) dataPicker{
> 
> //获取日期值
> 
> NSDate *date= dataPicker.date;
> 
> //格式化日期
> 
> NSDateFormatter *formatter = [[NSDateFormatter alloc] init];   
> 
> formatter.dateFormat = @"yyyy/MM/bb";   
> 
> self.label.text = [formatter stringFromDate:date];}

8. UIPickerView 跟android Spinner相似

设置数据源和代理(监听)为控制器,控制器遵循数据源河代理的协议,重写协议的方法:

简单使用

> #pragma mark 控制器充当UIPickerView的数据源和代理,必须遵循两个协议@interface ViewController : UIViewController@property (weak, nonatomic) IBOutlet UIPickerView *pickerView;
> 
> @end
> 
> #import "ViewController.h"
> 
> @interface ViewController()
> 
> @property (nonatomic,strong) NSArray *oneCol;
> 
> @property (nonatomic,strong) NSArray *towCol;
> 
> @end
> 
> @implementation ViewController
> 
> -(void) viewDidLoad{
> 
>     self.oneCol = @[@"00", @"01", @"02", @"03"];
> 
>     self.towCol = @[@"000", @"001", @"002", @"003", @"004"];
> 
> }
> 
> #pragma mark - UIPickerView的数据源方法(返回第component列的行数)
> 
> -(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
> 
>     return component == 0?self.oneCol.count:self.towCol.count;
> 
> }
> 
> #pragma mark - UIPickerView的数据源方法(返回列数)
> 
> -(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
> 
>     return 2;
> 
> }
> 
> #pragma mark - UIPickerView的代理方法(返回第component列第row航显示的字符串数据-设置数据)
> 
> -(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
> 
>     if(component==0){
> 
>         return self.oneCol[row];
> 
>     }else{
> 
>         return self.towCol[row];
> 
>     }
> 
> }
> 
> #pragma mark - UIPickerView的代理方法(选中了某一行调用)
> 
> -(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
> 
>     if(component==0){
> 
>         NSString *leftRow = self.oneCol[row];
> 
>         //获取第二列当前停留的行数
> 
>         int towRow = [pickerView selectedRowInComponent:1];
> 
>         NSString *rightRow = self.towCol[towRow];
> 
>         NSLog(@"第%d列:%@-----第%d列:%@", component, leftRow, 1, rightRow);
> 
>     }else{
> 
>         NSString *rightRow = self.towCol[row];
> 
>         int oneRow = [pickerView selectedRowInComponent:0];
> 
>         NSString *leftRow = self.oneCol[oneRow];
> 
>         NSLog(@"第%d列:%@-----第%d列:%@", 0, leftRow, 1, rightRow);
> 
>     }
> 
> }
> 
> @end

显示自定义条目

> #pragma mark 修改每一行的高度-(CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{
> 
>     return 70;
> 
> }#pragma mark 返回地component列第row行需要显示的控件-(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
> 
>     UIView *rowView = [[UIView alloc] init];
> 
>     CGFloat rowViewH = 40;
> 
>     CGFloat rowViewW = 200;
> 
>     rowView.bounds = CGRectMake(0, 0, 200, rowViewH);
> 
>     //国家名称    UILabel *nameLable = [[UILabel alloc] init];
> 
>     CGFloat nameW = 70;
> 
>     nameLable.frame = CGRectMake(0, 0, nameW, rowViewH);
> 
>     nameLable.textAlignment = NSTextAlignmentCenter;
> 
>     nameLable.text = @"asdfsd";
> 
>     [rowView addSubview:nameLable];
> 
>     //国旗    UIImageView *imageView = [[UIImageView alloc] init];
> 
>     imageView.frame = CGRectMake(nameW, 0, rowViewW-nameW, rowViewH);
> 
>     imageView.image = [UIImage imageNamed:@"zhongguo.jpg"];
> 
>     [rowView addSubview:imageView];
> 
>     return rowView;
> 
> }

9. UIScollView (android ScollView)

UIPageControl 请见:分页显示

当子控件内容太多或者子控件太大显示不全时,用UIScrollView实现滚动

常用属性

CGPoint contentOffset UIScrollView当前滚动到哪个位置了(相对于内容左上角的坐标)

CGSize contentSize UIScrollView的滚动范围(内容的尺寸)

UIEdgeInsets contentInset 这个属性可以在四周增加滚动范围

[图片上传失败...(image-52733c-1542002718992)]

BOOL bounces; 是否有弹簧效果

BOOL scrollEnabled; 是否能滚动

BOOL showsHorizontalScrollIndicator 是否显示水平方向的滚动条

BOOL showsVerticalScrollIndicator 是否显示垂直方向的滚动条

UIScrollViewIndicatorStyle indicatorStyle 设定滚动条的样式

BOOL tracking 是否正在被拖拽

BOOL dragging 当touch后还没有拖动的时候值是YES,否则是NO

BOOL decelerating 是否正在减速

使用示例:

> UIImage *image = [UIImage imageNamed:@"1.png"];
> 
> //通过图片初始化UIImageview,这样ImageView的宽高就跟图片宽高一样了
> 
> UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
> 
> [self.scroll addSubview:imageView];
> 
> //self.scroll.frame.size  UIScrollView控件的大小(可视范围)
> 
> //设置内容的宽高(可滚动范围)
> 
> self.scroll.contentSize = image.size;
> 
> //为UIScrollView设置上下左右额外的可拖动范围(空隙)
> 
> self.scroll.contentInset = UIEdgeInsetsMake(10, 20, 30, 40);
> 
> self.scroll.backgroundColor = [UIColor lightGrayColor];
> 
>   //self.scroll.contentOffset.x += 10;//不能直接修改对象的结构体属性的成员
> 
> //修改UIScrollView当前拖动的位置(相对于内容左上角的坐标)
> 
> CGPoint offset = self.scroll.contentOffset;
> 
> //向左移动(查看右边的内容)
> 
> offset.x += 50;
> 
> //执行动画
> 
> [UIView animateWithDuration:0.3 animations:^{
> 
>     self.scroll.contentOffset = offset;
> 
> }];

手势识别缩放

@property(nullable,nonatomic,weak)id delegate;

1

iOS中的UIScrollView已经封装了手势识别,不需要我们分析手指位置以及滑动方向,只需要设置上面的代理属性即可(代理可以理解为回调接口),这个代理需要遵守UIScrollViewDelegate协议;然后选择性的实现里面的回调方法。

而android中如果要实现此功能,需要我们分析多点触控以及手指位置和滑动方向来判断缩放还是放大。

步骤:

①、设置UIScrollView的代理delegate为控制器,控制器遵守UIScrollViewDelegate协议

②、设置最大和最小缩放比例maximumZoomScale,minimumZoomScale

③、让代理对象实现方法,返回需要缩放的子控件

> //设置最大缩放比例
> 
> self.scroll.maximumZoomScale = 2;
> 
> //设置最小缩放比例
> 
> self.scroll.minimumZoomScale = 0.5;
> 
> #pragma mark -UIScrollView的代理方法:返回需要进行缩放的空间(必须是UIScrollVIew的子控件)
> 
> (nullable UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
> 
>     return self.imageView;
> 
> }

代理中其他方法:

> - (void)scrollViewDidScroll:(UIScrollView *)scrollView; // any offset changes offset属性变化时调用(在被拖动)
> 
> // 将要开始拖拽时调用
> 
> - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;     
> 
> // 拖拽将要结束时调用
> 
> - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset NS_AVAILABLE_IOS(5_0);
> 
> // 拖拽结束时调用
> 
> - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
> 
> - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView;  // called on finger up as we are moving
> 
> - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;      // ScrollView减速完毕后调用                                           
> 
> - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView; // called when setContentOffset/scrollRectVisible:animated: finishes. not called if not animating
> 
> - (nullable UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;    // 返回需要进行缩放的子控件
> 
> - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view NS_AVAILABLE_IOS(3_2); // 将要缩放之前调用
> 
> - (void)scrollViewDidZoom:(UIScrollView *)scrollView NS_AVAILABLE_IOS(3_2); // any zoom scale changes 缩放时调用
> 
> - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view atScale:(CGFloat)scale; // 缩放完毕后调用
> 
> - (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView;  // return a yes if you want to scroll to the top. if not defined, assumes YES
> 
> - (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView;      // called when scrolling animation finished. may be called immediately if already at top

分页显示(android ViewPager)

[图片上传失败...(image-8798eb-1542002718991)]

> #define kCount 5
> 
> @interface ViewController()
> 
> @property (nonatomic, weak)UIPageControl *_pageControl;
> 
> @property (nonatomic, weak) UIScrollView*_scrollView;
> 
> @end
> 
> @implementation ViewController
> 
> - (void)viewDidLoad {
> 
>    [superviewDidLoad];
> 
>    for(int i = 0; I
> 
>         [self.view.subviews[i] removeFromSuperview];
> 
>     }
> 
>     //分页显示
> 
>     //1、添加UIScrollView
> 
>     UIScrollView *scrollView = [[UIScrollViewalloc] init];
> 
>     //设置填充父窗体
> 
>     scrollView.frame = self.view.bounds;
> 
>     [self.viewaddSubview:scrollView];
> 
>     self._scrollView= scrollView;
> 
>     CGFloat scrollWdith = scrollView.frame.size.width;
> 
>     CGFloat scrollHight = scrollView.frame.size.height;
> 
>     // 2、添加所有的ImageView
> 
>     for(int i = 0;i<=kCount;i++){
> 
>         //加载图片
> 
>         NSString*imageName = [NSString stringWithFormat:@"pages.bundle/%d.jpg", I];
> 
>         UIImage *image = [UIImageimageNamed:imageName];
> 
>         UIImageView *imageView = [[UIImageViewalloc] init];
> 
>         imageView.image= image;
> 
>         imageView.frame = CGRectMake((i-1)*scrollWdith, 0, scrollWdith, scrollHight);
> 
>         [scrollViewaddSubview:imageView];
> 
>     }
> 
>     //3、设置滚动范围
> 
>     scrollView.contentSize = CGSizeMake(kCount*scrollWdith, 0);
> 
>     //隐藏滚动条
> 
>     scrollView.showsHorizontalScrollIndicator = NO;
> 
>     //4、开启分页功能(按照ScrollView的宽度将内容分为若干页,正好ImageView的宽度相等,就实现了分页)
> 
>     scrollView.pagingEnabled = YES;
> 
>     //5、添加PageControl
> 
>     UIPageControl *pageControl =[[UIPageControl alloc] init];
> 
>     pageControl.bounds = CGRectMake(0, 0, 150, 50);
> 
>     pageControl.center = CGPointMake(scrollWdith * 0.5,
> 
> scrollHight - 50);
> 
>     //设置页数
> 
>     pageControl.numberOfPages= kCount;
> 
>     //当前选中页码对应控制器的颜色
> 
>     pageControl.currentPageIndicatorTintColor = [UIColorredColor];
> 
>     //其他控制器的颜色
> 
>     pageControl.pageIndicatorTintColor = [UIColorblackColor];
> 
>     //监听pageControl事件
> 
>     [pageControl addTarget:self action:@selector(pageChanged:)forControlEvents:UIControlEventValueChanged];
> 
>     //添加控制器
> 
>     [self.viewaddSubview: pageControl];
> 
>     self._pageControl= pageControl;
> 
>     //设置代理
> 
>     scrollView.delegate = self;
> 
>     //不需要弹簧效果
> 
>     scrollView.bounces = NO;
> 
> }
> 
> #pragma mark -滚动代理:减速完毕后调用(停止了)
> 
> - (void)scrollViewDidEndDecelerating:(UIScrollView*)scrollView{
> 
>     CGFloat offset = scrollView.contentOffset.x;   //当前x轴方向上滚动了多少
> 
>     int pageNum = offset/scrollView.frame.size.width;
> 
>     //设置页码
> 
>     self._pageControl.currentPage= pageNum;
> 
> }
> 
> #pragma mark
> 
> pageControl值变化时调用
> 
> -(void) pageChanged{
> 
>     CGFloat offsetX = self._pageControl.currentPage * self.view.frame.size.width;
> 
>     [UIView beginAnimations:nilcontext:nil];
> 
>     self._scrollView.contentOffset = CGPointMake(offsetX, 0);
> 
>     [UIViewcommitAnimations];
> 
> }
> 
> @end
> 
> ew�'qкX

10. UITableView( android ListView GridView ExpandListView)

10.1 数据源方法

TableView相当于ListView,设置数据源需要遵循UITableViewDataSource协议,相当于BaseAdapter,下面是协议的所有接口:

> @protocol UITableViewDataSource
> 
> @required   必须实现的
> 
> - (NSInteger)tableView:(UITableView *)tableView
> 
> numberOfRowsInSection:(NSInteger)section;   // 第section组有多少行数据
> 
> // 返回每一行显示的具体数据View(相当于getView()方法)
> 
> - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath;
> 
> @optional  选择实现的
> 
> - (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView;  // 一共有多少组数据(如果没有实现,默认为1)
> 
> - (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; // 分组头部标题
> 
> - (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section; // 分组尾部标题
> 
> // Individual
> 
> rows can opt out of having the -editing property set for them. If not
> 
> implemented, all rows are assumed to be editable.
> 
> - (BOOL)tableView:(UITableView*)tableView canEditRowAtIndexPath:(NSIndexPath*)indexPath;
> 
> //
> 
> Moving/reordering
> 
> // Allows the
> 
> reorder accessory view to optionally be shown for a particular row. By default,
> 
> the reorder control will be shown only if the datasource implements
> 
> -tableView:moveRowAtIndexPath:toIndexPath:
> 
> - (BOOL)tableView:(UITableView*)tableView canMoveRowAtIndexPath:(NSIndexPath*)indexPath;
> 
> //索引(e.g. "ABCD...Z#")
> 
> - (nullable NSArray *)sectionIndexTitlesForTableView:(UITableView*)tableView __TVOS_PROHIBITED;                                                 
> 
> - (NSInteger)tableView:(UITableView*)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index__TVOS_PROHIBITED;  // tell table
> 
> which section corresponds to section title/index (e.g. "B",1))
> 
> // Data
> 
> manipulation - insert and delete support
> 
> // After a row
> 
> has the minus or plus button invoked (based on the UITableViewCellEditingStyle
> 
> for the cell), the dataSource must commit the change
> 
> // Not called
> 
> for edit actions using UITableViewRowAction - the action's handler will be
> 
> invoked instead
> 
> - (void)tableView:(UITableView*)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
> 
> forRowAtIndexPath:(NSIndexPath*)indexPath;
> 
> // Data
> 
> manipulation - reorder / moving support
> 
> - (void)tableView:(UITableView *)tableView
> 
> moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath
> 
> toIndexPath:(NSIndexPath*)destinationIndexPath;
> 
> @end
> 

10.2 代理 UITableViewDelegate

> // 返回条目高度(可以根据不同的行号返回不同的高度)
> 
> - (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath;
> 
> - (CGFloat)tableView:(UITableView*)tableView heightForHeaderInSection:(NSInteger)section;
> 
> - (CGFloat)tableView:(UITableView*)tableView heightForFooterInSection:(NSInteger)section;
> 
> //  选中某一行的时候调用(点击)
> 
> -(void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
> 
> // 取消选中某一行
> 
> -(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
> 

10.3 常用属性和方法

[图片上传失败...(image-f6906d-1542002718991)]

10.4 多组数据

[图片上传失败...(image-cac2f2-1542002718991)]

> @interface ViewController()
> 
>      @property (nonatomic, strong) NSArray*gd;
> 
>      @property (nonatomic, strong) NSArray*hn;
> 
> @end
> 
> @implementation ViewController
> 
> - (void)viewDidLoad {
> 
>     [superviewDidLoad];
> 
>     self.gd = @[@"广州",
> 
> @"东莞",
> 
> @"惠州"];
> 
>     self.hn = @[@"常德",
> 
> @"长沙",
> 
> @"湘潭",
> 
> @"株洲",
> 
> @"岳阳",
> 
> @"湘西自治州"];
> 
> }
> 
> #pragma mark - 数据源方法
> 
> #pragma mark - 1、一共多少组数据
> 
> -(NSInteger)numberOfSectionsInTableView:(UITableView*)tableView{
> 
>     return 2;   //广东、湖南
> 
> }
> 
> #pragma mark - 2、第section组有多少行数据
> 
> -(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section{
> 
>    return section==0?self.gd.count:self.hn.count;
> 
> }
> 
> #pragma mark - 3、返回每一行显示的具体数据
> 
> -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath{
> 
>     // 组 indexPath.section
> 
>     // 列 indexPath.row
> 
>     UITableViewCell *cell = [[UITableViewCell alloc]
> 
> initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
> 
>     NSString *city = nil;
> 
>     if(indexPath.section == 0){
> 
>         city =self.gd[indexPath.row];
> 
>     }else{
> 
>         city =self.hn[indexPath.row];
> 
>     }
> 
>     //设置右边箭头样式
> 
>     cell.accessoryType= UITableViewCellAccessoryDisclosureIndicator;
> 
>     //设置cell上面显示的文本数据
> 
>     cell.textLabel.text= city;
> 
>     returncell;
> 
> }
> 
> #pragma mark - 4、 第section组的header标题
> 
> -(NSString *)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section{
> 
>     return section == 0? @"广州" :
> 
> @"湖南";
> 
> }
> 
> #pragma mark - 5、 第section组的尾部标题
> 
> -(NSString *)tableView:(UITableView*)tableView titleForFooterInSection:(NSInteger)section{
> 
>     return section == 0? @"广东很多帅哥":
> 
> @"湖南很多美女";
> 
> }
> 
> #pragma mark- 6、 索引,通讯录效果,是按照分组而不是拼音首字母的索引
> 
> - (nullable NSArray *)sectionIndexTitlesForTableView:(UITableView*)tableView __TVOS_PROHIBITED{
> 
>     return @[@"广州",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南",
> 
> @"湖南"];
> 
> }
> 
> #pragma mark-
> 
> UITableView代理方法
> 
> #pragma mark- 1、 返回某一行的高度
> 
> - (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath{
> 
>     return 70;
> 
> }
> 
> #pragma mark- 2、 选中某一行的时候调用(点击)
> 
> -(void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath{
> 
>     NSString *city = indexPath.section== 0? self.gd[indexPath.row] : self.hn[indexPath.row];
> 
>     //弹出对话框修改地名
> 
>     UIAlertView *alert =[[UIAlertView alloc] initWithTitle:@"地名" message:nil delegate:selfcancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
> 
>     //设置alertview样式
> 
>     alert.alertViewStyle= UIAlertViewStylePlainTextInput;
> 
>     //取出文本输入框
> 
>     [alert textFieldAtIndex:0].text= city;
> 
>     alert.tag = 1;
> 
>     //显示对话框
> 
>     [alert show];
> 
> }
> 
> #pragma mark-
> 
> UIAlertView代理方法
> 
> #pragma mark- 对话框按钮点击
> 
> - (void)alertView:(UIAlertView *)alertView
> 
> clickedButtonAtIndex:(NSInteger)buttonIndex
> 
> NS_DEPRECATED_IOS(2_0, 9_0){
> 
>     if(buttonIndex == 1){
> 
>         //点击了确定按钮
> 
>         //取得输入框文本
> 
>         NSString *city = [alertView textFieldAtIndex:0].text;
> 
>         NSString *old = self.gd[0];
> 
>         old = [NSString stringWithFormat:@"%@",city];
> 
>         //刷新UITableView数据,相当于android 的 adaptert.notifyDatesetChanged()
> 
>         //刷新所有数据
> 
> //        [self.tableView reloadData];
> 
>         //局部刷新
> 
>         NSIndexPath *path = [NSIndexPath indexPathForRow:alertView.tag inSection:0];
> 
>         [self.tableViewreloadRowsAtIndexPaths:@[path]withRowAnimation:UITableViewRowAnimationLeft];
> 
>     }
> 
> }
> 
> @end
> 

10.5 单组数据(ListView效果)

数据源返回分组数量的方法返回值为1就能实现单组效果

UITableViewCell系统样式:

[图片上传失败...(image-5a38a6-1542002718991)]

条目右边箭头样式:

[图片上传失败...(image-1a5660-1542002718991)]

10.6 性能优化

复用Cell

> #pragma mark 每当有一个cell进入视野范围内就会调用,返回当前这行显示的cell
> 
> - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
> 
> {
> 
>     // 0.用static修饰的局部变量,只会初始化一次< # # >
> 
>     static NSString *ID = @"Cell";
> 
>     // 1.拿到一个标识先去缓存池中查找对应的Cell
> 
>     UITableViewCell*cell = [tableView dequeueReusableCellWithIdentifier:ID];
> 
>     // 2.如果缓存池中没有,才需要传入一个标识创建新的Cell
> 
>     if (cell == nil) {
> 
>         cell = [[UITableViewCellalloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
> 
>     }
> 
>     // 3.覆盖数据
> 
>     cell.textLabel.text = [NSString stringWithFormat:@"
> 
> fdsfdsf-%d", indexPath.row];
> 
>     returncell;
> 
> }
> 

用户代码提醒

Xcode中有很多系统自带的代码块,只需要拖动到编辑器中,就能自动生成代码,这样可以避免写很多重复代码,方便编程;也可以自定义用户代码块,比如上面复用Cell的模板方法,选中代码后拖动到右下角代码块中即可。

[图片上传失败...(image-84db53-1542002718991)]

10.7 编辑模式

[图片上传失败...(image-3d52b8-1542002718991)]

删除\添加

开启编辑模式:

> // 开启编辑模式
> 
>     //self.tableView.editing
> 
> = YES;
> 
>     //[self.tableView
> 
> setEditing:YES];
> 
>     // 带有动画效果
> 
>     [self.tableView setEditing:! edt animated:YES];

下面方法的返回值决定编辑模式是添加还是删除:

> #pragma mark - 代理方法
> 
> #pragma mark 当tableview开启编辑模式就会调用
> 
> -(UITableViewCellEditingStyle)tableView:(UITableView *)tableVieweditingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
> 
> {
> 
>     //return
> 
> indexPath.row%2 ? UITableViewCellEditingStyleDelete :
> 
> UITableViewCellEditingStyleInsert;
> 
>     returntableView.tag;
> 
> }
> 

实现数据源的方法删除或添加数据:

> #pragma mark 提交编辑操作(点击了"删除"或者"+"按钮)时调用
> 
> // 实现了这个方法,就有左划删除功能
> 
> - (void)tableView:(UITableView*)tableViewcommitEditingStyle:(UITableViewCellEditingStyle)editingStyle  forRowAtIndexPath:(NSIndexPath*)indexPath
> 
> {
> 
>     //NSLog(@"------commit---%d",
> 
> indexPath.row);
> 
>     if(editingStyle == UITableViewCellEditingStyleDelete) {
> 
>         // 删除
> 
>         // 1.更改数据(删除本行的数据)
> 
>         [self.mydata removeObjectAtIndex:indexPath.row];
> 
>         // 2.刷新UI界面
> 
>         //[tableView
> 
> reloadData];
> 
>         [tableViewdeleteRowsAtIndexPaths:@[indexPath]withRowAnimation:UITableViewRowAnimationLeft];
> 
>     }else{
> 
>         // 添加
> 
>         // 1.更改数据(添加数据)
> 
>         // [self.mydata
> 
> addObject:@" hahahhahah"];添加到最后面去了
> 
>         // 插入数据到本行的后面
> 
>         [self.mydata insertObject:@"新添加的数据...." atIndex:indexPath.row +1];
> 
>         // 2.刷新UI界面
> 
>         //[tableView
> 
> reloadData];
> 
>         // 刷新指定行(个数不变)
> 
>         //[tableView
> 
> reloadRowsAtIndexPaths:<#(NSArray *)#>
> 
> withRowAnimation:<#(UITableViewRowAnimation)#>];
> 
>         // 删除指定行
> 
>         //[tableView
> 
> deleteRowsAtIndexPaths:<#(NSArray *)#>
> 
> withRowAnimation:<#(UITableViewRowAnimation)#>];
> 
>         // 插入新的行
> 
>         NSIndexPath *newPath = [NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0];
> 
>         [tableViewinsertRowsAtIndexPaths:@[newPath] withRowAnimation:UITableViewRowAnimationTop];
> 
>     }
> 
> }

排序

如果实现了数据源UITableViewDataSource的moveRowAtIndexPath方法,就会有排序拖动功能,但这只是界面表面的变化,数据顺序并没有变,所以在这个方法中,需要改变数据顺序。

> #pragma mark 如果实现了这个方法, 就会有排序功能
> 
> - (void)tableView:(UITableView*)tableView moveRowAtIndexPath:(NSIndexPath*)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPath
> 
> {
> 
>     // 取出即将要删除的数据
> 
>    NSString *data = self.mydata[sourceIndexPath.row];
> 
>     // 删除需要移动的那一行
> 
>     [self.mydataremoveObject:data];
> 
>     // 插入之前删除的数据
> 
>     [self.mydata insertObject:data atIndex:destinationIndexPath.row];
> 
> }
> 

4个刷新UI界面的方法

添加新的行:

[tableView insertRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationTop];

删除指定的行:

[tableView deleteRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationTop]

局部刷新指定的行:

[tableView reloadRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationTop]

整体刷新所有的行:

[tableView reloadData]

10.8 自定义Cell

步骤:

①、新建xid来描述Cell(拖一个UITableViewCell设置宽高以及identify);

②、实现数据源和代理方法,返回数据和Cell的高度(heightForRowAtIndexPath );

③、拿到Cell中的子控件绑定数据(根据tag);

④、拿到按钮绑定监听器(根据事件取得事件点对应的行号)

> #pragma mark 每当有一个cell进入视野范围内就会调用,返回当前这行显示的cell
> 
> - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
> 
> {
> 
>     // 0.用static修饰的局部变量,只会初始化一次
> 
>     static NSString *ID = @"Cell";
> 
>     // 1.拿到一个标识先去缓存池中查找对应的Cell
> 
>     UITableViewCell*cell = [tableView dequeueReusableCellWithIdentifier:ID];
> 
>     // 2.如果缓存池中没有,才需要传入一个标识创建新的Cell
> 
>     if (cell == nil) {
> 
>         // 通过 xib文件来加载cell
> 
>         NSBundle *bundle = [NSBundlemainBundle];
> 
>         NSArray * objs = [bundle loadNibNamed:@"BookCell" owner:nil options:nil];
> 
>         cell = [ objs lastObject];
> 
>         // 绑定监听器
> 
>         UIButton*collect  = (UIButton *)[cell viewWithTag:3];
> 
>         [collect addTarget:self action:@selector(collectBook:event:)forControlEvents:UIControlEventTouchUpInside];
> 
>     }
> 
>     //cell.tag =
> 
> indexPath.row + 1000;
> 
>     // 3.覆盖数据
> 
>     // 3.1 取出book对象
> 
>     Book *book =self.books[indexPath.row];
> 
>     // 3.2 设置名称
> 
>     UILabel *nameLabel = (UILabel *)[cell viewWithTag:1];
> 
>     nameLabel.text = book.name;
> 
>     returncell;
> 
> }

cell中的按钮添加点击事件

通过点击事件点的位置,确定cell的索引:

> // 得到触摸事件对象---> 得到触摸点 --->得到触摸点在UITableView中的位置 ---> 得到触摸点在UITableView中的行号
> 
> - (void)collectBook:(UIButton*) btn event:(UIEvent *)event
> 
> {
> 
>     //NSLog(@"----%@",
> 
> event);
> 
>     UITableView *tableView = (UITableView *)self.view;
> 
>     // 获取所有的触摸点(UITouch对象,如果是单点触碰,就只有1个UITouch)
> 
>     NSSet *touches = [eventallTouches];
> 
>     // 一个UITouch对象对应一根手指
> 
>     UITouch *touch = [touchesanyObject];
> 
>     // 获取触摸点在UITableView上面的的位置
> 
>     CGPointposition = [touch locationInView:tableView];
> 
>     // 根据触摸位置 得到 对应的行号
> 
>     NSIndexPath*indexPath = [tableView indexPathForRowAtPoint:position];
> 
>     //NSLog(@"%d",
> 
> indexPath.row);
> 
>     Book *book =self.books[indexPath.row];
> 
>     NSLog(@"%@", book.name);
> 
> }
> 

Cell属性封装:

根据tag找控件(android根据id找控件),tag太多不好管理,效率不高,如果控件太多代码量大:

定义一个类继承UITableViewCell,xid指向这个类,子控件作为此类的属性即可,创建Cell时用这个类接受:

[图片上传失败...(image-1625e9-1542002718991)]

10.9 九宫格

iOS中没有Android中的GridView,九宫格是由UITableView实现的,自定义Cell,每一行Cell中放入numClunk(多少列) 个按钮。

10.10 qq联系人列表

iOS中没有Android中的ExpandListView,如果需要实现分组展开合并功能,只需要控制返回那个分组返回的行数,行数为0就是合并了。

自定义分组标题

> #pragma mark 第section组对应的标题
> 
> - (UIView *)tableView:(UITableView *)tableView
> 
> viewForHeaderInSection:(NSInteger)section
> 
> {
> 
>     HeaderView *titleView =[HeaderView buttonWithType:UIButtonTypeCustom];
> 
>     // 设置标题内容
> 
>     NSDictionary *dict = self.allFriends[section];
> 
>     [titleView setTitle:dict[@"group"] forState:UIControlStateNormal];
> 
>     // 设置标题颜色
> 
>     [titleView setTitleColor:[UIColorblackColor] forState:UIControlStateNormal];
> 
>     // 设置背景颜色
> 
>     [titleView setBackgroundColor:[UIColorgrayColor]];
> 
>     // 设置按钮的tag为组号
> 
>     titleView.tag= section;
> 
>     // 监听标题点击
> 
>     [titleView addTarget:self action:@selector(titleClick:)forControlEvents:UIControlEventTouchUpInside];
> 
>     // 取出第section组的状态
> 
>     int result = [self.status[@(section)]intValue];
> 
>     // 对状态进行取反
> 
>     if (result == 0) {
> 
>         titleView.imageView.transform= CGAffineTransformIdentity;
> 
>     }else{
> 
>         titleView.imageView.transform= CGAffineTransformMakeRotation(M_PI_2);
> 
>     }
> 
>     returntitleView;
> 
> }
> 

合并展开分组

> #pragma mark - 监听标题点击
> 
> - (void)titleClick:(UIButton*)btn {
> 
>     // 取出标题按钮对应的组号
> 
>     int section = btn.tag;
> 
>     // 取出第section组的状态
> 
>     int result = [self.status[@(section)]intValue];
> 
>     // 对状态进行取反
> 
>     if (result == 0) {
> 
>         [self.status setObject:@1forKey:@(section)];
> 
>     }else{
> 
>         [self.status setObject:@0forKey:@(section)];
> 
>     }
> 
>     // 刷新数据(会重新给数据源发送消息)
> 
>     [self.tableViewreloadData];
> 
> }
> 
> //- (NSString
> 
> *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
> 
> //{
> 
> //    // 1.获取这组对应的字典数据
> 
> //    NSDictionary *dict =self.allFriends[section];
> 
> //   
> 
> //    return dict[@"group"];
> 
> //}
> 
> #pragma mark 每一组中有多少行数据
> 
> - (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
> 
> {
> 
>     // 取出第section组对应的状态
> 
>     int result = [self.status[@(section)]intValue];
> 
>     if (result == 0) { // 合并状态
> 
>         return 0;
> 
>     }else { // 展开状态
> 
>         // 1.先获取这组对应的数据
> 
>         NSDictionary *group = self.allFriends[section];
> 
>         // 2.获取这组里面的好友
> 
>         NSArray *friends = group[@"friends"];
> 
>         return friends.count;
> 
>     }
> 
> }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,817评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,329评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,354评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,498评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,600评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,829评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,979评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,722评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,189评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,519评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,654评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,940评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,762评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,993评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,382评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,543评论 2 349

推荐阅读更多精彩内容

  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,699评论 2 59
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,790评论 25 707
  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_X自主阅读 15,969评论 3 119
  • 孩子们开学已经快一个月了,我们六个留校陪读的家长彼此之间也从陌生到熟悉,再到现在成为亲如姐妹其乐融融的一家人。...
    极乐之子阅读 641评论 1 7
  • 今年的年会风格是民国风,下午去看了旗袍。整个试衣服的过程出乎我的意料,140斤的我居然有合适的尺寸,重点是还挑了一...
    彦过留痕阅读 713评论 1 1