【iOS】暑期第一周——ZARA app仿写

目录

  • 前言
  • 无限轮播图
  • 分栏控件和滚动视图
  • 自定义cell
  • 遇到的问题
    • 调整图标大小
    • 单元格附件视图设置
  • 总结

前言

  暑假学习的第一周任务是对ZARA app进行仿写,充分运用之前学习的Objective-C语言和UI控件。我在编写demo的过程中遇到了一些问题,特写该博客作为学习笔记。

无限轮播图

  刚打开ZARA app,我们在首页可以看到有一个商品展示的自动轮播图,无论是用图片两侧的按钮还是自动轮播,商品图片在视觉上给人一种无限循环轮播的效果。无限轮播图实质上是一个UIScrollView滚动视图控件,我们这里可以令ViewController遵循UIScrollViewDelegate协议,然后在

– (void)scrollViewDidScroll:(UIScrollView *)scrollView {}

方法里实现就行。方法里的编写思路是让他滚动到第六张图(注:我首页的无限轮播图为五张),也就是最后一张图时,让第一张图成为他的下一张图。

【代码如下】

//无限轮播实现部分
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {CGFloat contentOffsetX = scrollView.contentOffset.x;CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;CGFloat contentWidth = scrollView.contentSize.width;if (contentOffsetX >= contentWidth - screenWidth) {[scrollView setContentOffset:CGPointMake(screenWidth, 0) animated:NO];self.page.currentPage = 0;} else if (contentOffsetX <= 0) {[scrollView setContentOffset:CGPointMake(contentWidth - 2 * screenWidth, 0) animated:NO];self.page.currentPage = 4;} else {self.page.currentPage = (contentOffsetX / screenWidth) - 1;}
}

至于自动轮播,只需要写一个自动播放的函数,添加视图偏移和控制视图滚动的定时器就可以了,下面给出代码示例:

//自动轮播实现部分(定时器)
- (void)autoScroll
{CGFloat width = [UIScreen mainScreen].bounds.size.width;[_scrollView setContentOffset:CGPointMake(_scrollView.contentOffset.x + width, 0) animated:YES];
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{[self.timer invalidate];self.timer = nil;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{self.timer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(autoScroll) userInfo:nil repeats:YES];
}

至于图片左右的按钮调节部分,只要创建左右两个按钮。调节好Button在视图里的放置位置,为按钮添加事件函数(即按下左按钮,当到第一张图片时,如果继续按下左按钮,将会把滚动视图偏移到最后一张;同理,按下右按钮,当到最后一张图片时,如果继续按下右按钮,将会把滚动视图偏移到第一张),这里主要用到UIPageControl控件。下面给出按下按钮触发的事件函数代码:

//按压按钮触发事件函数
- (void)pressLeft
{[self.timer invalidate];self.timer = nil;int nowPage = _scrollView.contentOffset.x / self.view.frame.size.width;_scrollView.contentOffset = CGPointMake(self.view.frame.size.width * (nowPage - 1), 0);if (nowPage == 1) {_scrollView.contentOffset = CGPointMake(self.view.frame.size.width * 5, 0);}self.timer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(autoScroll) userInfo:nil repeats:YES];
}
- (void)pressRight
{[self.timer invalidate];self.timer = nil;int nowPage = _scrollView.contentOffset.x / self.view.bounds.size.width;_scrollView.contentOffset = CGPointMake( self.view.bounds.size.width * (nowPage + 1), 0);if (nowPage == 6) {_scrollView.contentOffset = CGPointMake(self.view.bounds.size.width * 4, 0);}self.timer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(autoScroll) userInfo:nil repeats:YES];
}

【效果图】
首页的效果图如下:
在这里插入图片描述

分栏控件和滚动视图

  在商品页面,主要是实现滚动视图和分栏控件,并实现分栏控件与滚动视图的同步——在点击分栏控件时,滚动视图会随之变到相应的位置,在滑动视图时,分栏控件同理,一般用于在商品分类展示时,商品类名与图片相对应。思路就是添加代码将滚动视图的偏移量转化成分栏控件的索引,同理在滚动视图也添加受控件索引的偏移函数。下面给出代码示例:

- (void)valueChanged
{NSInteger index = _segControl.selectedSegmentIndex;CGFloat x = index * self.view.frame.size.width;_scrollView.contentOffset = CGPointMake(x, _scrollView.contentOffset.y);
}- (void)scrollViewDidScroll:(UIScrollView *)scrollView {CGFloat offsetX = scrollView.contentOffset.x;CGFloat width = self.view.frame.size.width;NSInteger index = offsetX / width + 0.5;if (_segControl.selectedSegmentIndex != index) {_segControl.selectedSegmentIndex = index;}
}

效果图如下:
在这里插入图片描述

自定义cell

  用户页面本质上就是一个自定义的tableViewCell视图,自定义cell的使用,这里注意不同的位置,cell单元格的高度和内容不同,通过索引来区别和分类进行单元格的绘制都可以。
  除此之外,还需要实现用户在第一个单元格时,进入自己的个人信息页面,只需要给第一个单元格添加事件,该事件需要推出一个新的界面。
这里主要给出新界面的cell函数:

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];if ([self.reuseIdentifier isEqualToString: @"cell"]) {self.imageView2 = [[UIImageView alloc] init];[self.contentView addSubview: _imageView2];self.label1 = [[UILabel alloc] init];[self.contentView addSubview:_label1];self.label2 = [[UILabel alloc] init];[self.contentView addSubview:_label2];}return self;
}

效果图:
在这里插入图片描述
点击第一个单元格后:
在这里插入图片描述

遇到的问题

  在仿写时,遇到的主要问题有两个。第一个是在网上下载的图标通常不是我们想要的尺寸,我们如何得到自己想要的image的大小并重新呈现在画布上;第二个问题是,在用户页面,用户点击单元格选中后,单元格呈现出被点击的灰色状态,如何在用户松手后变回原来的状态。

调整图标大小

下面以商品页面的图标为例,给出代码:

    UIImage *tabImage = [UIImage imageNamed:@"shopping.png"];CGSize newSize = CGSizeMake(30, 30);UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);[tabImage drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();

这里通过使用 UIGraphicsBeginImageContextWithOptions 和相关方法,可以调整图像的大小,并将其用作 UITabBarItem 的图标。
drawInRect:方法中的参数:newSize 是上下文的大小,NO 表示图像是否不透明(透明),0.0 表示使用设备的默认缩放因子。

单元格附件视图设置

一般要用到以下两行代码(这里以cell为示例):

    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;cell.selectionStyle = UITableViewCellSelectionStyleDefault;

下面给出解释:

  • accessoryType 属性用于设置单元格右侧显示的附件视图类型。UITableViewCellAccessoryDisclosureIndicator 是一个右箭头图标,通常用于指示点击该单元格会导航到另一个视图控制器。
    其他可用的 UITableViewCellAccessoryType 类型包括:

UITableViewCellAccessoryNone: 无附件视图
UITableViewCellAccessoryCheckmark: 勾选标记
UITableViewCellAccessoryDetailButton: 详情按钮
UITableViewCellAccessoryDetailDisclosureButton: 详情披露按钮

  • selectionStyle 属性用于设置单元格被选中时的样式。
    UITableViewCellSelectionStyleDefault 是默认的选择风格,通常是灰色背景。
    其他可用的 UITableViewCellSelectionStyle 类型包括:>

UITableViewCellSelectionStyleNone: 无选择风格(即单元格被点击时不会改变背景)
UITableViewCellSelectionStyleBlue: 蓝色背景(已被废弃)
UITableViewCellSelectionStyleGray: 灰色背

总结

  因为离UI学习过去了快两个月,对于部分OC和UI知识有所遗忘,刚开始编写demo会比较慢,在仿写ZARA中比较重要的是自定义cell和TableView,同时也要注意页面的布局,尽量让页面看起来美观。总之,ZARA是UI学习完的基础练手项目,不仅简单回顾了UI的基础知识,也为后面网易云app仿写作了铺垫。

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

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

相关文章

【医疗图像分割】UNETR++论文笔记及代码跑通实践

在医疗图像分割任务中&#xff0c;transformer模型获得了巨大的成功&#xff0c;UNETR提出了efficient paired attention (EPA) 模块&#xff0c;利用了空间和通道注意力来有效地学习通道和空间的特征&#xff0c;该模型在Synapse&#xff0c;BTCV,ACDC,BRaTs数据集上都获得了很…

cf960(div2)

A. Submission Bait&#xff08;博弈&#xff09; 题意&#xff1a;爱丽丝和鲍勃在大小为n的数组a中进行游戏&#xff0c;他们轮流进行运算&#xff0c;爱丽丝先开始&#xff0c;不能运算的一方输&#xff0c;一开始mx0&#xff0c;每次操作&#xff0c;玩家可以选择一个牵引i…

实验1-2 简单求阶乘问题

PTA浙大版《C语言程序设计实验与习题指导&#xff08;第4版&#xff09;》题目集&#xff1a;实验1-2 简单求阶乘问题 #include<stdio.h> int main(){int n;scanf("%d",&n);//此处是输入数值int a,sum1; //a 是循环的次数&#xff1b;sum 是输出数值for(a…

yarn安装electron时报错RequestError:socket hang up

安装electron时候&#xff0c;出现RequestError:socket hang up这样的错误&#xff0c;找了半天很多方式都是用旧淘宝源&#xff0c;导致根本安装不上去。 在项目的根目录下创建.npmrc文件&#xff0c;添加以下内容 # registryhttps://mirrors.huaweicloud.com/repository/np…

Optional类的使用 java8(附代码)

&#x1f370; 个人主页:_小白不加班__ &#x1f35e;文章有不合理的地方请各位大佬指正。 &#x1f349;文章不定期持续更新&#xff0c;如果我的文章对你有帮助➡️ 关注&#x1f64f;&#x1f3fb; 点赞&#x1f44d; 收藏⭐️ 文章目录 一、什么是Optional&#xff1f;二、…

源码拆解SpringBoot的自动配置机制

SpringBoot相比于Spring系列的前作&#xff0c;很大的一个亮点就是将配置进行了简化&#xff0c;引入了自动化配置&#xff0c;仅靠几个注解和yml文件就取代了之前XML的繁琐配置机制&#xff0c;这也是SpringBoot的独有特点&#xff0c;下面我们从源码角度&#xff0c;一点点拆…

【自然语言处理】概论(一):自然语言处理概要

1.1 概论&#xff1a;&#xff08;一&#xff09;自然语言处理概要 知识点 自然语言的定义&#xff1a;人类交流使用的&#xff0c;包括口语和书面语的信息交流方式。AI的终极目标&#xff1a;使计算机具备理解&#xff08;听、读&#xff09;和生成&#xff08;说、写&#…

使用 WebSocket 实现实时聊天

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

PySide(PyQt)使用QPropertyAnimation制作动态界面

主脚本&#xff1a; # encoding: utf-8 import os import sysfrom PySide6.QtCore import QPropertyAnimation, QEasingCurvefrom UIS import *# 主画面类 class MainWindow(QMainWindow, animationButton_ui.Ui_MainWindow):def __init__(self):super().__init__()self.setup…

GitHub狂飙3万star的LLM公开资料 - 大模型入门教程

先用一张图片说明这篇blog多火热&#xff01; 本篇大型语言模型&#xff08;LLM&#xff09;课程分为三个部分&#xff1a; &#x1f9e9; LLM基础&#xff1a;涵盖了数学、Python和神经网络的基本知识。 &#x1f9d1;‍&#x1f52c; LLM科学家&#xff1a;专注于使用最新技…

Spring源码学习笔记之@Async源码

文章目录 一、简介二、异步任务Async的使用方法2.1、第一步、配置类上加EnableAsync注解2.2、第二步、自定义线程池2.2.1、方法一、不配置自定义线程池使用默认线程池2.2.2、方法二、使用AsyncConfigurer指定线程池2.2.3、方法三、使用自定义的线程池Excutor2.2.4、方法四、使用…

【代码】Python3|Scrapy框架初探(汽车之家大连市二手车车辆数据爬取、清洗与可视化)

本篇主要是整个项目的介绍&#xff0c;没提到太多琐碎的技术细节&#xff0c;以后有空的话会整理一下 Scrapy 和原生爬虫的差异&#xff0c;还有它坑人的一些地方&#xff0c;单发出来。 开源地址&#xff1a;https://github.com/shandianchengzi/car_home_spider 使用说明&a…

Vue3扁平化Tree组件的前端分页实现

大家好&#xff0c;我是小卷。得益于JuanTree的扁平化设计&#xff0c;在数据量很大的情况下除了懒加载&#xff0c;使用前端分页也是一种解决渲染性能问题的可选方案。 用法 要实现的文档&#xff1a; 分页效果&#xff1a; 实现 新增属性&#xff1a; 组件setup方法中新增…

科普文:万字梳理31个Kafka问题

1、 kafka 是什么,有什么作用 2、Kafka为什么这么快 3、Kafka架构及名词解释 4、Kafka中的AR、ISR、OSR代表什么 5、HW、LEO代表什么 6、ISR收缩性 7、kafka follower如何与leader同步数据 8、Zookeeper 在 Kafka 中的作用&#xff08;早期&#xff09; 9、Kafka如何快…

MobaXterm 软件安装及使用

MobaXterm 软件安装及使用 1. 引言 MobaXterm是一款功能强大的终端软件&#xff0c;支持SSH、Telnet、RDP、VNC、FTP、SFTP、X11转发和串口等远程会话功能。它使得在Windows系统上进行Linux系统的远程管理和文件传输变得简单便捷。 2. MobaXterm 软件下载 下载链接&#xff…

Python数值计算(13)

1. 数学知识 虽然在给定了N个点以后&#xff0c;通过这个点的最小幂多项式是确定的&#xff0c;但是表达方式可不止一种&#xff0c;例如前面提到的系数方式&#xff0c;根方式&#xff0c;还有插值的Lagrange形式等。这里介绍另外一种表达方式&#xff1a; 显然这个式子最高次…

CTF ssrf 基础入门 (一)

0x01 引言 我发现我其实并不是很明白这个东西&#xff0c;有些微妙&#xff0c;而且记忆中也就记得Gopherus这个工具了&#xff0c;所以重新学习了一下&#xff0c;顺便记录一下吧 0x02 辨别 我们拿到一个题目&#xff0c;他的名字可能就是题目类型&#xff0c;但是也有可能…

Java小抄|Java中的List与Map转换

文章目录 1 List<User> 转Map<User.id,User>2 基础类型的转换&#xff1a;List < Long> 转 Map<Long,Long> 1 List 转Map<User.id,User> Map<Long, User> userMap userList.stream().collect(Collectors.toMap(User::getId, v -> v, …

一个优秀的团队里,往往都有这几种人

“独木不成林&#xff0c;单弦难成曲”&#xff0c;一个优秀的团队&#xff0c;需要团队成员之间形成紧密的合作关系&#xff0c;充分发挥各自的优势和特长时&#xff0c;在各自的岗位发光发热&#xff0c;共同推动团队不断向前发展。一个优秀的团队中不可或缺的几个关键角色&a…

视觉SLAM第二讲

SLAM分为定位和建图两个问题。 定位问题 定位问题是通过传感器观测数据直接或间接求解位置和姿态。 通常可以分为两类&#xff1a;基于已知地图的定位和基于未知地图的定位。 基于已知地图的定位 利用预先构建的地图&#xff0c;结合传感器数据进行全局定位。SLAM中的全局…