UIKit之猜图器Demo

需求

实现猜图器Demo
请添加图片描述

  1. 功能分解:
    1>下一题切换功能
    2>点击图片后能放大并背景变暗(本质是透明度的变化)。再次点击则缩小,删除暗色背景。
    在这里插入图片描述
    3> 答案区按钮点击则文字消失,选择区对应文字恢复。
    4> 选择区文字按钮点击则添加该文字到答案区。
    5> 点击提示使得答案对应的第一个字符的按钮添加入答案区。

分析:

界面主要由如下三部分组成:top、middle、bottom。
在这里插入图片描述
由于上半部分的组件多是直接交互,所以写为该视图类的成员变量,而中部和下部,按钮单一,且一般都是多个按钮一起有响应动作发生:如删除、创建等,所以写入仅需两个视图成员:viewmiddle、viewbottom。
综上,涉及组件有:

UIButton、UILabel、UIView
1 右上角积分不可点击,但是有图片,又有文字,所以用UIButton,取消交互属性
2 中间图片可点击,用UIButton而不是UIIMageView
3 点击中间图片生成阴影,而点击阴影后回退到之前界面,说明阴影本质是带背景色的图片。

代码实现:

  1. VC处调用代码:
{[self testCaiTuDemo];
}
- (void) testCaiTuDemo{// 2. 猜图器上半视图CaiTuViewTop * viewtop = [[CaiTuViewTop alloc] initWithFrame:CGRectMake(0, 60, self.view.frame.size.width, self.view.frame.size.height)];[self.view addSubview:viewtop];
}
  1. 界面构成:
    自定义视图类:
    界面上半部分组件多直接交互,故写直接创建为成员变量,而中部和下部,按钮单一,一般是多个按钮产生有响应动作:如删除、创建等,故写入仅需两个视图成员:viewmiddle、viewbottom。
#import <UIKit/UIKit.h>
#import "CZQuestion.h"NS_ASSUME_NONNULL_BEGIN
@interface CaiTuViewTop : UIView
@property(strong, nonatomic) UIButton *imgbtn;
@property(strong, nonatomic) UIButton *l1btn;
@property(strong, nonatomic) UIButton *l2btn;
@property(strong, nonatomic) UIButton *r1btn;
@property(strong, nonatomic) UIButton *r2btn;
// 积分按钮:
@property(strong, nonatomic) UIButton *topRightbtn;
// 题号展示label
@property(strong, nonatomic) UILabel *labtop1;
// title
@property(strong, nonatomic) UILabel *labtop2;
// 当前题号
@property (nonatomic, assign) int index;
// ==== 猜图器plist信息 ====
@property (nonatomic, strong) NSArray * questions;
// 在放大缩小Frame时,存个原始frame来方便缩消回去 复原方便
@property (nonatomic, assign) CGRect iconFrame;// 在某个个自定义方法中,获取其它自定义方法中创建的属性,是获取不到的
// 为了删除放大后增加的btn背景视图,用来引用阴影按钮,方便找到并删除
@property(nonatomic, weak) UIButton *coverView;
@property(nonatomic, strong) UIView *viewmiddle;
@property(nonatomic, strong) UIView *viewbottom;- (void)btnNxtClick;-(void)NxtQuestion;-(void)shrinkbgclick;-(void) selectBtnClick:(UIButton *)btn;@end
NS_ASSUME_NONNULL_END
  1. 布局实现以及功能初始化:
    1> APP拥有酒红色背景图,通过创建UIImage类并添加到新建的UIImageView类对象中去,随后通过insertSubview添加到当前View。
    2> 创建App顶部各组件,注意右上角显示积分的UIButton需要设置取消交互,并注意图标在左而文字在右(设置Button的Image再设置Title即可,能左右分布的只能是IMage和Title)。
    3> 可点击图片的内边距设置:设置图片的backgroundImage后,再设置image,通过设置按钮的imageEdgeInsets
    4> 初始化题目信息。通过懒加载数据变量,设置界面显示第一题信息。
-(instancetype) initWithFrame:(CGRect)frame{self = [super initWithFrame:frame];if(self){// 背景图
#pragma mark - backGroundImage// 1. 设置背景图片,原理是加UIImageView视图,用UIIMage初始化该视图,并添加到self viewUIImage *backgroundImage = [UIImage imageNamed:@"bj.png"]; // 从项目中加载图片UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:backgroundImage];backgroundImageView.frame = self.bounds; // 设置与 self.view 相同的 framebackgroundImageView.contentMode = UIViewContentModeScaleAspectFill; // 设置填充模式[self insertSubview:backgroundImageView atIndex:0]; // 将 imageView 添加到视图的最底层#pragma mark - ViewTop// 按钮:_imgbtn = [[UIButton alloc] initWithFrame:CGRectMake(108, 120, 200, 200)];_l1btn = [[UIButton alloc] initWithFrame:CGRectMake(20, 210, 65, 35)];_l2btn = [[UIButton alloc] initWithFrame:CGRectMake(20, 274, 65, 35)];_r1btn = [[UIButton alloc] initWithFrame:CGRectMake(315, 210, 70, 35)];_r2btn = [[UIButton alloc] initWithFrame:CGRectMake(315, 274, 70, 35)];_topRightbtn = [[UIButton alloc] initWithFrame:CGRectMake(311, 73, 42, 20)];// 根据外面的初始化情况:设置width为屏宽,再设置左边距为0,直接设置text居中即可_labtop1 = [[UILabel alloc] initWithFrame:CGRectMake(0, 50, self.frame.size.width, 21)];// self.frame.size.width:因为_labtop2 = [[UILabel alloc] initWithFrame:CGRectMake(0, 75, self.frame.size.width, 21)];_topRightbtn = [[UIButton alloc] initWithFrame:CGRectMake(300, 30, 100, 20)];[_topRightbtn setTitle:@"1000" forState:UIControlStateNormal];_labtop1.textColor = [UIColor whiteColor];_labtop2.textColor = [UIColor whiteColor];_topRightbtn.titleLabel.textColor = [UIColor whiteColor];_topRightbtn.font = [UIFont systemFontOfSize:12];[_topRightbtn setImage:[UIImage imageNamed:@"coin.png"] forState:UIControlStateNormal];_topRightbtn.titleLabel.textAlignment = NSTextAlignmentCenter;// 按钮禁止点击_topRightbtn.userInteractionEnabled = NO;// 页号:这些不用设置,交给VC调用处//        _labtop1.text = @"1/10";//        // 图片描述//        _labtop2.text = @"第一张图片";//        // UILabel文字居中//        _labtop1.textAlignment = NSTextAlignmentCenter;//        _labtop2.textAlignment = NSTextAlignmentCenter;//        // UILabel大小设置//        _labtop1.font = [UIFont systemFontOfSize:12];//        _labtop2.font = [UIFont systemFontOfSize:12];//// 带白色边框的背景图:用白色给按钮的背景图打底,再设置图片:// center_img[_imgbtn setBackgroundImage:[UIImage imageNamed:@"center_img.png"] forState:UIControlStateNormal];// 2.1 初始index为-1,初始label信息为index0的内容// 读取数据也通过 viewTop来获取// 初始为-1,++后使得索引为0,从0处开始获取信息
#pragma mark - 初始化题目信息_index = -1;[self NxtQuestion];// 不显示的调试:网上也看到这种说不显示的例子了// center_img// people-wg:先往后做吧,然后在看着怎么设置// 图片像素太大,不显示//        [_imgbtn setImage:[UIImage imageNamed:@"people-cls.png"] forState:UIControlStateNormal];_imgbtn.contentMode = UIViewContentModeScaleAspectFit; // 或者使用其他contentMode// UIImage 的 scaling methods_imgbtn.imageEdgeInsets = UIEdgeInsetsMake(5, 5, 5, 5);// 点击不变灰色:取消高亮的接口:,showsHeighted已经不能用了_imgbtn.adjustsImageWhenHighlighted = NO;// 四周按钮[_l1btn setTitle:@"提示" forState:UIControlStateNormal];_l1btn.font = [UIFont systemFontOfSize:12];[_l1btn setImage:[UIImage imageNamed:@"icon_tip.png"] forState:UIControlStateNormal];[_l1btn setBackgroundImage:[UIImage imageNamed:@"btn_left"] forState:UIControlStateNormal];[_l2btn setTitle:@"帮助" forState:UIControlStateNormal];[_l2btn setImage:[UIImage imageNamed:@"icon_help.png"] forState:UIControlStateNormal];_l2btn.font = [UIFont systemFontOfSize:12];[_l2btn setBackgroundImage:[UIImage imageNamed:@"btn_left"] forState:UIControlStateNormal];[_r1btn setImage:[UIImage imageNamed:@"icon_img.png"] forState:UIControlStateNormal];[_r1btn setTitle:@"大图" forState:UIControlStateNormal];_r1btn.font = [UIFont systemFontOfSize:12];[_r1btn setBackgroundImage:[UIImage imageNamed:@"btn_right"] forState:UIControlStateNormal];[_r2btn setTitle:@"下一题" forState:UIControlStateNormal];_r2btn.font = [UIFont systemFontOfSize:12];[_r2btn setBackgroundImage:[UIImage imageNamed:@"btn_right"] forState:UIControlStateNormal];#pragma mark - btnAddTarget// 绑定帮助按钮的响应事件[_l1btn addTarget:self action:@selector(btnHelpClick) forControlEvents:UIControlEventTouchUpInside];// 绑定下一题按钮的响应事件[_r2btn addTarget:self action:@selector(btnNxtClick) forControlEvents:UIControlEventTouchUpInside];// 绑定响应事件[_r1btn addTarget:self action:@selector(EnlargeClick) forControlEvents:UIControlEventTouchUpInside];// 给头像绑定放大功能[_imgbtn addTarget:self action:@selector(imgBtnClick) forControlEvents:UIControlEventTouchUpInside];[self addSubview:_imgbtn];[self addSubview:_l1btn];[self addSubview:_l2btn];[self addSubview:_r1btn];[self addSubview:_r2btn];[self addSubview:_labtop1];[self addSubview:_labtop2];[self addSubview:_topRightbtn];#pragma mark - ViewMiddle// 宽度同当前_viewmiddle = [[UIView alloc] initWithFrame:CGRectMake(0, self.frame.size.height/2.5, self.frame.size.width, 50)];//_viewmiddle.backgroundColor = [UIColor greenColor];// 没有添加进去,_viewbottom = [[UIView alloc] initWithFrame:CGRectMake(0, self.frame.size.height/2, self.frame.size.width, 150)];// _viewbottom.backgroundColor = [UIColor greenColor];#pragma mark - 初始化答案区btn、带选取btn[self CreateAnswerBtn];[self CreateSelectBtn];#pragma mark - ViewBottom// 动态添加按钮功能:点击下一题的时候动态创建按钮[self addSubview:_viewmiddle];[self addSubview:_viewbottom];}return self;
}
  1. 懒加载数据:
    使用模型来记录变量可以避免使用字典时的键错误。 我读取时出错了,后来发现是plist中的option字段是数组类型,所以得使用数组的接口。
    我曾经声明错了,options属性该是NSArray
    通过字典封装模型,初始化函数类型是instancetype,防止继承体系下出问题。
@interface CZQuestion : NSObject
// 希望外部修改不会影响当前属性,就使用cpy
@property(nonatomic, copy) NSString *answer;
@property(nonatomic, copy) NSString *icon;
@property(nonatomic, copy) NSString *title;
// 强引用
@property(nonatomic, strong) NSArray *options;
-(instancetype) initWithDict:(NSDictionary *)dict;
+(instancetype) questionWithDict:(NSDictionary *)dict;
@end
#import "CZQuestion.h"@implementation CZQuestion
-(instancetype) initWithDict:(NSDictionary *)dict
{if(self = [super init]){self.answer = dict[@"answer"];self.title = dict[@"title"];self.icon = dict[@"icon"];self.options = dict[@"options"];}return self;
}// 这种命名方式是约定
+(instancetype) questionWithDict:(NSDictionary *)dict
{return [[self alloc]initWithDict:dict];
}@end

懒加载过程:读取文件到NSString,再转Array。由于文件本身是装着字典的,所以转的Array是个字典数组。

// 一般模型中属性全是String:记录
- (NSArray *)questions{if(_questions == nil){// 从安装路径读取plistNSString *path = [[NSBundle mainBundle] pathForResource:@"questions.plist" ofType:nil];// 把字符串字典,转为数组,此时数组中装着多个字典,下面要把字典转为类模型NSArray *arrayDicts = [NSArray arrayWithContentsOfFile:path];// 创建存模型的数组NSMutableArray *arrayModel = [NSMutableArray array];// 遍历for(NSDictionary *dict in arrayDicts){CZQuestion *model = [CZQuestion questionWithDict:dict];// 给模型数组中添加模型[arrayModel addObject:model];}// 最后把模型数组赋值给该懒加载变量,它是个数组,里面装着模型_questions = arrayModel;}return _questions;
}
  1. 核心功能实现:
    1> 下一题切换:
    更新index、更新题目信息、创建答案区和待选区按钮。
    2> 最后一题后弹出信息框:
    创建视图变量添加,绑定响应事件,点击后关闭当前视图,同时调用remove移除。
    3> 答案区按钮和待选区按钮的点击和消失:
    设置点击按钮后消失即可,但此前,在点击待选区按钮添加到答案区时,设置答案区按钮tag和待选区按钮tag相同。
    同时注意答案区满了后,禁止待选区视图的交互属性。
    4> 判断答案是否正确:
    读取数据模型的answer属性,和答案区对照,相同则设置蓝色字体。
    5> 积分的加法减法:
    在每一题填满且正确时,增加积分。
    点击提示后减少积分。
    6> 点击图片按钮放大图片:
    重新设置frame这一行添加到动画中执行。
    背景变化:把透明度变化添加到动画中执行。
    7> 加分
    回答完毕,正确则加分。
    注意不能通过title.text直接设置,必须通过setTitle()方法。
    8> 扣分
    回答完毕,错误则扣分

实现功能:

#import "CaiTuViewTop.h"@implementation CaiTuViewTop#pragma mark - 实现函数#pragma mark - btn:HelpClick
-(void) btnHelpClick{int score = self.topRightbtn.titleLabel.text.intValue;if(score >= 100){// 1. 减分[self deductScore];// 2.清空for(UIButton *btn in _viewmiddle.subviews){[self answerBtnClick:btn];}// 3. 获取答案CZQuestion *que = _questions[_index];NSString *answerFirst = [que.answer substringToIndex:1];// 4. 只提示第一个for(UIButton *btn in self.viewbottom.subviews){// Expected ']'if([btn.currentTitle isEqual:answerFirst]){[self selectBtnClick:btn];}}}else{NSLog(@"没积分了,不能提示");}
}-(void) delinfoBtn:(UIButton *)btn{//btn.hidden = YES;[btn removeFromSuperview];
}#pragma mark - btn:CreateAnswerBtn
-(void)CreateAnswerBtn{// 创建之前先清除已添加的答案按钮:// 如果存在元素,则删除
//    while(_viewmiddle.subviews.firstObject){
//        [_viewmiddle.subviews.firstObject removeFromSuperview];
//    }// 也可以让数组中每个元素都执行删除操作[_viewmiddle.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];//CZQuestion *que = self.questions[_index];int len = que.answer.length;CGFloat btnW = 35;CGFloat btnH = 35;CGFloat btnX = 35;CGFloat btnY = 2;CGFloat marginX = 10;   // 每个答案格X间距10,Y间距0// 每个间隔距离最左边CGFloat marginLeft = (_viewmiddle.frame.size.width - btnW * len - marginX*(len-1))/2;   // 每个答案格X间距10,Y间距0for(int i = 0; i < len; i++){UIButton *answerbtn = [[UIButton alloc] initWithFrame:CGRectMake(marginLeft+i*btnX + marginX*i, btnY, btnW, btnH)];// 设置背景图片[answerbtn setBackgroundImage:[UIImage imageNamed:@"btn_answer"] forState:UIControlStateNormal];[answerbtn setBackgroundImage:[UIImage imageNamed:@"btn_answer_highlighted"] forState:UIControlStateHighlighted];[answerbtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];[answerbtn addTarget:self action:@selector(answerBtnClick:) forControlEvents:UIControlEventTouchUpInside];[self.viewmiddle addSubview:answerbtn];}
}#pragma mark - btn:answerbtnClick
// 如果有内容,则隐藏,没有则不做
-(void) answerBtnClick:(UIButton *)btn{if(btn.currentTitle != nil){// 设置中间字体为黑色:如果当前点击删除某答案区字,答案区不满,应该再设为黑色[self setViewmiddleFontColor:[UIColor blackColor]];NSString *tmp = btn.currentTitle;[btn setTitle:nil forState:UIControlStateNormal];self.viewbottom.userInteractionEnabled = YES;// 根据tag寻找待选区对应的btn:这样也行,但是不能用self直接来找,因为self会找到两个:// 因为设置了middleView和bottomView中的btn的tag相等,所以通过self找到的tag不唯一// 此外,通过self的subview不能调用这个函数,只能通过直接的视图来获得,因为self的subview是个集合,非某个单一viewUIButton *selectbtn = (UIButton *)[_viewbottom viewWithTag:btn.tag];[self appearSelectBtn:selectbtn :tmp];// 正确方法2:
//        for(UIButton *optbtn in self.viewbottom.subviews){
//            if(optbtn.tag == btn.tag){
//                optbtn.hidden = NO;
//                break;
//            }
//        }}
}
#pragma mark - btn:CareteSelectBtn
-(void)CreateSelectBtn{// 让区域可交互:因为当输入正确使得界面切换到下一题时,上次因为满了而设定的不可选择仍然生效,所以要解除self.viewbottom.userInteractionEnabled = YES;// 先删除已有[_viewbottom.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];// 增加新的CZQuestion *que = self.questions[_index];int len = que.options.count;//长度调用int colcounts = 7;CGFloat btnW = 35;CGFloat btnH = 35;CGFloat btnX = 35;CGFloat btnY = 5;CGFloat marginX = 10;   // 每个答案格X间距10,Y间距0CGFloat marginY = 10;   // 每个答案格X间距10,Y间距0// 每个答案格X间距10,Y间距0// 每个间隔距离最左边:必然大于1列,所以直接按一列的减CGFloat marginLeft = (self.frame.size.width - btnW * colcounts - marginX*(colcounts-1))/2;// NSLog(@"第%d 批", _index);// 查坐标:0批有错误点for(int i = 0; i < len; i++){int row = i / colcounts;int col = i % colcounts;UIButton *answerbtn = [[UIButton alloc] initWithFrame:CGRectMake(marginLeft+col*btnX + marginX*col, marginY*row + btnH *row, btnW, btnH)];answerbtn.tag = i;// 设置背景图片[answerbtn setBackgroundImage:[UIImage imageNamed:@"btn_option"] forState:UIControlStateNormal];[answerbtn setBackgroundImage:[UIImage imageNamed:@"btn_option_highlighted"] forState:UIControlStateHighlighted];[answerbtn setTitle:que.options[i] forState:UIControlStateNormal];[answerbtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];[answerbtn addTarget:self action:@selector(selectBtnClick:) forControlEvents:UIControlEventTouchUpInside];[self.viewbottom addSubview:answerbtn];}
}#pragma mark - selectBtnClick
// 待选按钮的单击事件
-(void) selectBtnClick:(UIButton *)btn{// 1. 隐藏btn.hidden = YES;// 2. 获取当前按钮上的文字NSString *text = btn.currentTitle;// 3. 文字显示到答案按钮上for(UIButton *answerbtn in self.viewmiddle.subviews){// 挨个放:如果当前内容空,则放if(answerbtn.currentTitle == nil){[answerbtn setTitle:text forState:UIControlStateNormal];// 同步taganswerbtn.tag = btn.tag;break;}}// 每次点击完后判断是否已满,已满则禁止所有控件交互,所以也不会再触发该方法,能保证效率:BOOL isAnswerBtnFull = YES;for(UIButton *btnAnswer in self.viewmiddle.subviews){if(btnAnswer.currentTitle == nil){isAnswerBtnFull = FALSE;break;}}// 满了,则设置当前底部区域全不可交互,并且检查是否正确if(isAnswerBtnFull){self.viewbottom.userInteractionEnabled = NO;CZQuestion *model = self.questions[self.index];NSString *correctStr = model.answer;// 初始化NSMutableString *current = [NSMutableString string];for(UIButton *btnAnswer in self.viewmiddle.subviews){[current appendString:btnAnswer.currentTitle];}// 答案一致则设置全部为蓝色,且执行动画跳转去下一题if([correctStr isEqualToString:current]){[self setViewmiddleFontColor:[UIColor blueColor]];[self getScore];// 延迟后执行该方法:[self performSelector:@selector(btnNxtClick) withObject:nil afterDelay:0.5];}else{[self setViewmiddleFontColor:[UIColor redColor]];}}
}#pragma mark -加分
-(void) getScore{NSString * score = self.topRightbtn.titleLabel.text;int num = score.intValue;if(num >= 100)num += 100;NSString *newsc = [NSString stringWithFormat:@"%d", num];[_topRightbtn setTitle:newsc forState:UIControlStateNormal];//self.topRightbtn.titleLabel.text = newsc;
}#pragma mark -减分
-(void) deductScore{NSString * score = self.topRightbtn.titleLabel.text;int num = [score integerValue];if(num >= 100)num -= 100;NSString *newsc = [NSString stringWithFormat:@"%d", num];[_topRightbtn setTitle:newsc forState:UIControlStateNormal];
}#pragma mark -setFontcolor-(void) setViewmiddleFontColor:(UIColor *)color{for(UIButton *btn in self.viewmiddle.subviews){[btn setTitleColor:color forState:UIControlStateNormal];}
}// 待选区按钮出现:
-(void) appearSelectBtn:(UIButton *)btn :(NSString *) str{// 根据字符串赋值//[btn setTitle:str forState:UIControlStateNormal];//btn.hidden = YES;btn.hidden = NO;
}// 跳转下一题的上半信息全部更新
// index++,设置label内容
-(void)NxtQuestion{// 更新索引、信息框所展示的内容_index++;// 懒加载变量的访问必须通过self才能触发getter方法,直接_方式不能CZQuestion *model = self.questions[_index];// 页号_labtop1.text = [NSString stringWithFormat:@"%d/%ld", self.index+1, self.questions.count];// 图片描述_labtop2.text = model.title;// UILabel文字居中_labtop1.textAlignment = NSTextAlignmentCenter;_labtop2.textAlignment = NSTextAlignmentCenter;// 设置文字颜色,否则看不见// UILabel大小设置_labtop1.font = [UIFont systemFontOfSize:12];_labtop2.font = [UIFont systemFontOfSize:12];// 设置图片:把图片放小 试试[_imgbtn setImage:[UIImage imageNamed:model.icon] forState:UIControlStateNormal];// 最后一题禁用nxt按钮:OC的if可以省略{}if (_index == _questions.count-1)_r2btn.enabled = NO;
}-(void) imgBtnClick{if(_coverView == nil){[self EnlargeClick];}else{[self shrinkbgclick];}
}#pragma mark - 放大按钮功能// 放大按钮的响应事件
-(void) EnlargeClick{// 按钮阴影背景UIButton *btnview = [[UIButton alloc] init];[btnview setBackgroundColor:[UIColor blackColor]];// self本身是viewbtnview.frame = self.bounds;btnview.alpha = 0.0;// 记录刚创建的btnview_coverView = btnview;// 存原始frame_iconFrame = _imgbtn.frame;// 通过动画增加渐变暗:// 把之前的图片显示到最上层:不是新设置图片// 设置新的frame属性:// 高和宽设成一样的CGFloat iconW = self.frame.size.width;CGFloat iconH = iconW;// 相当于贴着屏幕中间的正方形,所以 用 ( 屏幕长度 - 正方形边长) / 2CGFloat iconY = (self.frame.size.height-iconH)/2;// 增加图片变大的动画// 增加背景变暗的动画/// 摈弃原本的写法:_imgbtn.frame = CGRectMake(0, iconY, iconW, iconH);// [btnview addTarget: action: forControlEvents:];[UIView animateWithDuration:1 animations:^{// 1. 缩小_imgbtn.frame = CGRectMake(0, iconY, iconW, iconH);// 2. 背景变暗消失:不用移除的方式,而是通过设置透明度_coverView.alpha = 0.6;// 3.}];// 添加事件后没找到函数:在.h文件中声明,这里点击一般进不去[btnview addTarget:self action:@selector(shrinkbgclick) forControlEvents:UIControlEventTouchUpInside];// 把背景贴上去[self addSubview: btnview];// 把底层图片放到顶层,因为刚刚添加了btnView[self bringSubviewToFront: _imgbtn];
}// 增加动画
-(void) shrinkbgclick{// 无动画的视线方式:// 删除背景视图
//    [_coverView removeFromSuperview];
//        // frame恢复原来
//    _imgbtn.frame = _iconFrame;
//    // 0.7秒执行frame变化:[UIView animateWithDuration:0.7 animations:^{// 1. 缩小_imgbtn.frame = _iconFrame;// 2. 背景变暗消失:不用移除的方式,而是通过设置透明度_coverView.alpha = 0.0;// 3.}completion:^(BOOL finished) {if(finished){[self bringSubviewToFront: _coverView];// 当缩完,可通过判断_cvoerView是否有值来判断当前的缩放状态_coverView = nil;}}];
}
@end

注意事项:

  1. 图片按钮不显示图片:

不是名字和函数错了,而是像素在当前视图中绘制不出来,我缩小后可以绘制出来了。

  1. 在VC中重写方法可以改变状态栏颜色。
    隐藏状态栏也是通过重写方法。

  2. 添加动画的对象可以是父视图,也可以是爷视图,我开发过程中犯了错,因为那时还没把当前元素添加到父视图中。

[answerbtn addTarget:self action:@selector(selectBtnClick:) forControlEvents:UIControlEventTouchUpInside];[self.viewbottom addSubview:answerbtn];
  1. 在设置imgbtn的backgroundImage之前设置Image,结果没有显示,在设置backgroundImage之后设置Image就显示了,为什么?。

因为绘制顺序、内边距等设置的顺序导致,切换设置顺序即可。

  1. 懒加载变量的触发问题:

懒加载变量需要通过getter()方法触发,通过_不会触发懒加载,通过self调用才行。

  1. 要删掉已经添加进来的按钮:
  1. while()或:
  2. self …数组中全部元素执行同一个删除代码。
  1. Array需要是强引用,@properyt中用(copy)即可,其它字符串用copy类型声明即可。

  2. 组件不显示问题:

一定是subview,查查坐标位置问题。数值可能成了负数或者太大。我自己是因为 底部视图还没创建,结果计算出了负值,所以要注意调用某个方法给视图添加组件时,要确保该视图已经创建并初始化。

  1. 获取组件上是否有已经存在text内容的API:

currentTitle,基于此可以获取点击的待选区按钮上的文字,也可以设置为答案区按钮上的文字。

  1. 注意关键字NO和FALSE的区别:NO确实是YES,而不是FALSE

  2. 按钮的title的清除:

不能通过设置@“”,而要设置nil。否则按钮的title仍不为空。

  1. 关于代理:什么时候需要代理、代理的好处:
    需要监控用户的操作,要用代理。视图需要实现代理协议。
    是一种设计模式,解除耦合,做某件事找代理去做。一些API中经常看见delegate,就是需要传入代理。代理就是需要执行的某个方法。比如这里警告框要实现的代理函数,可以监听到点击的按钮序号,进而获得按钮中的内容。
    · 规范:在当前类中声明代理并实现该函数。
    · 以警告框为例的代理逻辑:
    在这里插入图片描述

  2. AppIcon和LaunchImage

图片名称为:@2x、@3x的含义
为什么同样一张图片要做很多张?
1> 因为不同屏幕大小型号不一样,像素要求不同、分辨率不同,所以要求启动图和图标有多个版本。分辨率和像素点的关系:分辨率xy必须是像素点xy的倍数。程序代码中是点,运行后会自动把点转换为不同的像素去找图片。但是你的原始图片要准备好多份。分辨率高,则一个点表示多个像素。
2> 不同地方可以都要显示同一张图片,不同地方需要的图片尺寸是不一样的。
@2x:视网膜屏幕,在原来点坐标的大小上长乘以2
@3x:在代码写的时候统一使用btn_left,iOS根据屏幕会自动寻找约定好的后缀名@nx。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/15557.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springboot项目,@Test写法 @Before @After

某文件示例 package cn.xxx.crm.boss;import cn.xxxx.crm.manager.mq.rabbit.AliyunCredentialsProvider; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; im…

第十九届全国环境友好科技竞赛(绿色创业类)正式启动

近日&#xff0c;第十九届全国环境友好科技竞赛&#xff08;绿色创业类&#xff09;正式拉开帷幕。本次竞赛由清华大学、同济大学、西安建筑科技大学及中国环境科学学会共同主办&#xff0c;旨在通过学科竞赛的方式鼓励全国高校学生积极参与到资源节约型和环境友好型的和谐社会…

探索python字典:遍历与访问的艺术

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、获取字典的键与值 1. 获取字典的键 2. 获取字典的值 二、遍历字典的键值对 1. 使用 …

【全开源】二手车置换平台系统小程序(FastAdmin+ThinkPHP+Uniapp)

二手车置换平台系统 特色功能&#xff1a; 车辆评估&#xff1a;系统提供车辆状况、性能和价值的评估功能&#xff0c;通过拍照、上传图片等方式自动识别车辆信息并给出估价建议&#xff0c;帮助买家和卖家更准确地了解车辆价值。 在线交易&#xff1a;平台提供在线购车、售车…

Idea中flume的Interceptor的编写教程

1.新建-项目-新建项目 注意位置是将来打包文件存放的位置&#xff0c;即我们打包好的文件在这/export/data个目录下寻找 2. 在maven项目中导入依赖 Pom.xml文件中写入 <dependencies> <dependency> <groupId>org.apache.flume</groupId> <artifa…

❤Element的使用element

❤Element的使用 1、input输入框 禁止自动补全和下拉提示 input 输入框在输入后浏览器会记录用户输入的值&#xff0c;在下次输入的时候会将记录的值提示在输入框的下面&#xff0c;当输入框是密码的时候&#xff0c;这样可以看见上次输入的密码&#xff0c;这样用户体验不好…

python使用jsonpath来查找key并赋值

目录 一、引言 二、JsonPath简介 三、Python中的JsonPath库 四、使用JsonPath查找JSON Key 五、使用JsonPath赋值JSON Key 六、高级用法 七、结论 一、引言 在数据驱动的现代应用中&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;已成为一种广泛使…

基于大数据的支付风险智能防控技术规范

随着大数据、移动互联、人工智能、生物特征识别等技术的快速发展&#xff0c;支付方式正在发生着巨大而深刻的变革&#xff0c;新技术在丰富支付手段、提高支付效率的同时&#xff0c;带来了新的隐患&#xff0c;也对从业机构的风险防控能力提出了更高的要求。 传统的风控技术…

01-02.Vue的常用指令(二)

01-02.Vue的常用指令&#xff08;二&#xff09; 前言v-model&#xff1a;双向数据绑定v-model举例&#xff1a;实现简易计算器Vue中通过属性绑定为元素设置class 类样式引入方式一&#xff1a;数组写法二&#xff1a;在数组中使用三元表达式写法三&#xff1a;在数组中使用 对…

【全部更新完毕】2024电工杯B题详细思路代码成品文章教学:大学生平衡膳食食谱的优化设计及评价

大学生平衡膳食食谱的优化设计及评价 摘要 大学阶段是学生获取知识和身体发育的关键时期&#xff0c;也是形成良好饮食习惯的重要阶段。然而&#xff0c;当前大学生中存在饮食结构不合理和不良饮食习惯的问题&#xff0c;主要表现为不吃早餐或早餐吃得马虎&#xff0c;经常食用…

宝塔面板修改端口后无法登入

今天通过宝塔面板登录腾讯云主机&#xff0c;看到下面的提醒&#xff0c;顺便点进去随便改了个端口 本以为改端口是很简单事情&#xff0c;结果我改完之后面板立马登不上了&#xff0c;接下来我改了登录地址和端口也不行&#xff0c;我以为是防火墙的问题&#xff0c;增加了防火…

ViT:1 从DETR说起

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调重新阅读。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;则提供了大模型领域最新技…

Pycharm在下载安装第三方库时速度慢或超时问题 / 切换国内镜像地址

pycharm下载第三方库速度极慢&#xff0c;搜索了一下&#xff0c;发现方法非常乱&#xff0c;稍作整理。这个问题一般都会出现&#xff0c;在我们开发中遇到的常见问题&#xff0c;根据以下解决方法&#xff0c;基本可以解决&#xff0c;但是不能100%保证 Installing packages …

打造一个增强版Kimi:可以生成图片、PPT、PDF文档、数据分析等

Kimi虽然在国内AI大模型中表现不错&#xff0c;但是和ChatGPT还是差不少功能。现在有一个很简单的方法&#xff0c;把kimi功能增强&#xff0c;使用效果大大改善&#xff0c;比如生成图片&#xff1a; 具体方法如下&#xff1a; 打开coze网站&#xff1a;https://www.coze.cn/…

C++容器之位集(std::bitset)

目录 1 概述2 使用实例3 接口使用3.1 constructor3.2 count_and_size3.3 test3.4 any3.5 none3.6 all3.7 set3.8 reset3.9 filp3.10 to_string3.11 to_ulong3.12 to_ullong3.13 operators1 概述 位集存储位(只有两个可能值的元素:0或1,true或false,…)。   该类模拟bool…

推荐一款自助分析的财务分析软件:奥威BI软件

奥威BI软件是一款支持多维度动态自助分析的软件&#xff0c;预设了智能财务分析方案&#xff0c;提供内存行列计算模型解决财务指标计算难题&#xff0c;界面简洁&#xff0c;以点击、拖曳操作为主&#xff0c;十分适合没有IT背景的财务人做财务分析。因此也经常有人说奥威BI软…

Spark搭建 Standalone模式详细步骤

Standalone模式概述&#xff1a; Standalone模式是Spark自带的一种集群模式&#xff08;本地集群&#xff0c;不依赖与外部集群&#xff0c;比如Yarn&#xff09;&#xff0c;可以真实地在多个机器之间搭建Spark集群的环境。 Standalone是完整的Spark运行环境,其中: Master角…

OpenFeign微服务调用组件使用

前言&#xff1a;OpenFeign是可以跨服务、跨进程的调用方式。 什么是Feign Feign是Netflix开发的声明式、模版化的HTTP客户端。 优势: Feign可以做到使用 HTTP 请求远程服务时就像调用本地方法一样的体验&#xff0c;开发者完全感知不到这是远程方法&#xff0c;更感知不到这…

【TB作品】stm32单片机读取DS2401程序

DS2401是由Analog Devices公司生产的一种硅序列号芯片&#xff0c;它提供了一个绝对唯一的64位ROM识别码&#xff0c;用于确保可追溯性。以下是对DS2401器件的分析&#xff1a; 特点和优势&#xff1a; 唯一性&#xff1a;每个DS2401芯片都有一个独一无二的64位注册码&#x…

[less配置]vue2引入less

1、终端输入&#xff1a;npm install less less-loader --save-dev 2、在package.json查看是否安装less依赖 3、调用