【ios】【swift】UILabel的部分圆角样式实现

一、问题描述

由于项目上的银联支付接口新增了优惠码功能,需要在选择支付列表时展示配置的自定义优惠信息(例如“银联上新优惠,快来体验!”)。
美团UI参考

参考了许多App的支付UI,最后决定模仿某团的支付UI实现,通过对左上、右上、右下角切圆角操作完成。

二、解决流程

1 cornerRadius方案(否决)

首先想到的是使用UILabel.layer.cornerRadius(Number)方法,不过刚加上后发现单独使用该方法无效,查阅相关资料后发现需搭配UILabel.layer.masksToBounds(Boolean = true)方法才能显示。该方案有在xib文件修改和代码文件修改两种实现方式,需要在调试时才能展示圆角效果。但是最终由于该方案只能对四个角同时切圆角,故否决,如有需要可选用该部分代码。

1.1 代码文件修改方式
showDiscountLabel.layer.cornerRadius = 7;
showDiscountLabel.layer.masksToBounds = true;

代码文件方式

1.2 xib文件修改方式

⚠️注意:
在User Defined Runtime Attribute下新增这两个属性(如图)。其中layer.cornerRadius设置的类型是Number而非String,layer.masksToBounds设置的类型是Boolean并打勾。
xib文件方式

2 贝塞尔曲线方案

通过贝塞尔曲线的方式,可以实现对部分角切圆角的样式。在方案实现之初发现存在画曲线时获取的宽度为Label根据文本自适应之前的宽度,画曲线之后Label才会根据文本长度做自适应,所以实际使用中会出现文本过长超出框范围或文本过短框展示不全的问题(前辈给的建议是自定义一个Label再重写draw方法,觉得太麻烦了就着手继续改了)。
原本想到的方法是在画曲线前先通过字体大小以及文本内容计算出宽度再赋值给width,但是方法过于繁琐,最后想到了使用sizeToFit自适应大小的方法,通过先实现宽度的自适应后再画曲线的方式成功解决。
贝塞尔曲线解决方式

三、代码展示

1 UI更新代码

⚠️注意:
sizeToFit自适应方法会同时自适应高度和宽度,如果项目不需要高度自适应可以先提取出height的值,在执行自适应后再重新赋值给UILabel.height即可。

private func updateUI(){
	if nil != paySetting {
		iconImageView.setImageURL(paySetting?.bankLogoUri);
		showLabel.text = paySetting?.bankType;
		showTitleLabel.text = paySetting?.title;
		if paySetting?.discountStatus == 1 {
			showDiscountLabel.text = " " + (paySetting?.discountDescription)! + " ";
			// 使用贝塞尔曲线存在问题,画曲线时获取的宽度为自适应前的宽度,故先自适应宽度后再画曲线(保持高度不变)
			let height = showDiscountLabel.height;
			showDiscountLabel.sizeToFit();
			showDiscountLabel.height = height;
			showDiscountLabel.clipRectCorner(direction: [UIRectCorner.topLeft, UIRectCorner.topRight, UIRectCorner.bottomRight], cornerRadius: 7);
		} else {
			showDiscountLabel.alpha = 0;
		}
	}
}
2 贝塞尔曲线代码

通用代码,网上随处可见。

func clipRectCorner(direction: UIRectCorner, cornerRadius: CGFloat) {
	let cornerSize = CGSize(width: cornerRadius, height: cornerRadius);
	let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: direction, cornerRadii: cornerSize);
	let maskLayer = CAShapeLayer();
	maskLayer.frame = bounds;
	maskLayer.path = maskPath.cgPath;
	layer.addSublayer(maskLayer);
	layer.mask = maskLayer;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

布熬夜了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值