一、把刚才计算九宫格的思路再给大家过一遍

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)第四步,就是添加数据吧,第四步就是添加数据

相关链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: