当前位置: 首页 > news >正文

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初始化即可。

相关文章:

UIKit之图片浏览器

功能需求 实现一个图片浏览器,点击左右按钮可以切换背景图,且更新背景图对应的索引页和图片描述内容。 分析: 实现一个UIView的子类即可,该子类包含多个按钮。 实现步骤: 使用OC语言,故创建cocoa Touch类…...

如何查看SNMP设备的OID

什么是OID和MIB OID OID 代表对象标识符。 OID 唯一地标识 MIB 层次结构中的托管对象。 这可以被描述为一棵树,其级别由不同的组织分配。MIB MIB(管理信息基)提供数字化OID到可读文本的映射。 使用MIB Browser扫描OID 我的设备是一台UPS SN…...

什么?你设计接口什么都不考虑?

如果让你设计一个接口,你会考虑哪些问题? 1.接口参数校验 接口的入参和返回值都需要进行校验。 入参是否不能为空,入参的长度限制是多少,入参的格式限制,如邮箱格式限制 返回值是否为空,如果为空的时候是…...

2024年3月 青少年等级考试机器人理论真题二级

202403 青少年等级考试机器人理论真题二级 第 1 题 一个机器小车,用左右两个电机分别控制左右车轮,左侧电机转速是100rpm,右侧电机转速是50rpm,则此机器小车?( ) A:原地右转 B&am…...

C语言学习【printf函数和scanf函数】

C语言学习【printf函数和scanf函数】 printf()函数和scanf()函数可以让用户与程序交流,是输入/输出函数 printf()函数 请求printf()函数打印数据的指令要与待打印数据的类型相匹配。例如,打印整数时使用%d,打印字符时使用%c。这些符号被称…...

shell正则表达式

sort命令 以行为单位对文件内容进行排序,也可以根据不同的数据类型来排序 比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。 sort 对行内容进行升序排序 XXX | sort 选项 sort 选项 文件 常用选项&#x…...

react组件渲染性能优化之函数组件-useCallback使用

useCallback主要就是对函数进行缓存,useCallBack这个Hooks主要是解决React.memo不能缓存事件的问题 useCallBack(fn, dependencies) :fn想要缓存的函数,dependencies有关是否更新 fn 的所有响应式值的一个列表 比如:UseCallBackOptimize组件…...

【C++】:string类的基本使用

目录 引言一,string类对象的常见构造二,string类对象的容量操作三,string类对象的访问及遍历操作四,string类对象的修改操作五,string类非成员函数六,整形与字符串的转换 引言 string 就是我们常说的"…...

多线程的代码案例

目录 单例模式 饿汉模式 懒汉模式 阻塞队列 生产者消费者模型意义: 阻塞队列使用方法 实现阻塞队列 阻塞队列实现生产者消费者模型 定时器 实现简单的定时器 工厂模式 线程池 为啥呢? 从池子里面取 比 创建线程 效率更高 线程池的创建 怎么填坑 ThreadPoolExec…...

什么是Java中的设计模式?请列举几种常见的设计模式

一、引言 在软件开发中,设计模式是解决特定设计问题的最佳实践或通用解决方案。Java作为一种广泛使用的编程语言,其设计模式在软件设计和架构中起着至关重要的作用。设计模式不仅提高了代码的可读性和可维护性,还使得代码更加灵活和可扩展。…...

绘制奇迹:Processing中的动态图形与动画

🚀 欢迎回到Processing的世界,你的艺术编程航程刚刚开始。在我们的入门篇中,你已经学会了如何用Processing绘制基本的静态图形。现在,让我们一起探索Processing强大的动态图形和动画功能,释放你的创造力,走…...

Django视图Views

Views视图 HttpRequest 和HttpResponse Django中的视图主要用来接受web请求,并做出响应。视图的本质就是一个Python中的函数视图的响应分为两大类 1)以Json数据形式返回(JsonResponse) 2)以网页的形式返回 2.1)重定向到另一个网页 (HttpRe…...

国内智能搜索工具实战教程

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…...

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

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

QT实现Home框架的两种方式

在触摸屏开发QT界面一般都是一个Home页面,然后button触发进入子页面显示,下面介绍这个home框架实现的两种方式: 1.方式一:用stackedWidget实现 (1)StackedWidget控件在Qt框架中是一个用于管理多个子窗口或…...

机器学习笔记03

1.线性回归(linear regression) 是利用回归方程(函数)对一个或者多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方法。 线性模型: 1.线性关系&#xff1…...

【全面介绍下Spring】

🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…...

MYSQL-存储引擎

存储引擎就是储数据、建立索引、更新/查询数据等技术的实现方式。存储引擎是基于表的,而不是基于库的,所以存储引擎也可被 称为表类型。 存储引擎特点 . InnoDB 介绍 InnoDB是一种兼顾高可靠性和高性能的通用存储引擎,在MySQL 5.5之后,InnoDB是默认的MySQL存储引擎。 >特…...

红蓝对抗 网络安全 网络安全红蓝对抗演练

什么是红蓝对抗 在军事领域,演习是专指军队进行大规模的实兵演习,演习中通常分为红军、蓝军,演习多以红军守、蓝军进攻为主。类似于军事领域的红蓝军对抗,网络安全中,红蓝军对抗则是一方扮演黑客(蓝军&…...

springboot 序列化和反序列化

介绍 在Java中,序列化和反序列化是一种将对象转换为字节流或将字节流转换为对象的机制。通过序列化,可以将对象存储到文件中、传输到网络上,或者在分布式系统中进行对象的传递。本文将详细介绍Java序列化和反序列化的原理、使用方法和常见应用…...

python打卡day49

知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

EtherNet/IP转DeviceNet协议网关详解

一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如&#xff1a…...