当前位置:   article > 正文

「OC」暑假第三周——天气预报的仿写

「OC」暑假第三周——天气预报的仿写

「OC」暑假第三周——天气预报的仿写

写在前面

天气预报作为暑假最后的一个项目,算得上我觉得有点用的内容,毕竟用上了网络请求,就是迈出了新的一步,不过就是在网络请求之中其实卡了挺久,第一次使用或多或少出现了问题。写完了任务也是归心似箭,到了家才开始天气预报的总结。

预览

Aug-13-2024 18-21-35

此次天气预报一共实现了三个界面,一个是初始的主页面,供展示我们添加的城市天气以及展示模糊搜索的内容,第二个页面是从模糊搜索之中点入的天气详情页,有将该城市天气添加到主页的功能,第三个页面就是从主页的cell点入的所有天气详情页,可以查看所有已经添加的天气。

UItableView嵌套UICollectionView

image-20240814114438568

为了实现这个圆角控件,我一开始是想要直接使用一个单独的collectionView来进行布局,但是由于前面是tableView,要使得这个圆角控件的风格统一就必须把内容全部写在tableView之中,于是我就开始研究如何进行tableViewCellCollectionView的嵌套。

要实现嵌套,我们就要将实现collectionView所需要的协议放在tableViewCell之中,实现<UICollectionViewDataSource,UICollectionViewDelegate, UICollectionViewDelegateFlowLayout>,然后就在tableViewCell之中开始创建流式布局,创建collectionView,布局大小,就是将之前在控制器之中做的在tableViewCell之中实现,代码如下

#import "SquareTableViewCell.h"
#import "SquareCollectionViewCell.h"
@implementation SquareTableViewCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        
        self.backgroundColor = [UIColor clearColor];
        [self setupCollectionView];
    }
    return self;
}

- (void)setupCollectionView {
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
    layout.minimumInteritemSpacing = 10;
    layout.minimumLineSpacing = 10;
    layout.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);
    
    self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
    self.collectionView.backgroundColor = [UIColor clearColor];
    self.collectionView.delegate = self;
    self.collectionView.dataSource = self;
    [self.collectionView registerClass:[SquareCollectionViewCell class] forCellWithReuseIdentifier:@"SquareCollectionViewCell"];
    [self.contentView addSubview:self.collectionView];
    
    self.collectionView.translatesAutoresizingMaskIntoConstraints = NO;
    [NSLayoutConstraint activateConstraints:@[
        [self.collectionView.topAnchor constraintEqualToAnchor:self.contentView.topAnchor],
        [self.collectionView.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor],
        [self.collectionView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor],
        [self.collectionView.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor]
    ]];
}


- (void)setData:(NSArray *)data {
    _data = data;
    [self.collectionView reloadData];
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return self.data.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    SquareCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"SquareCollectionViewCell" forIndexPath:indexPath];
    
    NSDictionary *item = self.data[indexPath.item];
    [cell configureWithIcon:item[@"icon"] title:item[@"title"] detail:item[@"detail"] subdetail:item[@"subdetail"]];
    
    return cell;
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    CGFloat itemWidth = (self.contentView.bounds.size.width - 40) / 2; 
    return CGSizeMake(itemWidth, itemWidth);
}

@end

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

毛玻璃效果

UIVisualEffectView是从iOS 8开始提供的控件,功能是创建毛玻璃(Blur)效果,也就是实现模糊效果。

我在实现上面的圆角控件时,背景就是使用的是UIVisualEffectView,用于美化外观

UIVisualEffectView的基础使用非常简单,

 UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleRegular];
    UIVisualEffectView *blurView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
    blurView.frame = self.contentView.bounds;
    [self.contentView addSubview:blurView];
  • 1
  • 2
  • 3
  • 4

根据以上代码,我们有几个知识点需要了解一下

  1. UIBlurEffect

    • UIBlurEffectUIVisualEffect 类的子类,用于创建模糊效果。

    • 通过UIBlurEffectStyle

      枚举可以指定不同的模糊效果风格,包括:

      • UIBlurEffectStyleExtraLight:额外亮度模糊效果。
      • UIBlurEffectStyleLight:亮度模糊效果。
      • UIBlurEffectStyleDark:暗色模糊效果。
      • UIBlurEffectStyleRegular:一般模糊效果。
      • UIBlurEffectStyleProminent:显著模糊效果。
  2. UIVisualEffectView

    • UIVisualEffectView 是一个视图类,用于显示视觉效果,比如模糊效果。
    • 它可以包含 UIBlurEffectUIVibrancyEffect 对象,以创建模糊效果或振动效果。
    • 通过将 UIVisualEffectView 添加到视图层次结构中,可以在其上方显示模糊或振动效果,使应用程序的界面看起来更加吸引人。

其实了解了以上的两个知识点,我们就可以正常使用UIVisualEffectView的相关功能了。

在此之外我再介绍一下UIVisualEffectView之中的 UIVibrancyEffect 对象,用在实现在毛玻璃上的特殊书写效果,内容就像是写在这个毛玻璃效果之上的。如果我们需要,可以根据一下流程进行实现

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"back3.jpeg"]];
    // 创建一个模糊效果
    UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
    UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
    blurEffectView.frame = self.view.bounds;
    [self.view addSubview:blurEffectView];

    // 创建一个振动效果
    UIVibrancyEffect *vibrancyEffect = [UIVibrancyEffect effectForBlurEffect:blurEffect];
    UIVisualEffectView *vibrancyEffectView = [[UIVisualEffectView alloc] initWithEffect:vibrancyEffect];
    vibrancyEffectView.frame = self.view.bounds;

    // 在振动效果视图中添加子视图(比如标签)
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 400, 30)];
    label.text = @"Hello, Vibrancy Effect!";

    label.font = [UIFont boldSystemFontOfSize:30];
    label.textAlignment = NSTextAlignmentCenter;
    label.center = vibrancyEffectView.center;
    [vibrancyEffectView.contentView addSubview:label];

    // 将振动效果视图添加到模糊效果视图中
    [blurEffectView.contentView addSubview:vibrancyEffectView];
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

此外,需要注意的是如果我们要将控件添加到UIVisualEffectView之中,我们需要将子控件添加到其 contentView 属性中。

SVGKit库的使用

在关于天气相关的icon,我使用了和风天气API之中自带的icon,根据时刻的天气之中JSON数据,读取到相应的icon编号,利用和风天气自身给出的图片素材库实现了,当前天气icon的展示。

因为xcode似乎不支持SVG格式的图片,所以我们需要引入第三方SVGKit库来进行使用,首先是安装完成集成第三方库的Cocoapods,然后创建podfile文件,在podfile文件之中加入以下代码,并进行保存,最后在终端之中开始install就可以安装好了。

platform:ios,'17.5'

target 'weather' do
 
 pod 'SVGKit', :git => 'https://github.com/SVGKit/SVGKit.git', :branch => '2.x'
 pod 'CocoaLumberjack'


end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

关于SVGKit库的用法:

 NSString *imagename = data[@"icon"];
        
 SVGKImage* image = [SVGKImage imageNamed:imagename];
 image.size = CGSizeMake(40, 40);
 UIImage* iconImage = image.UIImage;
 UIImageView* iView = [[UIImageView alloc] initWithImage:iconImage];

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

就可以直接使用SVG类型的图片格式了

简单的动画实现

在天气预报编写的过程之中,我还加入了一些动画,比如搜索栏从右往左动至导航栏上;在点击搜索框键盘弹出的过程,慢慢添加一个半透明背景。

Aug-14-2024 19-50-24

- (void)keyboardWillShow:(NSNotification *)notification {
    [self.view addSubview:self.dimmedBackgroundView];
    
    [self.view addGestureRecognizer:self.tapGesture];
    [UIView animateWithDuration:0.3 animations:^{
        self.dimmedBackgroundView.alpha = 1;
        [self.view bringSubviewToFront:self.tableView1];
    }];
}
- (void)keyboardWillHide:(NSNotification *)notification {
    [self.view removeGestureRecognizer:self.tapGesture];
    [UIView animateWithDuration:0.3 animations:^{
        self.dimmedBackgroundView.alpha = 0;
        if (self.tableView1.hidden) {
            self.searchContainerView.frame = CGRectMake(self.view.frame.size.width, 0, self.view.frame.size.width, 44);
        }
       
           
    } completion:^(BOOL finished) {
        [self.dimmedBackgroundView removeFromSuperview];
        
    }];
}

-(void)setupSearchBar {
    self.searchBar = [[UISearchBar alloc] init];
    self.searchBar.placeholder = @"搜索城市或机场";
    self.searchBar.delegate = self;
    // 初始化容器视图
    self.searchContainerView = [[UIView alloc] initWithFrame:CGRectMake(self.view.frame.size.width, 0, self.view.frame.size.width, 44)];
    self.searchContainerView.backgroundColor = [UIColor whiteColor]; // 可以根据需要设置背景颜色
    [self.searchContainerView addSubview:self.searchBar];

    // 添加容器视图到导航栏的顶部
    [self.navigationController.navigationBar addSubview:self.searchContainerView];

    // 设置 searchBar 的 frame
    self.searchBar.frame = self.searchContainerView.bounds;
}

- (void)addButtonTapped {
    [UIView animateWithDuration:0.3 animations:^{
           self.searchContainerView.frame = CGRectMake(0, 0, self.view.frame.size.width, 44);
       }];
    
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

我通过判断键盘是否需要回收来,对黑色半透明背景和搜索栏进行动画操作,在搜索栏初始化的时候,我将其设置在了控制器屏幕外的右边,当点击加号按钮时,利用动画将搜索栏移至屏幕正上方,黑色半透明背景也是如此,当键盘弹出时将黑色背景加入并将透明度从0拉到1,当键盘回收时,再将视图透明度从1拉回0,然后再移出当前控制器。

主页之中详情页的编写

在点入主页之中的cell,我使用的是一个滚动视图,然后将详情页变为当前滚动视图所在的控制器的子控制器,然后将详情页控制器的view属性全部添加至滚动视图之中,具体代码如下:

-(void)setupScrollview {
    
    self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
    self.scrollView.showsHorizontalScrollIndicator = NO;
    self.scrollView.contentSize = CGSizeMake( W * self.weatherDataArray.count, 0);
    self.scrollView.pagingEnabled = YES;
    self.scrollView.scrollEnabled = YES;
    self.scrollView.delegate = self;
    self.scrollView.bounces = NO;
    [self.scrollView setContentOffset:CGPointMake( self.index * W, 0)];
    for (int i = 0; i < self.weatherDataArray.count; i++) {
        detailViewController *city = [[detailViewController alloc] init];
        city.cityName = self.weatherDataArray[i][@"cityName"];
        city.name = self.weatherDataArray[i][@"cityID"];
        city.view.frame = CGRectMake(i * W, 0, W, H);
        [self addChildViewController:city];//将详情页控制器作为当前控制器的子控制器
        [self.scrollView addSubview:city.view];
    }
    [self.view addSubview:self.scrollView];
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

总结

暑假的项目学习过程,随着天气预报的完成也是趋近尾声,接下来的日子可以好好回家休息了!!!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/1006468
推荐阅读
相关标签
  

闽ICP备14008679号