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(中点的位置)
只要继承了UIControl就能简单处理一些事件(点击事件、值改变事件);
继承了UIControl的子类有:UIButton、UISlider、UISwitch、UIDatePicker等等;
当需要监听一个子控件的事件的时候,先要看它是否继承自UIControl,再看它内部是否有delegate属性(代理);
常用属性:
enable
是否处理事
contentVerticalAlignment
内容在垂直方向上的排布方式
contentHorizontalAlignment
内容在水平方向上的排布方式
常用方法:
addTarget
添加事件监听器(参数:监听器对象、事件触发回调方法、事件类型)
removeTarget
删除事件监听器
allTargets
获取所有的监听器对象集合
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
self.imageView.image = [UIImage imageNamed:@“icon.png"];
设置图片展示模式(android ImageView 的scaleType属性):
@property (weak, nonatomic) IBOutlet UISlider *slider;
//设置最大值
self.slider.maximumValue = self.imageDate.count;
//设置最小值
self.slider.minimumValue = 1;
//设置当前值
self.slider.value = 1;
常用属性:
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:self action:@selector(directionBtnClick:) forControlEvents:UIControlEventTouchUpInside];
//根据按钮的tag获取子控件
UIButton*orangeBtn = [self.viewviewWithTag:kOrangeTag];
CGPoint center = orangeBtn.center;
staticCGFloatDELETE =50;
center.y += DELETE;
//重新赋值按钮的中点
orangeBtn.center= center;
根据系统自带样式类型创建
//创建一个加号的按钮
UIButton *btn = [UIButton buttonWithType:UIButtonTypeContactAdd];
btn.center = CGPointMake(100, 100);
常用属性:
text
显示文本内容
textColor
文字颜色
font
字体
shadowColor
文字的阴影颜色
shadowOffset
阴影的偏差距离(width水平方向的偏差距离,整数右边;height垂直方向上的偏差距离,正数下边)
textAlignment
设置文字的排列方式(偏左、偏右、居中)
numberOfLines
允许文字最多几行(默认1,如果是0,自动换行)
#pragma mark 开关值改变监听
-(IBAction)switchChanged:(UISwitch *)sender {
NSLog(@"开关值%d", sender.isOn);
self.view.backgroundColor = sender.isOn?[UIColor darkGrayColor]:[UIColor whiteColor];
}
-(void) viewDidLoad{
[super viewDidLoad];
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];
}
设置数据源和代理(监听)为控制器,控制器遵循数据源河代理的协议,重写协议的方法:
#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;
}
UIPageControl 请见:分页显示
当子控件内容太多或者子控件太大显示不全时,用UIScrollView实现滚动
常用属性
CGPoint contentOffset
UIScrollView当前滚动到哪个位置了(相对于内容左上角的坐标)
CGSize contentSize
UIScrollView的滚动范围(内容的尺寸)
UIEdgeInsets contentInset
这个属性可以在四周增加滚动范围
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;
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
#define kCount 5
@interface ViewController ()
@property (nonatomic, weak) UIPageControl *_pageControl;
@property (nonatomic, weak) UIScrollView *_scrollView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
for(int i = 0; i
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
// 返回条目高度(可以根据不同的行号返回不同的高度)
- (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
@interface ViewController ()
@property (nonatomic, strong) NSArray *gd;
@property (nonatomic, strong) NSArray *hn;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
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;
return cell;
}
#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:self cancelButtonTitle:@"取消" 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.tableView reloadRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationLeft];
}
}
@end
数据源返回分组数量的方法返回值为1就能实现单组效果
UITableViewCell系统样式:
条目右边箭头样式:
#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 = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
}
// 3.覆盖数据
cell.textLabel.text = [NSString stringWithFormat:@" fdsfdsf-%d", indexPath.row];
return cell;
}
// 开启编辑模式
//self.tableView.editing = YES;
//[self.tableView setEditing:YES];
// 带有动画效果
[self.tableView setEditing:! edt animated:YES];
下面方法的返回值决定编辑模式是添加还是删除:
#pragma mark - 代理方法
#pragma mark 当tableview开启编辑模式就会调用
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
//return indexPath.row%2 ? UITableViewCellEditingStyleDelete : UITableViewCellEditingStyleInsert;
return tableView.tag;
}
实现数据源的方法删除或添加数据:
#pragma mark 提交编辑操作(点击了"删除"或者"+"按钮)时调用
// 实现了这个方法,就有左划删除功能
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
//NSLog(@"------commit---%d", indexPath.row);
if (editingStyle == UITableViewCellEditingStyleDelete) {
// 删除
// 1.更改数据(删除本行的数据)
[self.mydata removeObjectAtIndex:indexPath.row];
// 2.刷新UI界面
//[tableView reloadData];
[tableView deleteRowsAtIndexPaths:@[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];
[tableView insertRowsAtIndexPaths:@[newPath] withRowAnimation:UITableViewRowAnimationTop];
}
}
#pragma mark 如果实现了这个方法, 就会有排序功能
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
// 取出即将要删除的数据
NSString *data = self.mydata[sourceIndexPath.row];
// 删除需要移动的那一行
[self.mydata removeObject:data];
// 插入之前删除的数据
[self.mydata insertObject:data atIndex:destinationIndexPath.row];
}
[tableView insertRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationTop];
[tableView deleteRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationTop]
[tableView reloadRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationTop]
[tableView reloadData]
#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 = [NSBundle mainBundle];
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;
return cell;
}
// 得到触摸事件对象 ---> 得到触摸点 ---> 得到触摸点在UITableView中的位置 ---> 得到触摸点在UITableView中的行号
- (void)collectBook:(UIButton *) btn event:(UIEvent *)event
{
//NSLog(@"----%@", event);
UITableView *tableView = (UITableView *)self.view;
// 获取所有的触摸点(UITouch对象,如果是单点触碰,就只有1个UITouch)
NSSet *touches = [event allTouches];
// 一个UITouch对象对应一根手指
UITouch *touch = [touches anyObject];
// 获取触摸点在UITableView上面的的位置
CGPoint position = [touch locationInView:tableView];
// 根据触摸位置 得到 对应的行号
NSIndexPath *indexPath = [tableView indexPathForRowAtPoint:position];
//NSLog(@"%d", indexPath.row);
Book *book = self.books[indexPath.row];
NSLog(@"%@", book.name);
}
iOS中没有Android中的GridView,九宫格是由UITableView实现的,自定义Cell,每一行Cell中放入numClunk(多少列) 个按钮。
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:[UIColor blackColor] forState:UIControlStateNormal];
// 设置背景颜色
[titleView setBackgroundColor:[UIColor grayColor]];
// 设置按钮的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);
}
return titleView;
}
#pragma mark - 监听标题点击
- (void)titleClick:(UIButton *)btn {
// 取出标题按钮对应的组号
int section = btn.tag;
// 取出第section组的状态
int result = [self.status[@(section)] intValue];
// 对状态进行取反
if (result == 0) {
[self.status setObject:@1 forKey:@(section)];
} else {
[self.status setObject:@0 forKey:@(section)];
}
// 刷新数据(会重新给数据源发送消息)
[self.tableView reloadData];
}
//- (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;
}
}