「iOS」暑假第一周 —— ZARA的仿写

暑假第一周 ZARA的仿写


文章目录

  • 暑假第一周 ZARA的仿写
    • 写在前面
    • viewDidLoad 之中的优先级
    • 添加自定义字体
      • 下载想要的字体
      • 添加至info之中
      • 找到字体名字并应用
    • 添加应用图标和启动页面

写在前面

暑假第一周留校学习,对于ZARA进行了仿写,在仿写的过程之中,还是遇到了一些问题,此文章就是对在仿写过程之中遇到问题及其解决方案的总结,并且对自己仿写的内容进行展示。

viewDidLoad 之中的优先级

先是在布局我的主页面的时候。使用自动布局去布局scrollView,我发现scrollView似乎进行布局之后并不会把scrollview给布局到主页面的时候,当时遇到这个问题,找不到问题发生的原因,以为是scrollView无法进行自动布局,所以直接使用frame对布局进行赋值,也算是将问题解决了。

但是在编写第二个菜单页面的时候,将scrollViewsegementView结合的时候,又是遇到这个问题了,但是这次就找到了问题所在的地方。

在程序之中 viewDidLoad 我将所有控件都进行布局,包括对scrollView之中的图片进行添加,代码如下:

#import "JCFourth.h"

@interface JCFourth ()<UIScrollViewDelegate>

@property (nonatomic, strong) UISegmentedControl *segmentedControl;
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) NSArray *titles;
@property (nonatomic, strong) NSMutableArray *imageViews;
@property (nonatomic, assign) NSInteger currentIndex;
@property (nonatomic, strong) UIView *lineView;

@end

@implementation JCFourth

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.titles = @[@"女士", @"男士", @"儿童", @"HOME", @"香水"];
    self.currentIndex = 0;
    self.imageViews = [NSMutableArray array];
    
    [self setUpSegmentedControl];
    [self setUpScrollView];
    [self setUpLine];
    [self configureImages];
}



- (void)setUpLine {
    self.lineView = [[UIView alloc] initWithFrame:CGRectZero];
    self.lineView.backgroundColor = [UIColor blackColor];
    self.lineView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:self.lineView];
    
    [NSLayoutConstraint activateConstraints:@[
        [self.lineView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
        [self.lineView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
        [self.lineView.topAnchor constraintEqualToAnchor:self.segmentedControl.bottomAnchor],
        [self.lineView.heightAnchor constraintEqualToConstant:1]
    ]];
}

- (void)setUpSegmentedControl {
    self.segmentedControl = [[UISegmentedControl alloc] initWithItems:self.titles];
    self.segmentedControl.translatesAutoresizingMaskIntoConstraints = NO;
    self.segmentedControl.selectedSegmentIndex = 0;
    [self.segmentedControl addTarget:self action:@selector(segmentChanged:) forControlEvents:UIControlEventValueChanged];
    [self.view addSubview:self.segmentedControl];
    
    
    // 设置背景图像为透明图像
    UIImage *transparentImage = [[UIImage alloc] init];
    [self.segmentedControl setBackgroundImage:transparentImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
    [self.segmentedControl setBackgroundImage:transparentImage forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
    
    [NSLayoutConstraint activateConstraints:@[
        [self.segmentedControl.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
        [self.segmentedControl.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
        [self.segmentedControl.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:100],
        [self.segmentedControl.heightAnchor constraintEqualToConstant:40]
    ]];
    
    
}

- (void)setUpScrollView {
    self.scrollView = [[UIScrollView alloc] init];
    self.scrollView.pagingEnabled = YES;
    self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;
    self.scrollView.showsHorizontalScrollIndicator = NO;
    self.scrollView.showsVerticalScrollIndicator = NO;
    self.scrollView.delegate = self;
    [self.view addSubview:self.scrollView];
    
    [NSLayoutConstraint activateConstraints:@[
        [self.scrollView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
        [self.scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
        [self.scrollView.topAnchor constraintEqualToAnchor:self.segmentedControl.topAnchor],
        [self.scrollView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor constant:-75]
    ]];
}
- (void)configureImages {
    
    for (int i = 0; i < self.titles.count + 2; i++) {
        NSString *imageName;
        UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.scrollView.frame.size.width * i, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height)];
        if (i == 0) {
            imageName = @"香水1.jpg";
        } else if (i == self.titles.count + 1) {
            imageName = @"女士1.jpg";
        } else {
            imageName = [NSString stringWithFormat:@"%@1.jpg", self.titles[i - 1]];
        }
        UIImage *image = [UIImage imageNamed:imageName];
        if (image) {
            imageView.image = image;
        } else {
            NSLog(@"Image not found: %@", imageName);
        }
        imageView.contentMode = UIViewContentModeScaleAspectFill;
        imageView.clipsToBounds = YES; // 确保裁剪内容
        [self.scrollView addSubview:imageView];
        [self.imageViews addObject:imageView];
    }
    self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * (self.titles.count + 2), self.scrollView.frame.size.height);
    
    CGPoint contentOffset = CGPointMake(self.scrollView.frame.size.width, 0);
    [self.scrollView setContentOffset:contentOffset animated:NO];
}

- (void)segmentChanged:(UISegmentedControl *)sender {
    NSInteger index = sender.selectedSegmentIndex;
    [self.scrollView setContentOffset:CGPointMake(self.view.frame.size.width * (index + 1), 0) animated:YES];
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    CGFloat offsetX = scrollView.contentOffset.x;
    CGFloat pageWidth = scrollView.frame.size.width;
    
    int index = (int)(offsetX / pageWidth + 0.5) % ((int)self.imageViews.count + 2);
    if (index == 0) {
        self.segmentedControl.selectedSegmentIndex = 4;
    } else if (index == 6) {
        self.segmentedControl.selectedSegmentIndex = 0;
    } else {
        self.segmentedControl.selectedSegmentIndex = index - 1;
    }
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    CGFloat offsetX = scrollView.contentOffset.x;
    CGFloat pageWidth = scrollView.frame.size.width;
    
    if (offsetX >= pageWidth * 6) {
        // 滚动到假的最后一页,瞬间跳到实际第一页
        [self.scrollView setContentOffset:CGPointMake(pageWidth, 0) animated:NO];
    } else if (offsetX <= 0) {
        // 滚动到假的第一页,瞬间跳到实际最后一页
        [self.scrollView setContentOffset:CGPointMake(pageWidth * 5, 0) animated:NO];
    }
    

}

@end

scrollView之中的图片内容是空白的,我们得到的界面是这样的:

image-20240710220003258

其实在 viewDidLoadscrollView是已经布局在了界面之上,但是为什么没有画面呢?是因为在自动布局的过程之中分为几个阶段:

  1. viewDidLoad 阶段:在 viewDidLoad 方法中,我们在其中创建和配置视图的约束,但实际的布局计算和应用尚未发生。
  2. viewWillAppear: 阶段:在视图控制器即将显示之前,自动布局系统会进行一次布局计算和应用。在这个阶段,系统会根据视图的约束来计算视图的大小和位置,并应用于屏幕上的实际视图。
  3. viewDidLayoutSubviews 阶段:在视图控制器视图的布局发生变化时,例如设备旋转、状态栏变化或者视图控制器自身布局发生变化时,自动布局系统会再次进行布局计算和应用。这个阶段是在视图完成布局后调用的,所以对于scrollView之中的图片内容,应该是在自动布局计算结束之后,可以在 viewDidLayoutSubviews 方法中进行进一步的布局调整或更新。

因此,虽然我们在 viewDidLoad 方法中创建和配置视图的约束,但实际的布局计算和应用发生在稍后的阶段,主要是在 viewWillAppear:viewDidLayoutSubviews 阶段。由于在 viewDidLoad 方法中实际的布局计算和应用尚未发生,所以在 viewDidLoad 方法中尝试设置图片视图的位置或大小,无法得到预期的结果。

那解决方法其实很简单,我们只要将将 configureImages 方法放在 viewDidLayoutSubviews 方法中以确保在正确的时机设置图片视图的尺寸。

而在 viewDidLayoutSubviews 方法中,视图层次结构已经完成布局,并且子视图的大小和位置已经确定。这是因为 viewDidLayoutSubviews 方法在每次视图布局发生变化时都会被调用,包括视图控制器的初始布局以及后续的布局更改,例如设备旋转、状态栏变化或者视图控制器自身布局发生变化。

因此,将 configureImages 方法放在 viewDidLayoutSubviews 方法中,可以确保在正确的时机设置图片视图的尺寸,以适应当前的布局状态。这样,无论是初始布局还是后续的布局更改,都能够正确地显示图片在 UIScrollView 中。

总结起来,将 configureImages 方法放在 viewDidLayoutSubviews 方法中是为了确保在视图布局完成后再设置图片视图的尺寸,以适应当前的布局状态。这样可以解决图片在 UIScrollView 中无法正确显示的问题。

image-20240710220816229

最后结果如上图。

添加自定义字体

在仿写NARA的过程之中,我发现自带的字体和logo本身的差距较大,于是想着自己找个更美观的艺术字来进行使用,于是学习了如何添加字体。

下载想要的字体

在网上查找相关的字体下载网站,下载后缀为.ttf 或者为 .otf的文件,与添加图片类似,直接将文件拖拽至项目之中,记得勾选add to target

image-20240711162325798

添加至info之中

然后打开info文件,在Imformation property List的目录下添加 “Fonts provided by application”的文件

image-20240711162723017

最后添加文件的全称(加上后缀),添加到这个文件夹之下

image-20240711162933822

找到字体名字并应用

因为可能存在字体本身的名字和我们添加的.ttf的文件上的名字不同,那么我们就要找出所属的字体名字。我们可以用上这个程序:

    for(NSString *familyname in [UIFont familyNames]){
          NSLog(@"family: %@",familyname);
          for(NSString *fontName in [UIFont fontNamesForFamilyName:familyname]){
              NSLog(@"----font: %@",fontName);
          }
          NSLog(@"--------------");
    }

这段代码的意思就是,是打印出所有非系统字体的类以及具体的字体名字,这是一个很直接的方法,但由于xcode也有自带的非系统字体,那么如果字体原先的名字和我们使用的.ttf文件的差别很大的话,我们要将他们找出来的话还是很麻烦的,不过一般情况下字体自身的名字是会和我们添加的.ttf文件名字相等的。

找到字体名字之后我们可以使用+ (nullable UIFont *)fontWithName:(NSString *)fontName size:(CGFloat)fontSize; 的方法对字体进行运用

UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
    titleLabel.text = @"ZARA";
    titleLabel.font = [UIFont fontWithName:@"TimesNewRomanPS-BoldItalicMT" size:60];
    titleLabel.textAlignment = NSTextAlignmentLeft;

经过以上的操作我们就可以使用自定义的字体啦

image-20240711164126407

添加应用图标和启动页面

应用图标和启动页面又被称作app icon和launch image

对于应用图标的使用其实很简单

我们在左侧菜单栏找到Assets,点进去后右键在iOS选项之中点击添加New iOS App icon,然后将自己想要的图片放入即可。(注:要求的图片应该是1024✖️1024 pt)

image-20240711201919289

那么对于启动页面,我们可以在左侧菜单栏的Launch Screen之中将相应的图片界面给手动添加进去,如下图所示

image-20240711202756493

将以上的内容综合一下,我们就得到了具备应用图标和启动页面,看起来有点像模像样的ZARA啦

Jul-11-2024 20-28-43

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

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

相关文章

探索创意无限:独特的平面设计趋势与案例分享

随着平面设计领域的不断发展&#xff0c;平面设计趋势也在不断变化。在一个信息爆炸的时代&#xff0c;设计不仅仅是视觉的表达&#xff0c;更是思想和情感的交流。到了 2024 年&#xff0c;一些新的平面设计趋势已经开始显现&#xff0c;同时一些旧的趋势得到了新的发展和再度…

Jenkins安装部署与配置

目录 前言 Jenkins 的主要功能 Jenkins 的工作流程 一. 环境准备 二. 安装JDK 三. 安装Tomcat 四. 部署Jenkins 五. 浏览器访问 六. 修改超级管理员默认密码 七. 系统配置 八. 安装插件 九. 手动部署插件 前言 Jenkins 是一个开源的自动化服务器&#xff0c;用于…

C# 串口数据转网口实现空气风速风向检测

1.窗体搭建 添加time(定时器) 因为需要风速和风向自动刷新 2.进行网口空气检测 ①服务器连接按钮 // 连接按钮private void button1_Click(object sender, EventArgs e){if (button1.Text "连接"){ConnectSocke();// 连接服务器}else{CloseSocket(); // 关闭服务器…

苹果提出RLAIF:轻量级语言模型编写代码

获取本文论文原文PDF&#xff0c;请在公众号【AI论文解读】留言&#xff1a;论文解读 代码生成一直是一个充满挑战的领域。随着大型语言模型&#xff08;LLM&#xff09;的出现&#xff0c;我们见证了在自然语言理解和生成方面的显著进步。然而&#xff0c;当涉及到代码生成&a…

XD文件打开神器:这个在线工具你一定要试试!

你有没有遇到过对设计师发来的XD文件没有头绪&#xff1f;不知道XD文件深层含义&#xff1f;如何打开XD文件最省时省力&#xff1f;这篇文章告诉你答案。 https://ad.js.design/online/xd/?sourcecsdn&planxy711 XD文件是什么&#xff1f; 事实上&#xff0c;XD文件就是…

C++入门基础篇(1)

欢迎大家来到海盗猫鸥的博客—— 断更许久&#xff0c;让我们继续好好学习吧&#xff01; 目录 1.namespace命名空间 命名空间的存在价值&#xff1a; 命名空间的定义&#xff1a; 命名空间的使用&#xff1a; 2.C输入输出函数 使用&#xff1a; 3.缺省参数 4.函数重载…

界面组件Kendo UI for React 2024 Q2亮点 - 生成式AI集成、设计系统增强

随着最新的2024年第二季度发布&#xff0c;Kendo UI for React为应用程序开发设定了标准&#xff0c;包括生成式AI集成、增强的设计系统功能和可访问的数据可视化。新的2024年第二季度版本为应用程序界面提供了人工智能(AI)提示&#xff0c;从设计到代码的生产力增强、可访问性…

linux-5.10.110内核源码分析 - Freescale ls1012a pcie msi中断

1、dts msi控制器描述 1.1、dts描述 msi: msi-controller11572000 {compatible "fsl,ls1012a-msi";reg <0x0 0x1572000 0x0 0x8>;msi-controller;interrupts <0 126 IRQ_TYPE_LEVEL_HIGH>; };ls1012a msi控制器具体介绍可以参考官网手册”25.1.1 PC…

【cocos creator】2.x,伪3d拖拽,45度视角,60度视角,房屋装扮

伪3d拖拽,45度视角,60度视角 工程下载:(待审核) https://download.csdn.net/download/K86338236/89530812 dragItem2.t s import mapCreat2 from "./mapCreat2";const {ccclass, property } = cc._decorator; /*** 拖拽类,挂在要拖拽的节点上*/ @ccclass export…

电影购票小程序论文(设计)开题报告

一、课题的背景和意义 随着互联网技术的不断发展&#xff0c;人们对于购票的需求也越来越高。传统的购票方式存在着排队时间长、购票流程繁琐等问题&#xff0c;而网上购票则能够有效地解决这些问题。电影购票小程序是网上购票的一种新型应用&#xff0c;它能够让用户随时随地…

MacOS可以玩什么游戏 苹果笔记本电脑能打游戏吗 macbook能打什么游戏

长期以来&#xff0c;Mac电脑在游戏方面的局限性一直是用户关注的问题。在最新的 macOS Sonoma 14 系统中&#xff0c;苹果首次引入了全新的 Game mode&#xff08;游戏模式&#xff09;&#xff0c;将 M 系列芯片的超强能力在游戏中进一步释放&#xff01; Mac 不能玩游戏的难…

Fragment(未完结)

什么是Fragment? 1:具备生命周期,小Activity 2:必须委托在activity中才能运行 Fragment初体验 1、创建fragment_blank.xml <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools&qu…

一进四出学生公寓电表功能对比

一进四出学生公寓对比石家庄光大远通电气有限公司产品使用功能&#xff1a;预收费功能&#xff1a;用户应先到学校购电处购电,售电计算机将在十秒钟内自动将数据发送到控电柜各个用电单元,然后系统会给用户供电,当用户剩余电量为零时,系统可自动切断该单元供电,只有当用户重新购…

MYSQL审批流程判断同一层级审批人是否全部通过审批

在做流程审批的时候&#xff0c;通常会出现某一层有多个审批人的情况&#xff0c;这个时候需要所有人都通过才会进入到下一步 数据结构如下图表格所示 每一个审批申请对应一个apply_id serial_no相同的代表是同一层级审批人 approval_status是审核状态 下面我们可以用一个SQL来…

[leetcode]circular-array-loop 环形数组是否存在循环

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:bool circularArrayLoop(vector<int>& nums) {int n nums.size();auto next [&](int cur) {return ((cur nums[cur]) % n n) % n; // 保证返回值在 [0,n) 中};for (int i 0; i < n; i…

【UE5.1】NPC人工智能——01 准备NPC角色

效果 步骤 1. 之前我们已经创建了“BP_NPC”&#xff08;见&#xff1a;【UE5.1 角色练习】06-角色发射火球-part2&#xff09; 该蓝图继承于角色类 我们在该蓝图中添加了两个方法和两个变量。方法一个是用于修改角色HP值的&#xff0c;另一个是在收到伤害后执行的逻辑。两个…

AIGC爬虫类代码示例:Scrapy和OpenAI API实现抓取内容并生成内容

对于我从事爬虫行业多年的经验来说&#xff0c;编程各种需求代码真是非常吃力且细致的活&#xff0c;随着AI的大火&#xff0c;我在设想有没有可能通过AI自动化程序实现自动抓取生成想要的文本内容。前提我是打算通过结合爬虫技术&#xff08;如Scrapy&#xff09;和生成式AI模…

Affnity 值得购买吗?有Affinity 优惠码?

今年&#xff0c;Affinity 提供了全场 7 折优惠活动&#xff0c;这里包括桌面应用、插件、工作手册等内容&#xff0c;另外针对 iPad 应用提供更为给力的 5 折优惠&#xff01;对于从事图形设计、排版的用户来说&#xff0c;由于 Affinity 的创意设计应用均采用了一次买断制&am…

如何在函数中使用return返回axios的请求结果

使用场景&#xff1a;在添加学生上课记录的时候&#xff0c;需要先获取学生的剩余课时&#xff0c;需要通过接口获取。所以需要封装一个方法&#xff0c;能够通过接口获取学生的课时数量。 解决方案&#xff1a;通过异步解决 封装方法的代码如下&#xff1a; const getStude…

Linux--安装VMware步骤

安装VMware VMware Desktop Hypervisors for Windows, Linux, and Mac 复制链接打开浏览器下载即可 从官网下载软件&#xff0c;完成后为确保后续正常使用&#xff0c;需要检查虚拟网卡是否安装完成 检查虚拟网卡的安装步骤 Windows--设置--高级设置--网络适配器--看是否有显…