Icons & Image in SwiftUI

3,294 阅读4分钟

这节主要讲iOS 系统中icon的和Image在SwiftUI中的使用

  1. icons
  2. Image

Icons

使用系统图片几乎和使用自定义图片一样,但是一个重点不同的地方是,我们需要使用 Image(systemName:) 方法来加载系统图片。例如下面代码,加载了系统内置的心跳 icon.

那么 icon 在哪里可以找到了?其实系统有一个专门的app,你可以下载就可以看到对应的icon,只需要复制icon的名称,使用Image(systemName:) 方法即可显示。 地址:developer.apple.com/sf-symbols/

image.png

但是上面的代码和展示是有问题的,我设置了frame 宽和高都是200,但是图片很小。这是为什么呢?

这时我们需要引入一个新的 属性 resizable。 在 SwiftUI 中,Image 视图提供了 .resizable() 修饰符,用于指定图像在显示时是否可以自动调整大小。当您在创建 Image 视图时,如果使用了 .resizable() 修饰符,那么图像将允许在其所在的父容器中自由调整大小,以适应不同的尺寸要求

使用 .resizable() 修饰符时,通常还需要指定图像的 aspectRatio ,以确保图像按比例进行调整。您可以通过设置 aspectRatio 参数来指定图像的宽高比,或者使用 scaledToFit()scaledToFill() 方法来指定调整大小的方式。

image.png 设置图像比例 4:3,填充模式是 .fit

image.png

以下是同一个图片的不同填充模式, 效果对比。这里我用了一个线来风格,加强范围对比。可以看到使用fill填充的图片其实已经超过了父视图的大小了。

image.png

此时我们可以使用 clipped 来剪裁超出父视图的大小的部分

image.png

那么 .fit 和 .fill 有什么区别了? 下面做了简单的对比

.fit:

  • 当使用 .fit 作为 aspectRatio 参数时,图像会按照原始的宽高比例进行缩放,以适应父容器的大小,并保持图像的完整内容显示在父容器内。
  • 这意味着图像会按比例缩放,直到其中一个维度(宽度或高度)达到父容器的边界,另一个维度可能会超出父容器而被裁剪掉。
  • 如果父容器的宽高比例和图像的宽高比例不一致,图像会被自动裁剪,以适应父容器的边界。

.fill:

  • 当使用 .fill 作为 aspectRatio参数时,图像会按照原始的宽高比例进行缩放,以填满整个父容器,保持图像的内容不变形。
  • 这意味着图像会按比例缩放,直到完全覆盖父容器的边界,但可能会有一部分图像超出父容器的边界。
  • 如果父容器的宽高比例和图像的宽高比例不一致,图像会被拉伸以填满整个父容器,但不会保持原始比例,可能导致图像内容变形。

renderingMode

SwiftUI 中,Image 视图提供了 renderingMode 属性,用于指定图片的渲染模式。这个属性允许您在显示图像时更改其显示样式,包括颜色透明度等效果

image.png

VStack {
            Image(systemName: "lamp.table.fill")
                .renderingMode(.original)
                .resizable()
                .aspectRatio(0.75, contentMode: .fit)
//                .foregroundColor(Color.orange)
                .frame(width: 200, height: 200)
            
            Image(systemName: "lamp.table.fill")
                .renderingMode(.template)
                .resizable()
                .aspectRatio(0.75, contentMode: .fit)
                .foregroundColor(Color.orange)
                .frame(width: 200, height: 200)
        }

我们只改变了渲染模式,就可以来改变原始图片的颜色和透明度了

这里的 VStack 是一个布局容器,允许容器内的组件以竖直方向来布局UI元素

那么renderingMode 属性的作用是啥了。我们来对比看看

renderingMode 是一个 Image.RenderingMode 枚举,包含以下几个选项:

  • .original:显示原始图像,不进行任何渲染修改。图像将以其原始颜色显示。
  • .template:将图像视为模板图像。这意味着图像的颜色将被忽略,而是使用它所在视图的前景色(foregroundColor)进行填充。适用于图标,使其根据前景色自动适应外观。

Image

我们的项目不光有系统的icon,也会有很多设计师给的图片,或者是一些 placeholder图片。这个时候就需要用到加载图片的函数,加载的代码如下,

Steve_jobs 是一张图片名称,具体效果如下

Image("steve_jobs")
            .resizable()
            .scaledToFit()
            .frame(width: 300, height: 300)
            .clipped()
            .cornerRadius(150)

image.png

其实和使用系统的icon没有什么大的差别

当你想把图片变成圆形时,上面提供了一种方法,当然你还可以使用其他方法来完成

系统提供了 clipshape 方法,允许你使用一个图形来作为剪切图片的参照

image.png

struct IconsAndImageSample: View {
    var body: some View {
        Image("steve_jobs")
            .resizable()
            .scaledToFit()
            .frame(width: 300, height: 300)
            .clipShape(Ellipse())
    }
}

也可以变成一个有圆角的图形

image.png

struct IconsAndImageSample: View {
    var body: some View {
        Image("steve_jobs")
            .resizable()
            .scaledToFit()
            .frame(width: 300, height: 300)
            .clipShape(RoundedRectangle(cornerRadius: 25.0))
    }
}

好了,icon和imag就介绍这么多。谢谢观看!