iOS之Drawing<1>

本文介绍如何在iOS应用中创建尺寸可变的图片。通过使用UIImage的resizableImageWithCapInsets方法,开发者可以根据需要调整图片大小并选择铺瓷砖或拉伸的方式填充背景。文章还提供了具体的Swift代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在iOS应用中,用户看到的一切都是视图(UIView),视图是有内容(content)的,包含图画。一个空白的视图可以任意绘画,你的代码决定视图绘制什么内容。

尺寸可变的图片(重要):

界面的某些地方有时候需要一张尺寸可变的图片。比如,有时候,你想要用一张图片以铺瓷砖或者拉伸的方式来填充背景。为了制作一张尺寸可变的图片,利用一张普通的图片,调用它的resizableImageWithCapInsets(capInsets:, resizingMode:) -> UIImage方法。参数解释如下:
- capInsets:类型是UIEdgeInsets,里面的四个参数代表的是距离图片四边的内边距
- resizingMode:如果上下文要比图片大的话,尺寸可变的图片会有两种表现形式,取决于该参数的值。.Tile以铺瓦转的形式用图片铺满内容;.Stretch图片以拉伸的形式填充满内容。

假设UIImageView高度和宽度是固定的(这样就不会采用图片的尺寸了),而且contentMode.ScaleToFill(这样图片就会表现出可变的行为)

首先使用.Tile样式:

let v=UIImage(named: "star.png")
        let //vr=v?.resizableImageWithCapInsets(UIEdgeInsetsZero, resizingMode: .Tile)
let vr=v!.resizableImageWithCapInsets(UIEdgeInsetsMake(v!.size.height/4.0, v!.size.width/4.0, v!.size.height/4.0, v!.size.width/4.0), resizingMode: .Tile)

self.iv=UIImageView(image: vr)
self.iv!.frame=CGRect(x: 100, y: 100, width: 100, height: 100)

我们再来看一下.Stretch样式

let vr=v!.resizableImageWithCapInsets(UIEdgeInsetsMake(v!.size.height/4.0, v!.size.width/4.0, v!.size.height/4.0, v!.size.width/4.0), resizingMode: .Stretch)

通常的拉伸策略是让接近初始图片的一半作为CapInset,只留下中心的1或者2像素。

let vr=v!.resizableImageWithCapInsets(UIEdgeInsetsMake(v!.size.height/2.0-1, v!.size.width/2.0-1, v!.size.height/2.0-1, v!.size.width/2.0-1), resizingMode: .Stretch)

当然,我们不用代码就可以配置一个尺寸可变的图片,方法是在asset catalog中配置:选中图片——在属性检查器—Slicing部分配置,如图:

using AIToy.Common; using System.Collections.ObjectModel; using System.ComponentModel; namespace AIToy.Pages.My; public partial class UpdateResources : BasePage { public ObservableCollection<MenuItem> MenuItems { get; set; } = new(); public UpdateResources() { InitializeComponent(); LoadMenuItems(); BindingContext = this; } private async void LoadMenuItems() { await Task.Run(() => { var data = GenerateMenuItems(); Dispatcher.Dispatch(() => { MenuItems.Clear(); foreach (var item in data) MenuItems.Add(item); }); }); } private List<MenuItem> GenerateMenuItems() { var female = new[] { "female01", "female02", "female03", "female04", "female05", "female06" }; var male = new[] { "male01", "male02", "male03", "male04", "male05", "male06" }; var result = new List<MenuItem>(12); for (int i = 0; i < 12; i++) { result.Add(new MenuItem { Name = i > 5 ? female[i - 6] : male[i], SubItems = new ObservableCollection<SubItem> { new() { Name = "视频" }, new() { Name = "音频" } } }); } return result; } public class MenuItem : INotifyPropertyChanged { public string Name { get; set; } public ObservableCollection<SubItem> SubItems { get; set; } = new(); private bool _isChecked; public bool IsChecked { get => _isChecked; set { _isChecked = value; foreach (var subItem in SubItems) { subItem.IsChecked = value; } OnPropertyChanged(); } } private bool _isExpanded = true; public bool IsExpanded { get => _isExpanded; set { _isExpanded = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public class SubItem : INotifyPropertyChanged { public string Name { get; set; } private bool _isChecked; public bool IsChecked { get => _isChecked; set { _isChecked = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }<?xml version="1.0" encoding="utf-8" ?> <common:BasePage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="AIToy.Pages.My.UpdateResources" xmlns:common="clr-namespace:AIToy.Common" xmlns:m="clr-namespace:AIToy.Manager" xmlns:controls="clr-namespace:AIToy.Controls" Title="UpdateResources" BackgroundColor="#0D0C0D"> <ScrollView> <VerticalStackLayout Padding="20" Spacing="15"> <Label Text="资源管理器" FontSize="24" FontAttributes="Bold" HorizontalOptions="Center"/> <Border Stroke="#512BD4" StrokeThickness="2" StrokeShape="RoundRectangle 10" Padding="10"> <VerticalStackLayout Spacing="10"> <CollectionView ItemsSource="{Binding MenuItems}"> <CollectionView.ItemTemplate> <DataTemplate> <VerticalStackLayout Spacing="5"> <Grid> <CheckBox IsChecked="{Binding IsChecked}" VerticalOptions="Center"/> <Label Text="{Binding Name}" FontSize="18" FontAttributes="Bold" Margin="30,0,0,0"/> </Grid> <BoxView HeightRequest="1" Color="LightGray" Margin="30,0,0,0"/> <StackLayout Margin="30,0,0,0" Spacing="5" IsVisible="{Binding IsExpanded}"> <CollectionView ItemsSource="{Binding SubItems}"> <CollectionView.ItemTemplate> <DataTemplate> <Grid> <CheckBox IsChecked="{Binding IsChecked}" VerticalOptions="Center"/> <Label Text="{Binding Name}" Margin="30,0,0,0"/> </Grid> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> </StackLayout> </VerticalStackLayout> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> </VerticalStackLayout> </Border> </VerticalStackLayout> </ScrollView> </common:BasePage> 这是.net maui代码,加载需要6-7秒,如何优化让他秒开,前端写死也行
08-07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值