UIKit之图片浏览器

功能需求

实现一个图片浏览器,点击左右按钮可以切换背景图,且更新背景图对应的索引页和图片描述内容。

分析:

  • 实现一个UIView的子类即可,该子类包含多个按钮。

实现步骤:

  1. 使用OC语言,故创建cocoa Touch类型文件。Xcode会创建.h文件和.m文件:PicBrowserDemo类。
    在这里插入图片描述

  2. 图片资源导入:注意图片不要重名
    注意各项的类型:Root是Array,其余是Dictionary

  3. 实现该类。
    该类带有多个控件,令其继承UIView。
    a. 声明类的成员变量:在.h文件中定义:,类型是strong。
    该图片浏览器需要两个可显示文字内容但不可修改的Label、两个前后图片切换的按钮以及承载图片的视图。
    在.h 文件中:

@interface PicBrowserDemo : UIView
@property(strong, nonatomic) UIImageView  *imageView;
@property(strong, nonatomic) UILabel *label1;
@property(strong, nonatomic) UILabel *label2;
@property(strong, nonatomic) UIButton *btn1;
@property(strong, nonatomic) UIButton *btn2;
@end

b. 创建plist类型文件,直接在项目下创建,plist文件属于resource类型文件,在该栏目下可找到。
选择root类型为Array,而每个元素设置为字典,因为每个字典中存图片的名称和title(描述)。

c. .m 文件:

// 1 plist:
	信息填写
// 2 初始化各个组件,显示的信息以第一张为基准
// 3 nxt
// 4 pre
// 5 降低冗余,合并:pre、nxt函数

#import "PicBrowserDemo.h"

// 写私有属性:在这里
@interface PicBrowserDemo()
// assign、strong的区别: asign表示基本类型的变量
@property(nonatomic, strong) NSArray *pic;
@property(nonatomic, assign) int index;

@end

// 从plist中读取到的各图片信息集合

@implementation PicBrowserDemo
-(instancetype) initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if(self){
        // 初始化5个组件
        _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(80, 230, 150, 150)];
        // 图片模式:放入如何显示的 按比例缩放,不会拉伸变形
        _imageView.contentMode = UIViewContentModeScaleAspectFit;
        
        // 初始化为pic中第一张图片
        NSDictionary *dict = self.pic[0];
        _imageView.image = [UIImage imageNamed:dict[@"icon"]];
        // 固定值写法:
        //_imageView.image = [UIImage imageNamed:@"i1.png"];
        
        // label1:
        _label1 = [[UILabel alloc] initWithFrame:CGRectMake(80, 190, 150, 40)];
        _label2 = [[UILabel alloc] initWithFrame:CGRectMake(80, 380, 150, 40)];
        
        // text填内容
        _label1.text = [NSString stringWithFormat:@"%d/%ld", 1, self.pic.count];
        // 下面的label填入title
        _label2.text = dict[@"title"];
        
        // 填充方式fill
        _label1.textAlignment = NSTextAlignmentCenter;
        _label2.textAlignment = NSTextAlignmentCenter;
        // btn1
        _btn1 = [[UIButton alloc] initWithFrame:CGRectMake(30, 300, 50, 50)];
        _btn2 = [[UIButton alloc] initWithFrame:CGRectMake(230, 300, 50, 50)];
        // btn1
        [_btn1 setBackgroundImage:[UIImage imageNamed:@"zuo1.jpg"] forState:UIControlStateNormal];
        // btn2
        [_btn2 setBackgroundImage:[UIImage imageNamed:@"you1.png"] forState:UIControlStateNormal];
        
        // 绑定点击向前和向后
        [_btn1 addTarget:self action:@selector(changePages:) forControlEvents:UIControlEventTouchUpInside];
        //
        [_btn2 addTarget:self action:@selector(changePages:) forControlEvents:UIControlEventTouchUpInside];
        
//        [_btn1 addTarget:self action:@selector(pre) forControlEvents:UIControlEventTouchUpInside];
//        //
//        [_btn2 addTarget:self action:@selector(nxt) forControlEvents:UIControlEventTouchUpInside];
//        
        
        // 用tags区分该切换前一张还是后一张
        _btn1.tag = 1;
        _btn2.tag = 2;

        [self addSubview: _imageView];
        [self addSubview: _btn1];
        [self addSubview: _btn2];
        [self addSubview: _label1];
        [self addSubview: _label2];
    }
    return self;
}

// 重写属性pic的get方法懒加载:
/* 第一次调用一定为空,加载即可
 */
- (NSArray *) pic{
    if(_pic == nil){
        // 获取plist的文件路径
        // nsBundle:获取手机上软件的安装路径,而非项目路径
        NSString *path = [[NSBundle mainBundle] pathForResource:@"pics" ofType:@"plist"];
        // 读取文件
        NSArray *array = [NSArray arrayWithContentsOfFile:path];
        NSLog(@"count:%ld", array.count);
        _pic = array;
    }
    return _pic;
}

// 不需要参数:
- (void) changePages:(UIButton *)sender{
    switch (sender.tag) {
        case 1:
            _index--;
            break;
        case 2:
            _index++;
            break;
    }
    NSDictionary *dict = self.pic[self.index];
    // 上面的label填入页码
    _label1.text = [NSString stringWithFormat:@"%d/%ld", self.index+1, self.pic.count];
    // 下面的label填入title
    _label2.text = dict[@"title"];
    // 图片框填入图片:
    _imageView.image = [UIImage imageNamed:dict[@"icon"]];
    // 如果已经到了最后一张,则按钮切换为不允许点
    // 索引为末尾-1,则设置下一张按钮为不可点击
    // 没必要通过图片来设置,通过yes、no设置即可达到所需的灰色状态
    // 两条必须同时设置:否则会出现 翻到底再返回时,向右按钮仍然灰色
    self.btn2.enabled = !(_pic.count -1 == _index);
    self.btn1.enabled = !(0 == _index);
}


// 加索引:
- (void) nxt{
    _index++;
    NSDictionary *dict = self.pic[self.index];
    // 上面的label:填入序号
    _label1.text = [NSString stringWithFormat:@"%d/%ld", self.index+1, self.pic.count];
    // 下面的label:填入标题
    _label2.text = dict[@"title"];
    // 图片框填入图片:
    _imageView.image = [UIImage imageNamed:dict[@"icon"]];
    // 如果已经到了最后一张,则按钮切换为不允许点
    // 索引为末尾-1,则设置下一张按钮为不可点击
    // 没必要通过图片来设置,通过yes、no设置即可达到所需的灰色状态
    self.btn2.enabled = !(_pic.count -1 == _index);
    self.btn1.enabled = !(0 == _index);
}

//
- (void) pre{
    _index--;
    NSDictionary *dict = self.pic[self.index];
    // 上面的label:填入序号
    _label1.text = [NSString stringWithFormat:@"%d/%ld", self.index+1, self.pic.count];
    // 下面的label:填入标题
    _label2.text = dict[@"title"];
    // 图片框填入图片:
    _imageView.image = [UIImage imageNamed:dict[@"icon"]];
    // 如果为0,则设置向左不可点击且更换图片
    self.btn1.enabled = !(0 == _index);
    self.btn2.enabled = !(_pic.count -1 == _index);
}
@end

调用入口:

- (void)viewDidLoad {
    [super viewDidLoad];
    //[self test_Common_arrtibute];
    [self testPicBrowser];
}

-(void) testPicBrowser{
    PicBrowserDemo *browserView = [[PicBrowserDemo alloc] initWithFrame:CGRectMake(50, 80, 300 ,700)];
    //[browserView setBackgroundColor: [UIColor blueColor]];
    [self.view addSubview:browserView];
    
}
  1. 效果展示
  1. 首页只可向右
  2. 尾页只可向左

在这里插入图片描述
在这里插入图片描述

要注意的问题以及犯错

  1. 关于懒加载:
    设置变量同名的函数,实则为setter,判断变量指向为空,则做初始化获取操作,后续再利用都不需要,此为懒加载方式。
  1. 关于plist加载:
    使用bundle接口,, 通过plist文件名即可,该底层原理是使用了安装APP后的文件结构来获取文件,而非运行工程的目录结构。
  1. plist总是读取为空
    我的plist获取方式是读取Array接口,而我的plist中root设置为dictionary类型,因此接口不对应,获取错误了。改root为array类型即可。
  1. 初始化index报错
    switch中,tag为2是向右点击,所以应该index++。
  1. 图片浏览器初始化:
    按pic第一张的图片和title初始化即可。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

解决kali Linux安装后如何将语言修改为中文

开启虚拟机 用root用户进入终端 进入终端执行dpkg-reconfigure locales命令 选择en_US.UTF-8 UTF-8选项,按空格键将其取消。 选择zh_CN.UTF-8 UTP-8,按空格选择,按tab键选择ok。 选择zh_CN.UTF-8字符编码,按tab键选择ok&#xff0…

【JAVA】嵌入式软件工程师-2025校招必备-详细整理

一、Java 基础 1.JDK 和 JRE 有什么区别? jdk:java development kit jre:java runtime Environment jdk是面向开发人员的,是开发工具包,包括开发人员需要用到的一些类。 jre是java运行时环境,包括java虚拟机…

IDEA的妙用

IDEA 安装破解 复制JetbrainsIdesCrack-4.2.jar到安装目录下 修改安装目录下的bin目录的idea64.exe.vmoptions: 最后一行添加:-javaagent:E:\develop\JetBrains\IntelliJ IDEA 2018.3.5\bin\JetbrainsIdesCrack-4.2.jar(注意:使用自己的路…

(2)双指针练习:复写零

复写零 题目链接:1089. 复写零 - 力扣(LeetCode) 给你一个长度固定的整数数组 arr ,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。 注意:请不要在超过该数组长度的位置写入元素。请对输入…

WebSocket or SSE?即时通讯的应用策略【送源码】

最近在研究H5推送,发现除了我们常用的WebSocket以外,其实还有一种协议也能实现H5推送,那就是SSE协议。 而且,当前主流的大模型平台,比如ChatGPT、通义千问、文心一言,对话时采用的就是SSE。 什么是SSE协议…

基于HTML5和CSS3搭建一个Web网页(一)

倘若代码中有任何问题或疑问,欢迎留言交流~ 网页描述 创建一个包含导航栏、主内容区域和页脚的响应式网页。 需求: 导航栏: 在页面顶部创建一个导航栏,包含首页、关于我们、服务和联系我们等链接。 设置导航栏样式,包括字体、颜色和背景颜…

识物扫一扫识别植物怎么做?6个软件教你轻松识别植物

识物扫一扫识别植物怎么做?6个软件教你轻松识别植物 识别植物可以通过专门的植物识别应用来实现。以下是六款可以帮助您轻松识别植物的软件: 1.一键识别王:这款软件有着强大的植物识别服务,用户可以通过拍照或上传图片来识别植物…

算法学习笔记(5.0)-基于比较的高效排序算法-归并排序

##时间复杂度O(nlogn) 目录 ##时间复杂度O(nlogn) ##递归实现归并排序 ##原理 ##图例 ##代码实现 ##非递归实现归并排序 ##释 #代码实现 ##递归实现归并排序 ##原理 是一种基于分治策略的基础排序算法。 1.划分阶段:通过不断递归地将数组从中点处分开&…

迷宫游戏(c++)

我们来玩一个迷宫游戏,尝试走一下面的迷宫。 迷宫游戏 我们用一个二维的字符数组来表示前面画出的迷宫: S**. .... ***T 其中字符S表示起点,字符T表示终点,字符*表示墙壁,字符.表示平地。你需要从S出发走到T&#xf…

【全开源】JAVA共享自习室共享学习室无人系统支持微信小程序+微信公众号+H5

开启智能学习新时代 随着社会的快速发展,人们对于学习环境的需求也日益增加。为满足这一需求,我们推出了“共享自习室系统源码”,旨在通过智能化的管理方式,打造高效、便捷、舒适的共享学习空间。 核心功能 自习室预约&#xf…

6. 网络编程-网络io与select、poll,epoll

https://0voice.com/uiwebsite/html/courses/v13.7.html 首先看看这个学习计划 网络、网络编程、网络原理基础组件,20个。中间件 Redis ,MySQL,Kafka,RPC,Nginx开源框架(解决方案)业务开发(工程师开发&am…

YOLOv9训练自己的数据集:最新最详细教程

一、代码及论文链接: 代码链接:https://github.com/WongKinYiu/yolov9/tree/main 论文链接:https://arxiv.org/abs/2402.13616 二、使用步骤 1.1 虚拟环境配置 创建一个虚拟环境用于单独对yolov9的环境进行配置: conda crea…

Java中的数组、Set、List、Map类型的互相转换总结

序言 数组、Set、List、Map是Java语言非常常用的几种数据类型,他们之间存在着千丝万缕的联系。关于底层的数据结构我这里就不再多说啦,直接从应用出发,总结他们之间的转换方法,并给出推荐方法。 大家可以点赞收藏等到需要的时候…

传说中的运维门户设计

在IT服务管理这片广阔天地中,运维门户如同一位技艺高超的魔术师,轻轻一挥手,便将纷繁复杂的运维世界化繁为简,编织成一张便捷高效、触手可及的网络。它不仅是ITSM系统中不可或缺的一环,更是连接用户与技术世界的桥梁&a…

【打字】打字训练之针对性键盘区域练习

本文章的核心点是:使用代码生成自己想要训练的键位的词汇,然后导入到打字软件针对性练习 一个程序员突然想纠正打字习惯源于腱鞘炎,虽然使用双拼打字已经不慢了,但是姿势不是很正确,导致了腱鞘炎。 所以想着好好纠正指…

就这?轻轻松松在RK356X Android11适配ML307R Cat.1模组

开源鸿蒙硬件方案领跑者 触觉智能 Industio 本文基于IDO-SXB3568主板,介绍Android11平台上适配中移物联ML307R Cat.1 4G模组的方法。该方法适用于触觉所有RK356X的主板。 IDO-SXB3568是触觉智能推出的RK3568行业主板,预计6月上旬正式上架售卖。该行业主…

Docker安装Mosquitto

在物联网项目中,我们经常用到MQTT协议,用MQTT协议做交互就需要部署一个MQTT服务,而mosquitto是一个常用的MQTT应用服务, Mosquitto是一个实现了消息推送协议MQTT v3.1的开源消息代理软件。MQTT(Message Queuing Teleme…

【淘宝超高价女装】电商最好项目:一单赚1000多

课程目录 01.【超高价女装】项目介绍实操案例 02.【超高价女装】找款:配得上1000多的款式 03.【超高价女装】软件上款:600个款为底 04.【超高价女装】标题:能卖1000多的标题 05.【超高价女装】销量布局:主推款做销量评价 06…

【python量化交易】—— Alpha选股策略 - Qteasy自定义交易策略【附源码】

使用qteasy创建并回测Alpha选股交易策略 使用qteasy创建并回测Alpha选股交易策略策略思想第一种自定义策略设置方法,使用持仓数据和选股数据直接生成比例交易信号PS信号:第二种自定义策略设置方法,使用PT交易信号设置持仓目标:第三…

代码审计--变量覆盖

漏洞原理 变量覆盖(Dynamic Variable Evaluation) 是指变量未被初始化, 而我们自定义的变量可以替换程序原有的变量值。 相关函数 $$ , extract , parse_str , import_request_variables 等等 这里涉及到一个安全函数&#xf…