【动态生成“答案”按钮 Objective-C语言】

一、之前我们实现了“下一题”功能,和“大图”功能,接下里,我们把前面的总结一下:

之前实现的“下一题”功能,和“大图”功能的步骤:

1.新建项目

2.拷贝素材

3.懒加载模型数据.

4.通过storyboard设计"超级猜图"的上半部分界面。

1> 一个UIImageView做背景

2> 分析界面上的控件应该使用什么控件

**注意按钮点击没有高亮效果取消: highlighted adjust image属性

5.实现状态栏白色文字效果。

6.实现点击"下一题"功能。

* 使用一个index属性来记录当前显示的题目的索引。

* 点击"下一题"的时候,从数组中获取对应的题目,并显示到对应的界面控件上。

* 解决最后一题之后再次点击"下一题"索引越界问题。sender. enabled = (self.index != self.questions.count - 1);

** 注意:设置按钮图片的时候,通过调用setImage: forState: UIControlStateNormal]方法来设置。

7.在viewDidLoad中,初始化第一个问题 (显示第一个问题到界面上) 。

* 设置self. index = -1

* 手动调用"下一题"按钮的点击事件

8.实现"查看大图"功能。

** 点击右侧"大图"按钮,显示大图

* 实现思路(步骤) :

1> 添加一个“阴影”按钮,因为该“阴影”要实现点击,所以用“按钮”

2> 然后再把“头像按钮"显示在”阴影“上面。

3> 通过动画的方式改变"头像按钮"的frame(位置和尺寸),变成大图效果。

** 注意:如果图片没有变大,检查是否没有取消"自动布局(Auto Layout)"

** 点击"遮罩阴影”,回到小图

1> 通过动画慢慢将"遮罩阴影”的透明度变为0

2> 通过动画慢慢将"头像图片的frame修改为原来的位置

3> 在动画执行完毕后,移除"遮罩阴影”

** 点击图片本身显示大图,再次点击图片本身显示小图

9.动态生成"答案按钮"。

*思路:

0> 在点击"下一题"按钮中实现该功能

1> 创建一个UIView来存放所有的"答案按钮"

2> 根据每个问题的答案的文字个数来创建按钮

3> 每次创建按钮之前,先把旧的按钮都删除

4> 指定每个"答案按钮”的尺寸和中间的margin,然后计算第一个按钮的x值(marginLeft) 。

5> 在循环中,计算每个按钮的x值(y值都是0)。

二、把这个“下一题”功能,和“大图”功能,实现以后,接下来,我们就要开始实现动态生成“答案按钮”了,接下来,就实现动态生成“答案按钮”,

1.好,接下来,我们就给大家做这个“答案按钮”,生成“答案按钮”,

那么,我们还是先思考一下,这个动态生成“答案按钮”,该怎么实现,好,首先,实现的思路就是这样的,来,我们先看这个示例程序吧,我们这样,嗯,我们把这些,这些就是放答案的按钮吧,

答案按钮

中间这三个,就是“答案按钮”吧,

下面这些,是放这个待选项的按钮,下面是放待选项的按钮,我们把这个红色的这个把它作为一个View,这是一个View,

首先,创建一个View,放在这儿,下面给它创建一个View,放在这儿,然后呢,创建若干个按钮,动态创建若干个按钮,放到这个View里面,注意,这是创建几个按钮,取决于什么,取决于当前答案的文字的个数吧,所以说,我们这里要根据当前这个题目的答案的文字个数,是什么,来动态创建这些按钮,然后设置按钮的背景图是一个什么颜色,白色吧,然后默认状态下什么颜色,点击状态下什么颜色,然后把它坐标排好,这样的话,我们这儿是不是实现了,

实现这个以后,然后我们再根据当前这个题目的待选文字的个数,是不是实现下面这几个按钮,是不是这样的,好,我问大家,现在生成这个答案按钮,这个代码应该写在哪里,

生成这几个答案按钮,这几个按钮,这个代码应该写在哪里,生成这几个答案按钮的代码,应该写在哪里,肯定是控制器里面,这个我知道,在控制器里面,在哪里,是不是点击“下一题”的时候啊,当你点击“下一题”的时候,要把“下一题”的数据填上,同时要根据当前这个题目的答案的个数,文字个数,是不是要显示这几个“答案按钮”啊,同时,再根据当前这个题目的待选答案的文字个数,动态生成待选答案的按钮,

所以说,当你点击“下一题”的时候,是不是要做这一系列操作,明白了吗,好,所以我们先把这两个View拽过来,

拽一个View过来

然后,再设置它的坐标,宽和高,宽给个多少,375吧,是不是和屏幕一样宽,距离左边的距离,左边是x,x给个0吧,y就是255吧,高给个35吧,

然后,它的背景色,为了我们等会能看到,因为按钮也是白色,背景色是白色,看不出来了,把这个背景色改一下,大家喜欢什么颜色,黄色,好,Background属性给个黄色,

然后接下来,选中左边控件列表里的“View”,command + C,command + V,复制一个,Y坐标,来个317吧,它距离上边的距离,来个317吧,然后呢,它的高度呢,注意它的Y值是多少,317吧,整个屏幕的高度是667,拿667-317等于多少,350吧,这样它的高度,就是多少,350吧,这样子,它的高度,是不是它刚好是填满整个屏幕的下边啊,

待选答案

然后呢,我们给它的背景色,给它来一个,蓝色吧,Background属性,给它来个蓝色,

这样的话,我们是不是这两个View都有了,这两个View就都有了,

2.好,这两个View好了以后,那么接下来,当点击“下一题”的时候,需要向这两个View里面动态创建子控件,

既然要向这两个View里面,动态创建子控件,所以说,我们是不是要通过一个什么,要通过两个属性,是不是来引用这两个View,

这样的话,等会儿是不是就可以向这两个View里面创建子控件了,通过两个属性来引用,所以说,既然要通过属性来引用,所以说,就想到了什么,拖线吧,

先在控件列表中,修改一下这两个View的名称,放置“答案按钮”的这个View,给它来个什么名称呢,answerView吧,下面这个是“待选项”,名字给它来个optionsView,

然后,拖线,按住control键,把这个answerView拖到ViewController.m文件的延展里,设置5个参数:

Connection:Outlet,

Object:View Controller,

Name:answerView,

Type:UIView,

Storage:Weak,

点击Connect按钮,

自动生成了下面这个属性:

@property(nonatomic,weak) IBOutlet UIView *answerView;

然后,是这个optionsView,拖线,设置5个参数:

Connection:Outlet,

Object:View Controller,

Name:optionisView,

Type:UIView,

Storage:Weak,

点击Connect按钮,

自动生成了下面这个属性:

这个是不是用来放答案的View啊,用来放待选答案的View:

@property(nonatomic,weak)IBOutlet UIView *optionsView;

当这两个View没有问题以后,接下来,我们就要在单击“下一题”,这个“下一题”,这个事件当中,我们是不是就要,根据当前这个题目的答案的文字个数,动态创建按钮了,好,找到“下一题”,

如果ViewController.m文件里面的方法太多,找不到的话,可以从方法的下拉列表里找:

方法列表

好,是不是这个- nextQuestion,啊

这是我们点击“下一题”吧,

//下一题

- (void)nextQuestion{

//1.让索引++

self.index++;

//2.根据索引获取当前的模型数据

TestQuestion *model = self.questions[self.index];

//3.把模型数据设置到界面对应的控件上

self.lblIndex.text = [NSString stringWithFormat:@“%d/%ld”,(self.index+1),self.questions.count];

self.lblTitle.text = model.title;

[self.btnIcon setImage:[UIImage imageNamed:model.icon] forState:UIControlStateNormal];

//4.设置到达最后一题以后,禁用“下一题”按钮

self.btnNext.enabled = (self.index != self.questions.count - 1);

}

这是我们点击“下一题”,在这里面,

1)第一步,让索引++,

2)第二步,获取模型数据,

3)第三步,根据模型数据,填充我们的控件的数据,

4)第四步,设置这个按钮是否禁用,

5)第五步,动态创建“答案按钮”

在这个里面,我们要做这么几步事情,

1)第一步,先获取当前这个题目的答案这个文字吧,然后呢,再根据这个答案文字的个数,是不是循环,创建按钮,怎么写,

//5.动态创建“答案按钮”

//5.1 获取当前答案的文字的个数

//所以就是,当前这个模型,这个模型,是不是当前这个问题,这个模型啊,当前这个模型里面,有一个叫做什么的东西,answer吧,这个东西,这个东西就是当前这个问题的答案,这个答案的具体内容吧,然后呢,有几个答案,就是里面有几个文字,就是循环几次吧,就是循环几次啊,就是循环几次,所以说,我们就这么做,我们能把这个答案的文字内容直接显示上来吗,答案不能显示吧,是不是不要那个答案的文字内容啊,只要它的文字个数,我们就可以,这里可以拿一个NSInteger,

NSInteger len = model.answer.length;

//这个model.answer.length,是不是获取答案里面的文字的个数啊,

//5.2 循环创建答案按钮,有几个文字就创建几个按钮

//怎么写,这里就可以使用for循环了吧,

for(int i = 0 ; i < len ; i++){

//然后呢,每次是不是有一个答案文字,就创建一个按钮,

//1.创建按钮

UIButton *btnAnswer = [[UIButton alloc] init];

//2.把按钮加到answerView里面去,

[self.answerView addSubview:btnAnswer];

//这个answerView,是不是指的就是我们这里这个黄色的View,

//运行一下,但是这里为什么什么都没看见呢,因为我们是不是压根儿就没有设置按钮的大小、frame、背景色,是不是什么都没有设置啊,

//3.先就设置按钮的背景色图,然后再设置按钮的什么,再设置按钮的frame,把这两个设置好以后,是不是就能看到这个按钮了,好,我们看一下这个示例程序,这个示例程序里面,这个“答案按钮”的默认背景色是不是白色啊,当按下的时候,背景色变成灰色了,所以它有两张背景图,默认是一张背景图,按下的时候,是一张背景图,ok,这个按钮有两张背景图,

//3.1 设置按钮的背景图

//3.2 设置按钮的frame

//然后,它的大小呢,它的这个大小也是35,高和宽都是35,我们看一下,这个图片素材里面,就看图片素材里面,Images.csassets文件夹里面,有一个Btn文件夹,按钮,哪个是按钮的背景图呢注意看看,这个,这就是默认状态下,按钮的背景图,是不是白色背景啊,

//btn_answer,这个是默认状态下的背景图,

//btn_answer_highlighted,当你点击的时候,这个是高亮状态下的背景图,是不是灰色的背景啊,我们这里来设置背景图,

//3.1 设置按钮的背景图

//怎么设置背景图,setBackgroundImage,

[btnAnswer setBackgroundImage:[UIImage imageNamed:@“btn_answer”] forState:UIControlStateNormal];

//好,高亮状态下,怎么设置,

[btnAnswer setBackgroundImage:[UIImage imageNamed:@“btn_answer_highlighted” forSate:UIControlStateHighlighted];

//好,这是设置背景图,背景图设置好以后,接下来,我们就要设置它的frame吧,所以首先,固定好它的大小,

//3.2 设置按钮的frame

CGFloat answerW = 35;

CGFloat answerH = 35;

CGFloat answerY = 我们这个Y值,是多少,来,看一下,

答案按钮

//我们将来这个“答案按钮”,是不是一个一个加到这个View里面了,所以这个按钮,是不是紧贴着上边缘,所以Y值,是多少,0吧,

CGFloat answerY = 0;

//X轴,是不是要动态算一下 ,X值要动态算一下,好,这个X值,怎么算

//来,看一下我们这个X值,怎么算,这个和我们之前的九宫格,是不是稍微有一点点不一样啊,注意看,我们现在最外层这个View,这个黄色的框框,是不是就是我们最外层这个View啊,

最外层这个View

//如果现在我们有3个按钮,它们左边和右边的距离,这两个黄色的箭头,是不是距离是相等的,如果现在有四个,左边和右边的距离,是不是也是相等的,可能中间会宽一些,但是它这四个,距离左边和右边的距离,是不是还是相等的

距离相等

//所以说,首先,我们第一,给定一个按钮的高和宽,第二,再给定一个按钮中间的间距,

//然后我们动态去计算它两边的距离,是不是动态计算两边的距离,那么这个时候,我们来,

//这个动态计算两边的距离,这该怎么算呢,

减掉中间

//我们现在先用总的宽度,减去中间有几个按钮,就减去几个按钮的宽度,再减去中间按钮个数 - 1 的按钮中间的间距,比如说,现在有3个按钮,就是减掉2个间距,减完之后,是不是就把中间这一坨,都减掉了,然后再除以2,是不是就是两边这个距离了,

//所以说,我们首先就是要用这个View的宽度,减去有几个按钮,就是几个按钮的宽度,再减去有几个按钮,就是按钮的个数减1,然后呢,是不是再乘以这间距的个数,

//这样除以2,最终计算出来的,就是两边这个间距了吧,

//好,那么这两边的间距,我们就先给它来一个,

//假设每个按钮之间的间距都是10

//3.2 设置按钮的frame

CGFloat margin = 10;//假设每个按钮之间的间距都是10

CGFloat answerW = 35;

CGFloat answerH = 35;

CGFloat answerY = 0;

//然后呢,我们当前,当前你这个循环,你这个循环,是不是有几次循环,就创建几个按钮啊,

//所以说,我们这些,每个按钮的大小都一样,每个按钮的间距都是10,每个按钮的Y坐标都是0,就是这些可以怎么样,这些可以提取到外面,在循环里面,是不是只要算一下它那个X坐标,就可以了吧,

//计算按钮的X值

CGFloat answerX =

//那么,计算按钮的X值之前,我们是不是还要算一下两边这两个间距啊,

//所以,我们循环之前,还要再来一个,CGFloat marginLeft,这两边这两个间距,就等于什么呢,就等于当前self.answerView.frame.size.width,等于这个总View的宽度,减去谁, 减去是不是有几个按钮,就是减去几个按钮的宽度吧,减去几个按钮的宽度,然后再减去谁,减去按钮的个数 - 1 ,也就是len - 1,这么多的margin,吧,是不是总共的宽度,减去它,然后什么的,再减去它,把它们这一堆都减完了以后,最后怎么样,最后乘以0.5,或者除以2,是不是都可以,最后除以2,这样的话,拿到这个值,这个值是不是就是算出了我们距离左边这个距离,其实也就是距离右边的距离吧,

CGFloat marginLeft = (self.answerView.frame.size.width - (len * answerW) - (len - 1) * margin ) * 0.5;

//然后拿到这个距离以后,第一个按钮的X坐标,就等于这个距离左边的距离吧,就等于这个marginLeft,也就是marginLeft 加上 , 0倍的这个宽度和margin的和吧,

//也就是marginLeft + 0 * (answerW + margin)

//第二个按钮,等于marginLeft + 1 * (answerW + margin)

//第二个按钮,等于marginLeft,加上一倍的这个宽度和margin的和吧,

//第三个按钮,等于marginLeft,加上两倍的这个宽度和margin的和吧,

//第i个按钮,等于marginLeft,加上当前索引是几,就是几倍的这个宽度和margin的和吧,

//第i个按钮,等于marginLeft + i * (answerW + margin)

//这样,X的值,就算出来了,

//计算按钮的X值

CGFloat answerX = marginLeft +i * (answerW + margin);

btnAnswer.frame = CGRectMake(answerX + answerY + answerW + answerH);

//这样的话,我们再运行一下,是不是这5个按钮都有了

五个按钮

//再点“下一题”,一片白,因为每次点击这个按钮,都会创建好几个“答案按钮”啊,你点的次数越多,是不是里面的按钮越来越多,就变满屏了,所以说,每一次点之前,要干什么,是不是要清除所有的“答案按钮”吧,

//5.0 清除所有的“答案按钮”

//怎么来清除所有的“答案按钮”呢,就是如何把一个按钮从我们的控件中移除呢,

//就是调用按钮自己的removeFromSuperview,是不是就ok了,

//所以说,我这里就这么写:

while(self.answerView.subviews.firstObject){

//code;

}

//while循环,让这个self.answerView.subviews.firstObject,只要它有这么一个对象,有这么一个对象,就怎么办,调什么,让它第一个对象,self.answerView.subviews.firstObject,让它第一个对象,removeFromSuperview,

while(self.answerView.subviews.firstObject){

[self.answerView.subviews.firstObject removeFromSuperview];

}

//只要你有这个对象,我就让它从父控件中移除,也就是说,每次当你点击“下一题”按钮的时候,我先从这个answerView里面把所有子控件清掉,然后,是不是再创建新控件吧,

//运行一下,ok了吧,

//好,这样的话,删除每一个子控件,可以这么来删,但是这样写,是不是还得自己去写循环,还得自己去写循环,那么大家还记得数组里面有一个方法是,让数组里面每一个对象执行某个特定的方法,还记得这个吗,就这么写吧,我们可以直接这么写,注意看:

//self.answerView.subviews,注意,这个subviews属性,是一个什么类型,是不是一个数组类型啊,NSArray * subviews,

//数组里面,每一个对象,是不是就是我们那个按钮类型,我们可以直接让数组调一个makeObjectsPerformSelector:@selector(selector),让数组里面的每一个成员,执行它的哪个方法啊,removeFromSuperview,这样的话,一句话搞定,这句话的意思是,让这个数组里面的每一个成员,每一个对象,分别调一下这个方法,

//这句话的意思:让subviews这个数组中的每个对象,分别调一次removeFromSuperview方法,内部执行了循环,无需我们自己来写循环

[self.answerView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];

//不需要我们自己去写循环了,直接这么写就OK了,

//好,我们再运行一下试试看,这样的话,这个答案就生成好了,那么这个答案按钮就生成好了,那么接下来,我们这个黄色背景是不是就可以把它干掉了吧,

//怎么给它干掉呢,打开main.storyboard,选中这个控件列表中的answerView,右边的属性,Background,不要选这个Default,选择Clear Color,其实是透明的,没有颜色就是透明的,ok,

好,这是我们这个动态生成“答案”按钮

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清风清晨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值