闲聊
现在是7月30日夜间10点15分,闲聊这里改了又删删了又改,不知道说什么,在一次项目开发任务中,我遇到了一个在 tableView 屏幕视图下添加一个按钮,使 tableView 在上下拉动的时候 button 可以不受它上下拉动的影响,保持独立固定的问题,它要么不显示,要么就跟着一起被拖动,要么就是显示的位置和样式和自己的期望不一致。
这几个问题花了我好几天的时间,从周导、Tinker 的提示, baidu、google、bing、stackOverflow 获得的大量的信息,用另外一个 .m 文件来包含它,让它显示在 tableView 之上,虽然解决了显示的问题,但是依然觉得不够完美,强迫症在作怪,我想让他放在一个文件里面,在一个文件里面自由定制它们。0.0
这促使了我更进一步学习屏幕布局。
开始
我觉得一开始非常有必要的了解屏幕坐标体系。
而这一切就藏在 view 的两个方法(其实还有个 center ,暂时就这两个参数吧):
1 2 3 4 5 6 7 |
-(CGRect)frame{ return CGRectMake(self.frame.origin.x,self.frame.origin.y,self.frame.size.width,self.frame.size.height); } -(CGRect)bounds{ return CGRectMake(0,0,self.frame.size.width,self.frame.size.height); } |
frame和bounds
frame 指的是 当前的 view 在父 view 的坐标大小,而 bounds 指的是当前自己的 view 坐标大小。
我目前对他们的理解是:他们的区别仅仅在于坐标值不同。
CGRectMake()
通常我们在初始化一个 view 的时候会常见一个函数:
1 2 |
CGRectMake ( CGFloat x, CGFloat y, CGFloat width, CGFloat height ); |
苹果官方文档介绍的很直白,值得留意的是,它前面的两个参数: CGFloat x, CGFloat y, 参考上面介绍 frame和bounds 的图,x, y 的原坐标 (0,0) 是从左上角开始的。
例如初始化一个坐标x,y 都为50,宽度和高度都为 200 的 View;
1 2 |
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0,0,200,200); |
背景基本就这些
实现
下面通过代码来解析。
如图,这个 demo 主要实现在有 tableView 情况下,如何在屏幕底部固定一个按钮,当然了,也可以很多个按钮。。
直观上看,这个 demo 包含了三个 view , 分别是 导航栏、tableView 和 button ,这三个都继承于 UIView ,它们的宽度相同,区别个高度,位置坐标。别问我为什么还有一个导航栏,我喜欢怎么加就怎么加?。 我的要求是,可以自由对他们进行调整,就算有一个被隐藏了,看不见,也不影响其他 view 的在屏幕中的坐标位置以及大小。简单说,就是精准布局。
上代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
// // ViewController.m // demo2 // // Created by Cookies-J on 30/7/2016. // Copyright © 2016年 J lam. All rights reserved. // #import "ViewController.h" @interface ViewController () <UITableViewDelegate, UITableViewDataSource> { // 先定义好三个view,分别是导航栏,tableview,和button。 UINavigationBar *navBar; UITableView *myTableView; UIButton *button; } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // 设置self.View 的背景颜色,方便后面 [self.view setBackgroundColor:[UIColor redColor]]; // 初始化这三个 view 的位置大小 [self initView]; // 加载这三个view的内容 [self setNavBar]; [self setTableView]; [self setbuttomButton]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - 设置view -(void) initView { // 设置导航栏的高度为80 navBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 80.f)]; // tableView这里设置它的高度,和 y 轴位置。 // y 轴的位置也就通过获取导航栏高度而得。 // tablview 高度的意义有两点,1:给底部的 button 预留空间,方便计算 button 的 y 轴位置;2:设置底部的 button 之后,不至于遮挡到数据。 myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, navBar.frame.size.height, self.view.frame.size.width, self.view.frame.size.height - 130.f) style:UITableViewStylePlain]; button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; // 接下来 button 的位置就很简单了,导航栏的高度加上 tableview 的高度就是它的位置,高度为 50 button.frame = CGRectMake(0, navBar.frame.size.height + myTableView.frame.size.height, self.view.frame.size.width, 50.0); } //设置导航栏元素 -(void) setNavBar { // 设置导航栏背景颜色 [[UINavigationBar appearance] setBarTintColor:[UIColor cyanColor]]; UINavigationItem *navTitle = [[UINavigationItem alloc] init]; [navTitle setTitle:@"固定底部按钮"]; navBar.translucent = NO; [navBar pushNavigationItem:navTitle animated:YES]; [self.view addSubview:navBar]; } //设置 tableview 元素 -(void) setTableView { myTableView.delegate = self; myTableView.dataSource = self; [self.view addSubview:myTableView]; } //设置 button 元素 -(void) setbuttomButton { [button setTitle:@"显示 view 高度" forState:UIControlStateNormal]; [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; button.layer.cornerRadius = 0.0; button.layer.borderWidth = 0.0; button.backgroundColor = [UIColor orangeColor]; [button addTarget:self action:@selector(getViewHeight) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:button]; } #pragma mark - tableview dataSource,delegate -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 50; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *ident = @"myCell"; UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:ident]; NSInteger i = 0; for (; i < 50; i++) { cell.textLabel.text = @"My heart is with you, forever and ever.."; } return cell; } #pragma mark -button 的方法 -(void) getViewHeight { NSLog(@"屏幕的高度 %.2f",self.view.frame.size.height); NSLog(@"导航栏的高度 %.2f, 宽度(Bounds): %.2f", navBar.frame.size.height, navBar.bounds.size.width); NSLog(@" tableView 的高度 %.2f", myTableView.frame.size.height); NSLog(@"底部 button 的高度 %.2f", button.frame.size.height); } @end |
比如你现在注释掉第 34 行;
1 2 |
// [self setTableView]; |
run 一下:
又或者注释 33 和 35 行
1 2 3 4 |
// [self setNavBar]; [self setTableView]; // [self setbuttomButton]; |
So,它不管哪个模块被隐藏了,只要能理解 view 这frame、bounds、CGRectMake,这三个东西,我个人认为从此布局就简单多了。??
用 masonry 实现
这个明天发。。
总结
因为专注了,所以细节很深刻,欢迎指正。