一、把刚才计算九宫格的思路再给大家过一遍
1.现在我们要计算九宫格坐标
1)先把每一个格子,每一个九宫格的大小,先确定了,
在这里先指定宽和高
CGFloat appW = 75;
CGFloat appH = 90;
2)再去计算第一个格子的一些间距,
到上面的间距,marginTop = 30;
再计算出第一个格子距离左边这个间距,marginX ,
marginX = (self.view.frame.size.width - columns * appW ) / (columns + 1 ) ;
这是一个平均值,这个平均值怎么来算,控制器所管理的这个View,减去当前每行上有几个格子,用这个个数,乘以每个格子的宽度,
减完以后,就是把这三个蓝色的距离减去,剩下就是白色的距离,除以每行格子的个数加1,得到的就是我们这个白色的距离,
为了我们后面计算方便,我们这里首先是要定义一个变量,用来保存每行最多有多少个格子,
假如说,我们现在刚好排的齐齐的,如果是13个呢,最下面一行,是不是会多出一个来,
如果是14个呢,多出两个来,如果是15个呢,最下面一行又多出一行来,
3)把这个marginX算出来,marginTop算出来,每一个格子的大小确定以后,接下来,就再假设一个marginY,
假设每行与每行之间这个间距,和X的间距是相等的,
marginY = marginX;
4)把这个算出来以后,紧接着,我们就要去计算每一个格子的X和Y坐标了,
那么我们刚才通过分析,发现每一个格子的X坐标等于什么:
appX = marginX + (i % columns) * (marginX + appW);
第一个格子的X坐标等于什么,就等于左边这个间距,marginX , 加上0倍的这个格子的宽度,加上marginX这个距离的和,
第二个格子的X坐标等于什么,就等于左边这个间距,marginX,加上1倍的这个格子的宽度,加上marginX这个距离的和,
第三个格子的X坐标等于什么,就等于左边这个间距,marginX,加上2倍的这个格子的宽度,加上marginX这个距离的和,
第一个这是0,
第二个这是1,
第三个这是2,
也就是说,第一列的这4个格子,是不是都应该是0,
第二列的这4个格子,是不是都应该是1,
第三列的这4个格子,是不是都应该是2,
它们所在列的索引是不是就是0、1、2啊
凡是索引为2的,它的X都是marginX + 两倍的这个宽度appW + 和marginX的和,
凡是索引为1的,它的X都是marginX + 1倍的这个宽度appW + 和marginX的和,
那么,我们首先要计算出,每一个单元格,它的这个列索引,0、1、2,
怎么去计算每个单元格的列索引,
就使用单元格它自己的索引i,除以当前你每行有几个单元格,取余,这个值,就是它的列索引,i%3=?
有了列索引之后,用列索引,乘以你这个宽度appW + marginX的和,然后再加上前面这个marginX,
这就是每一个单元格的X值,
5)每一个这个单元格的Y值,
这个Y值,就等于我们这个marginTop,第一行是不是都是marginTop啊,
第一行,索引是0,
第二行,索引是1,
第三行,索引是2,
第四行,索引是3,
每一行的索引算出来,
第一行,就是marginTop + 0倍的(这个高度appH + marginY的和),
0倍的,相当于没有,加上marginTop,
第二行,索引为1,就是这个marginTop + 1倍的(这个高度appH + marginY的和),
第三行,索引为2,就是这个marginTop + 2倍的(这个高度appH + marginY的和),
第四行,索引为3,就是这个marginTop + 3倍的(这个高度appH + marginY的和),
这样的话,我们这个X和Y,是不是能算出来了,
6)也就是核心点:
第一,先确定每一个应用的大小,
第二,计算我们的间距,
第三,计算我们每一个单元格所在的行索引和列索引,
把这几个都算完以后,有了这几个作为前提条件,
我们就可以在循环里面,去计算每一个应用的X和Y的值,
//计算每个单元格所在的列索引
int colIdx = i % columns;
//计算每个单元格所在的行索引
int rowIdx = i / columns;
CGFloat appX = marginX + colIdx * (appW + marginX);
CGFloat appY = marginTop + rowIdx * (appH + marginY);
把这个值计算出来以后,接下来,我们再运行的时候,这个应用就可以正常显示了,
8)计算步骤:
-1 . 确定每个app的宽和高
-2. 计算marginX,marginY,marginTop,
-3. 计算每个app所在的行索引、列索引,
-4. 根据当前app的行索引和列索引计算appX和appY,
计算完了以后,设置frame,就显示出来了,
二、相这个View里面加子控件,
1.分析一下,每个View里面,有哪些子控件,
2.每一个View里面,是不是都有一个图片框,还有一个Label,还有一个下载这个按钮,
是不是都有这3个控件,
所以说,接下来我们就要向这个UIView里面,增加这3个子控件,
那么增加这3个子控件的时候,这里怎么来给它加,
3.我们先简化、简化、再简化,
先不要关心每一个子控件里面显示的数据,先别管数据,
先把子控件加进去,
加进去,我们这里怎么排列呢,
假设这是一个UIView,那个框框,
首先,我们在它的最上方,这里,加这么一个图片,
当然这个图片没有必要和它一样大,你可以和它加的小点儿,
比如说,它整个的宽度是不是75,你这个图片的宽度,可以是45,
45,然后让它在这个View里面,居中显示吧,
请问,整个这个View的宽度是75,里面这个图片框的宽度是45,它怎么居中,
75 - 45 是不是剩下30,30 / 2 是不是它距离左边的距离,
Y值呢,它就紧贴住这个上边缘,是不是Y值等于0啊,
这样的话,第一个是不是ok了,
3.然后,再来一个Label,
这个Label的Y值,紧贴住这个图片框的底边缘,
相当于Label的Y值,就等于这个图片框的高度,
因为这个图片框是不是紧贴住这个内边缘了,
所以说,它的高度,是不是就是Label的Y值,
然后呢,让Label的宽度,和整个这个View的宽度一样,
这样的话,Label是不是就是占满整个的宽度,
然后,设置Label里面的文字,居中显示,
是不是文字就居中了,
4)然后,下面再来一个按钮,
这个按钮的宽度,和我们这个图片框的宽度是一样的,
它这个宽度是45,
它的宽度是45,用总的宽度75 - 45 ,除以2,
它是不是也可以居中显示啊,
这样的话,里面再显示文字,
5)整体排列就是按照这种方式来排,
接下来,我们就按照这种思路,先把这几个子控件,给它添加进去,
为了我们能看到添加进去的子控件,
我把加到这个View里面的每一个子控件,给它设置一个背景色,
这样的话,我们是不是能看到了,
2.接下来,我们来写代码
首先,在这个循环里,我们创建一个空白的View,
for(int i = 0 ; i < self.apps.count; i++){
//1.创建每个应用(UIView)
UIView *appView = [[UIView alloc] init];
//2.设置appView的属性
//2.1 设置appView的背景色
appView.backgroundColor = [UIColor blueColor];
//2.2 设置appView的frame属性
//计算每个单元格所在的列索引
int colIdx = i % columns;
//计算每个单元格所在的行索引
int rowIdx = i / columns;
CGFloat appX = marginX + colIdx * ( appW + marginX);
CGFloat appY = marginTop + rowIdx * (appH + marginY);
appView.frame = CGRectMake(appX,appY,appW,appH);
//3.将appView加到self.view(控制器所管理的那个view)
[self.view addSubview:appView];
}
我们在这个循环里面,第一步,创建一个空白的View,
第二步,设置这个View的一些属性,
设置属性里面就包含,一个是设置它的背景色,一个是设置它的坐标吧,
第三步,把这个View加到我们这个大View里面,
第四步,向这个UIView中增加子控件,
//4.向UIView中增加子控件,
//增加子控件,第一个是要增加一个图片框,
//根据我们的分析,因为它只显示图片,不需要单击,
//所以第一个是一个图片框,
//4.1 增加一个图片框,
//4.2 增加一个Label(标签)
//4.3 增加一个按钮(UIButton)
//增加一个图片框,图片框是哪个类型,
UIImageView *imgViewIcon = [[UIImageView alloc] init];
来个imgView头像,可以吧,
这样是不是创建了一个空的图片框了吧,
为了能看到这个图片框,我们是不是要给这个图片框一个背景色,
imgViewIcon.backgroundColor = [UIColor yellowColor];
接下来,我们要能看到这个图片框,是不是得给这个图片框设置一个frame吧,
设置frame,我们就先把坐标设置出来,
CGFloat iconW = 45;
CGFloat iconH = 45;
CGFloat iconX =
距离左边,等于什么,是不是等于我们整个这个View的宽度,appView.frame.size.width ,减去它自身的宽度 iconW,然后呢,再除以几,除以2,这样它相对于那个View是不是就居中了,
除以2,是不是也等价于乘以0.5,是不是都一个意思啊,
CGFloat iconX = (appView.frame.size.width - iconW) * 0.5;
然后Y值呢,
CGFloat iconY =
它的Y值,是不是要紧贴这个View的Y值,
所以说它这里,Y值就等于几,0吧,
CGFloat iconY = 0;
这样的话,我们这个图片框的frame,已经处理好了,
接下来,设置它的frame,
imgViewIcon.frame = CGRectMake(iconX,iconY,iconW,iconH);
这样的话,这个图片框是不是搞定了,
运行一下看看,别着急往下写,
看一下,是不是根本看不到,
原因是,你只是创建了这个控件,设置了它的属性,最后还缺一步,添加啊,
//把图片框添加到appView中,
[appView addSubview:imgViewIcon];
这样是不是加进来了,
我们再运行,图片框上来了吗,上来了吧,ok,图片框好了,
别管里面的数据,咱们等会儿再设置数据,
3.然后呢,我们再做第二步,是不是把这个Label也加进去,
怎么把Label加进去呢,还是这几步,
1)创建Label:UILabel *lblName
是不是设置标题这个Label吧,
UILabel *lblName = [[UILabel alloc] init ] ;
2)设置背景色,
lblName.backgroundColor = [UIColor redColor];
3)设置frame
frame怎么设置,先把这几个变量整理好吧,
CGFloat nameW = appView.frame.size.width;
来个它的宽度等于谁,是不是等于咱们这个View的宽度啊,
CGFloat nameH = 20;
它的高度呢,假设等于20吧,
CGFloat nameY = iconH;
它的Y值等于多少,是不是等于这个图片框的高度,
CGFloat nameX = 0;
它的X值等于多少,是不是紧贴住我们这个内边框吧,
因为它的宽度,和我们这个View的宽度是一样的嘛,
lblName.frame = CGRectMake(nameX,nameY,nameW,nameH);
//添加到appView中
[appView addSubview:lblName];
好,这样的话,是不是这几个都加进来了,
运行一下,看到了吧,
8)接着,我们是不是要添加下面的按钮啊,
//4.3 增加一个按钮(UIButton)
UIButton *btnDownload = [[UIButton alloc] init];
//设置背景色
btnDownload.backgroundColor = [UIColor greenColor];
//设置frame,设置frame,先确定它的大、小、高、宽吧
CGFloat btnW =
//宽等于多少,刚才是不是假设这个按钮的宽和上面的图片一样宽啊,
CGFloat btnW = iconW;
//高等于多少,高是不是就可以给它假设一个20啊,
CGFloat btnH = 20;
//X,它距离左边距离就等于什么,就等于图片框距离左边的距离
CGFloat btnX = iconX;
//Y,它的Y值等于多少,等于这个Label的Y值加上Label的高度,这是不是就是它的Y值啊,
CGFloat btnY = nameY + nameH;
//添加到appView中
[appView addSubview:btnDownload];
9)这是一种写法,或者说,我们给大家介绍另外一个概念,是什么概念呢,有这么一个东西:
假如说这是一个容器,这个容器里有一个子控件,有这么一个子控件,这个子控件的X值是哪里,
这个子控件左上角那一点距离左边的距离,就是它的X值,
这个子控件左上角那一点距离顶部的距离,就是它的Y值,
这个子控件左下角那一点的X值,和左上角那一点的X值,是一样的,
这个子控件左下角那一点的Y值,等于多少,等于这个子控件左上角的Y值,加上它自身的高度,
你算左下角那一点的Y值,可以用它的Y值 + 它的高度,这是一种算法,
或者说,你可以算出这个元素的最大的Y值,就是指的它,左下角那点的Y值,
这个控件的Y值,就是左上角那一点的Y值,
这个控件最大的Y值,就是指的左下角那一点的Y值,
这个控件的X值,就是左上角那一点的X值,
这个控件最大的X值,就是最右边那两个点的X值,
X的值 + 它的宽度,就表示它最大的X值,
Y的值 + 它的高度,就表示它最大的Y值,
所以,继续写刚才的代码:
//设置frame
CGFloat btnW = iconW;
CGFloat btnH = 20;
CGFloat btnX = iconX;
CGFloat btnY = nameY + nameH;
//添加到appView中,
[appView addSubview:btnDownload];
//补充:控件的最大的Y值 = 控件的Y值 + 控件的高度,
//控件的最大的X值 = 控件的X值 + 控件的宽度,
CGFloat btnY = nameY + nameH;
//这地方,刚好是控件的Y值 +控件的高度,是不是刚好是控件的最大的Y值啊,
//所以这个地方,我们也可以用另外一种方法来计算:
//就是,获取控件的最大的Y值,
//这个怎么计算呢,有一个方法叫做CGFloat CGRectGetMaxY(CGRect rect)
CGFloat btnY = CGRectGetMaxY(CGRect rect);
//这是不是要传一个Rect类型,谁是Rect类型,
//我们这里要计算的是谁,是不是btnY的Y值,这个btnY的Y值,就等于Label的最大的Y值,
//其实就是Label的Y值 + Label的高度,其实就是Label的最大的Y值,
//所以说,我们这里传参的时候,其实要个CGRect类型,其实刚好就等于这个Label的frame,它是不是刚好就是一个CGRect类型,
//把lblName.frame传进来,这个方法就会计算出这个frame中的最大的Y值,返回给这个btnY,其实就是它的Y值 + 它的高度,
所以说,以后需要用到这个Y值 + 高度的时候,可以直接获取这个控件的最大的Y值,就等于它的Y值 + 它的高度,
获取这个控件最大的X值,就等于它的X值 + 它的宽度,
10)算好这4个值之后,接下里,设置UIButton的frame,
btnDownload.frame = CGRectMake(btnX,btnY,btnW,btnH);
这样的话,这个按钮是不是也上来了,来,再运行一下:
这些内容都上来了,也就是说,现在控件都已经全白上来了,你觉得接下来该干什么了,是不是该添加数据了,所以说,咱们现在回忆一下,咱们做这个九宫格的步骤,是干什么:
1)第一步,是不是创建九宫格,
2)第二步,是不是算坐标,
3)第三步,是不是向九宫格中添加子控件,
4)第四步,就是添加数据吧,第四步就是添加数据
相关链接
发表评论