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

暑假第一周 ZARA的仿写


文章目录

写在前面

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

viewDidLoad 之中的优先级

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

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

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

objc 复制代码
#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之中的图片内容是空白的,我们得到的界面是这样的:

其实在 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 中无法正确显示的问题。

最后结果如上图。

添加自定义字体

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

下载想要的字体

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

添加至info之中

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

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

找到字体名字并应用

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

obj 复制代码
    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; 的方法对字体进行运用

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

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

添加应用图标和启动页面

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

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

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

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

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

相关推荐
文件夹__iOS9 小时前
SwiftUI 核心选型:class + ObservableObject VS struct + @State
ios·swiftui·swift
开开心心就好14 小时前
解决打印机共享难题的实用工具
人工智能·vscode·游戏·macos·音视频·语音识别·媒体
Digitally15 小时前
如何顺畅将传音 Infinix 数据传输到 Mac?
macos
SameX15 小时前
独立开发了一款健康记录 App,聊聊几个让我纠结很久的设计决策
ios
报错小能手15 小时前
Swift UI 框架 实战 简易计数器、待办清单 、随机壁纸图库、个人笔记
ui·ios
游戏开发爱好者817 小时前
深入理解iOSTime Profiler:提升iOS应用性能的关键工具
android·ios·小程序·https·uni-app·iphone·webview
for_ever_love__1 天前
UI学习:多界面传值的正向传值(属性传值)和反向传值(代理传值)
学习·ui·ios·objective-c
开心就好20251 天前
全面介绍iOS开发工具:Xcode、AppCode、CocoaPods、Fastlane和Git
后端·ios
懋学的前端攻城狮1 天前
数据持久化与缓存策略:在离线与在线间架起桥梁
ios·swift
~央千澈~2 天前
以cocos3.8.8开发的游戏为例商业实战项目举例cocos打包ios苹果安装包ipa完整详细教程-优雅草卓伊凡
ios