仅为部分 UIView 设置背景颜色
Posted
技术标签:
【中文标题】仅为部分 UIView 设置背景颜色【英文标题】:Set background color for only part of UIView 【发布时间】:2013-08-05 17:27:41 【问题描述】:我希望 UIView 的底部(不是一半)与顶部的颜色不同。
我想知道我是否应该创建一个 CGRect 然后给它上色?这是在正确的轨道上吗?
- (void)drawRect:(CGRect)rect
CGRect aRect = CGRectMake(x, y, width, height);
// Fill the rectangle with grey
[[UIColor greyColor] setFill];
UIRectFill( rect );
【问题讨论】:
你需要创建一个 UIView 子类来覆盖 drawRect 方法。 如果有帮助,请批准一个答案。 【参考方案1】:是的,因为您已经覆盖了 drawRect 方法,所以可以这样做。
- (void)drawRect:(CGRect)rect
CGRect topRect = CGRectMake(0, 0, rect.size.width, rect.size.height/2.0);
// Fill the rectangle with grey
[[UIColor greyColor] setFill];
UIRectFill( topRect );
CGRect bottomRect = CGRectMake(0, rect.size.height/2.0, rect.size.width, rect.size.height/2.0);
[[UIColor redColor] setFill];
UIRectFill( bottomRect );
根据需要更改框架内的值。
【讨论】:
当我将您的代码放入我的 .m 文件中时,没有任何反应。 drawRect 是自动调用的,对吧? 你把它放在哪个 .m 文件中?是的,它是自动调用的,但是 drawRect 是 UIView 类的一个方法。你真的要覆盖 UIView 吗? 就像我说的,drawRect是UIView类的一个方法。您必须创建一个覆盖 UIView 的类,并将其添加为 viewcontroller 主视图的子视图【参考方案2】:使用 Swift 5.1 和 ios 13,您可以选择以下两种方式之一来解决您的问题。
#1。使用UIRectFill(_:)
函数在UIView
子类中使用UIColor
实例绘制并填充指定的CGRect
实例
UIKit
提供了一个UIRectFill(_:)
函数。 UIRectFill(_:)
有以下声明:
func UIRectFill(_ rect: CGRect)
用当前颜色填充指定的矩形。
以下 Playground 代码展示了如何使用UIRectFill(_:)
:
import UIKit
import PlaygroundSupport
class CustomView: UIView
override init(frame: CGRect)
super.init(frame: frame)
backgroundColor = UIColor.green
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
override func draw(_ rect: CGRect)
super.draw(rect)
let bottomRect = CGRect(
origin: CGPoint(x: rect.origin.x, y: rect.height / 2),
size: CGSize(width: rect.size.width, height: rect.size.height / 2)
)
UIColor.red.set()
UIRectFill(bottomRect)
let view = CustomView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
PlaygroundPage.current.liveView = view
#2。使用CGContext
的fill(_:)
方法在UIView
子类中使用UIColor
实例绘制并填充指定的CGRect
实例
CGContext
有一个名为fill(_:)
的方法。 fill(_:)
有以下声明:
func fill(_ rect: CGRect)
使用当前图形状态下的填充颜色绘制包含在提供的矩形内的区域。
以下 Playground 代码展示了如何使用fill(_:)
:
import UIKit
import PlaygroundSupport
class CustomView: UIView
override init(frame: CGRect)
super.init(frame: frame)
backgroundColor = UIColor.green
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
override func draw(_ rect: CGRect)
super.draw(rect)
let bottomRect = CGRect(
origin: CGPoint(x: rect.origin.x, y: rect.height / 2),
size: CGSize(width: rect.size.width, height: rect.size.height / 2)
)
UIColor.red.set()
guard let context = UIGraphicsGetCurrentContext() else return
context.fill(bottomRect)
let view = CustomView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
PlaygroundPage.current.liveView = view
【讨论】:
#1 和 #2 哪个更好?【参考方案3】:您还可以将 CALayer 作为子层添加到您的视图中。 包括 CoreGraphics 和 QuartzCore 框架,并在您的 drawRect 方法中创建具有所需形状因子的 CGRect。 使用 rect 实例化一个 CALayer,并使用 [self.layer addSublayer:theLayer] 将其添加到视图层。 在添加之前使用 CALayer 的 -setBackgroundColor: 方法。
如果这是在 View Controller 而不是 View 子类中,请在 viewDidLoad 方法中执行完全相同的操作。
布莱恩
【讨论】:
你的理论很清楚,但给出一些代码对我有帮助。【参考方案4】:您可以使用此代码。请根据您的需要更改 CGRect。
- (void)drawRect:(CGRect)rect
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect topView = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height / 2);
CGRect bottomView = CGRectMake(0, [UIScreen mainScreen].bounds.size.height / 2, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height / 2);
UIColor * grayColor = [UIColor colorWithRed:230.0/255.0 green:230.0/255.0 blue:230.0/255.0 alpha:1.0];
CGContextSetFillColorWithColor(context, grayColor.CGColor);
CGContextFillRect(context, bottomView);
CGContextSetFillColorWithColor(context, [UIColor yellowColor].CGColor);
CGContextFillRect(context, topView);
以下链接可能对您有更多帮助。 http://www.raywenderlich.com/32925/core-graphics-tutorial-shadows-and-gloss
【讨论】:
【参考方案5】:你可以做一个 CGRect 并剪裁一部分来填充。
但是为什么不尝试两个不同的 UIView 并排放置呢?
婆罗门
【讨论】:
【参考方案6】:覆盖 UIView 子类的 drawRect 方法。以下代码将使视图的上半部分变为黑色,视图的下半部分变为红色。
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
// Top View
CGRect topRect = CGRectGetMinX(self.bounds), CGRectGetMinY(self.bounds), CGRectGetMaxX(self.bounds), CGRectGetMaxY(self.bounds);
[[UIColor blackColor] setFill];
UIRectFill(topRect);
// Bottom View
CGRect bottomRect = CGRectGetMinX(self.bounds), CGRectGetMidY(self.bounds), CGRectGetMaxX(self.bounds), CGRectGetMidY(self.bounds);
[[UIColor redColor] setFill];
UIRectFill(bottomRect);
注意:您也只能在子类化 UIView 时覆盖 drawRect: 方法。根据您的评论观点,我感觉这不是您在做的事情。
【讨论】:
当我实现你的代码时,我得到一个错误,“在对象类型 [myUIView] 上找不到属性'frame'”... 你在继承 UIView 吗?如果是这样,那么您应该可以访问 frame 属性。 另外,我认为发布的代码不正确。你想用self.bounds
定义topRect和bottomRect,而不是self.frame
,因为frame
是根据superview的坐标空间,而bounds
是根据view的坐标空间,这就是你的想要自定义绘图。
@ZevEisenberg 这不是错误的,在某些情况下边界很有用。但是在这种情况下,当 UIView 子类被实例化时,框架被设置为其父视图。
在此使用 frame
是不正确的,只要视图的原点不在其父视图的坐标空间中的 0,0 处,或者当视图上存在可能导致 @ 的变换时987654327@ 和 bounds
是不同的。以上是关于仅为部分 UIView 设置背景颜色的主要内容,如果未能解决你的问题,请参考以下文章