How do I draw stuff under the text of a UILabel?












0















I created a custom UILabel subclass that has a circle in the middle, and the label's text (which is a number) will be on top of the circle.



I initially thought of doing this using layer.cornerRadius, but that will not create a circle when the label's width and height are not equal.



What I mean is, for a label with width 100 and height 50, I still want a circle with radius 50 and centre at (50, 25).



Therefore, I tried to use UIBezierPath to draw the circle. This is what I have tried:



override func draw(_ rect: CGRect) {
super.draw(rect)
if bounds.height > bounds.width {
let y = (bounds.height - bounds.width) / 2
let path = UIBezierPath(ovalIn: CGRect(x: 0, y: y, width: bounds.width, height: bounds.width))
circleColor.setFill()
path.fill()
} else {
let x = (bounds.width - bounds.height) / 2
let path = UIBezierPath(ovalIn: CGRect(x: x, y: 0, width: bounds.height, height: bounds.height))
circleColor.setFill()
path.fill()
}
}


I have put super.draw(rect) because I thought that would draw the label's text, but when I run the app, I only see the circle and not my label text.



I am very confused because why hasn't super.draw(rect) drawn the label's text?










share|improve this question























  • When drawing/painting, think in the context of a physical canvas, those things you paint will be covered by those things you paint/draw later

    – MadProgrammer
    Jan 3 at 2:29
















0















I created a custom UILabel subclass that has a circle in the middle, and the label's text (which is a number) will be on top of the circle.



I initially thought of doing this using layer.cornerRadius, but that will not create a circle when the label's width and height are not equal.



What I mean is, for a label with width 100 and height 50, I still want a circle with radius 50 and centre at (50, 25).



Therefore, I tried to use UIBezierPath to draw the circle. This is what I have tried:



override func draw(_ rect: CGRect) {
super.draw(rect)
if bounds.height > bounds.width {
let y = (bounds.height - bounds.width) / 2
let path = UIBezierPath(ovalIn: CGRect(x: 0, y: y, width: bounds.width, height: bounds.width))
circleColor.setFill()
path.fill()
} else {
let x = (bounds.width - bounds.height) / 2
let path = UIBezierPath(ovalIn: CGRect(x: x, y: 0, width: bounds.height, height: bounds.height))
circleColor.setFill()
path.fill()
}
}


I have put super.draw(rect) because I thought that would draw the label's text, but when I run the app, I only see the circle and not my label text.



I am very confused because why hasn't super.draw(rect) drawn the label's text?










share|improve this question























  • When drawing/painting, think in the context of a physical canvas, those things you paint will be covered by those things you paint/draw later

    – MadProgrammer
    Jan 3 at 2:29














0












0








0








I created a custom UILabel subclass that has a circle in the middle, and the label's text (which is a number) will be on top of the circle.



I initially thought of doing this using layer.cornerRadius, but that will not create a circle when the label's width and height are not equal.



What I mean is, for a label with width 100 and height 50, I still want a circle with radius 50 and centre at (50, 25).



Therefore, I tried to use UIBezierPath to draw the circle. This is what I have tried:



override func draw(_ rect: CGRect) {
super.draw(rect)
if bounds.height > bounds.width {
let y = (bounds.height - bounds.width) / 2
let path = UIBezierPath(ovalIn: CGRect(x: 0, y: y, width: bounds.width, height: bounds.width))
circleColor.setFill()
path.fill()
} else {
let x = (bounds.width - bounds.height) / 2
let path = UIBezierPath(ovalIn: CGRect(x: x, y: 0, width: bounds.height, height: bounds.height))
circleColor.setFill()
path.fill()
}
}


I have put super.draw(rect) because I thought that would draw the label's text, but when I run the app, I only see the circle and not my label text.



I am very confused because why hasn't super.draw(rect) drawn the label's text?










share|improve this question














I created a custom UILabel subclass that has a circle in the middle, and the label's text (which is a number) will be on top of the circle.



I initially thought of doing this using layer.cornerRadius, but that will not create a circle when the label's width and height are not equal.



What I mean is, for a label with width 100 and height 50, I still want a circle with radius 50 and centre at (50, 25).



Therefore, I tried to use UIBezierPath to draw the circle. This is what I have tried:



override func draw(_ rect: CGRect) {
super.draw(rect)
if bounds.height > bounds.width {
let y = (bounds.height - bounds.width) / 2
let path = UIBezierPath(ovalIn: CGRect(x: 0, y: y, width: bounds.width, height: bounds.width))
circleColor.setFill()
path.fill()
} else {
let x = (bounds.width - bounds.height) / 2
let path = UIBezierPath(ovalIn: CGRect(x: x, y: 0, width: bounds.height, height: bounds.height))
circleColor.setFill()
path.fill()
}
}


I have put super.draw(rect) because I thought that would draw the label's text, but when I run the app, I only see the circle and not my label text.



I am very confused because why hasn't super.draw(rect) drawn the label's text?







ios swift uiview uibezierpath






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Jan 3 at 1:51









SweeperSweeper

70.5k1075143




70.5k1075143













  • When drawing/painting, think in the context of a physical canvas, those things you paint will be covered by those things you paint/draw later

    – MadProgrammer
    Jan 3 at 2:29



















  • When drawing/painting, think in the context of a physical canvas, those things you paint will be covered by those things you paint/draw later

    – MadProgrammer
    Jan 3 at 2:29

















When drawing/painting, think in the context of a physical canvas, those things you paint will be covered by those things you paint/draw later

– MadProgrammer
Jan 3 at 2:29





When drawing/painting, think in the context of a physical canvas, those things you paint will be covered by those things you paint/draw later

– MadProgrammer
Jan 3 at 2:29












1 Answer
1






active

oldest

votes


















1














The text is not seen because the "z-index" of UIBezierPaths depends on the order in which they are drawn. In other words, UIBezierPaths are drawn on top of each other.



super.draw(rect) indeed draws the text. But when you put it as the first statement, it will get drawn first, so everything you draw after that, goes on top of the text. To fix this, you should call super.draw(rect) last:



override func draw(_ rect: CGRect) {
if bounds.height > bounds.width {
let y = (bounds.height - bounds.width) / 2
let path = UIBezierPath(ovalIn: CGRect(x: 0, y: y, width: bounds.width, height: bounds.width))
circleColor.setFill()
path.fill()
} else {
let x = (bounds.width - bounds.height) / 2
let path = UIBezierPath(ovalIn: CGRect(x: x, y: 0, width: bounds.height, height: bounds.height))
circleColor.setFill()
path.fill()
}
super.draw(rect) // <------- here!
}


Alternatively, just subclass UIView, draw the circle in draw(_:), and add a UILabel as a subview of that. The advantage if this approach is that it does not depend on the implementation of super.draw(_:), which might change in the future,






share|improve this answer


























  • Instead of subclassing the UILabel, why not just create a custom view with the UILabel on top, and leave the drawing code in the custom view?

    – meim
    Jan 3 at 5:31











  • @meim I want to make it using as few subviews as possible, because I don't want to add that many constraints on each of them.

    – Sweeper
    Jan 3 at 5:45











  • With this implementation, it's possible in the future your custom drawing code is overwritten by super.draw(rect) since it's a black box inside UILabel's implementation. In the custom view implementation, if you're worried about too many constraints, you can simply set label.frame = bounds in layoutSubviews

    – meim
    Jan 3 at 6:02













  • @meim Oh I see. You do have a point. Edited.

    – Sweeper
    Jan 3 at 6:07











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54015404%2fhow-do-i-draw-stuff-under-the-text-of-a-uilabel%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














The text is not seen because the "z-index" of UIBezierPaths depends on the order in which they are drawn. In other words, UIBezierPaths are drawn on top of each other.



super.draw(rect) indeed draws the text. But when you put it as the first statement, it will get drawn first, so everything you draw after that, goes on top of the text. To fix this, you should call super.draw(rect) last:



override func draw(_ rect: CGRect) {
if bounds.height > bounds.width {
let y = (bounds.height - bounds.width) / 2
let path = UIBezierPath(ovalIn: CGRect(x: 0, y: y, width: bounds.width, height: bounds.width))
circleColor.setFill()
path.fill()
} else {
let x = (bounds.width - bounds.height) / 2
let path = UIBezierPath(ovalIn: CGRect(x: x, y: 0, width: bounds.height, height: bounds.height))
circleColor.setFill()
path.fill()
}
super.draw(rect) // <------- here!
}


Alternatively, just subclass UIView, draw the circle in draw(_:), and add a UILabel as a subview of that. The advantage if this approach is that it does not depend on the implementation of super.draw(_:), which might change in the future,






share|improve this answer


























  • Instead of subclassing the UILabel, why not just create a custom view with the UILabel on top, and leave the drawing code in the custom view?

    – meim
    Jan 3 at 5:31











  • @meim I want to make it using as few subviews as possible, because I don't want to add that many constraints on each of them.

    – Sweeper
    Jan 3 at 5:45











  • With this implementation, it's possible in the future your custom drawing code is overwritten by super.draw(rect) since it's a black box inside UILabel's implementation. In the custom view implementation, if you're worried about too many constraints, you can simply set label.frame = bounds in layoutSubviews

    – meim
    Jan 3 at 6:02













  • @meim Oh I see. You do have a point. Edited.

    – Sweeper
    Jan 3 at 6:07
















1














The text is not seen because the "z-index" of UIBezierPaths depends on the order in which they are drawn. In other words, UIBezierPaths are drawn on top of each other.



super.draw(rect) indeed draws the text. But when you put it as the first statement, it will get drawn first, so everything you draw after that, goes on top of the text. To fix this, you should call super.draw(rect) last:



override func draw(_ rect: CGRect) {
if bounds.height > bounds.width {
let y = (bounds.height - bounds.width) / 2
let path = UIBezierPath(ovalIn: CGRect(x: 0, y: y, width: bounds.width, height: bounds.width))
circleColor.setFill()
path.fill()
} else {
let x = (bounds.width - bounds.height) / 2
let path = UIBezierPath(ovalIn: CGRect(x: x, y: 0, width: bounds.height, height: bounds.height))
circleColor.setFill()
path.fill()
}
super.draw(rect) // <------- here!
}


Alternatively, just subclass UIView, draw the circle in draw(_:), and add a UILabel as a subview of that. The advantage if this approach is that it does not depend on the implementation of super.draw(_:), which might change in the future,






share|improve this answer


























  • Instead of subclassing the UILabel, why not just create a custom view with the UILabel on top, and leave the drawing code in the custom view?

    – meim
    Jan 3 at 5:31











  • @meim I want to make it using as few subviews as possible, because I don't want to add that many constraints on each of them.

    – Sweeper
    Jan 3 at 5:45











  • With this implementation, it's possible in the future your custom drawing code is overwritten by super.draw(rect) since it's a black box inside UILabel's implementation. In the custom view implementation, if you're worried about too many constraints, you can simply set label.frame = bounds in layoutSubviews

    – meim
    Jan 3 at 6:02













  • @meim Oh I see. You do have a point. Edited.

    – Sweeper
    Jan 3 at 6:07














1












1








1







The text is not seen because the "z-index" of UIBezierPaths depends on the order in which they are drawn. In other words, UIBezierPaths are drawn on top of each other.



super.draw(rect) indeed draws the text. But when you put it as the first statement, it will get drawn first, so everything you draw after that, goes on top of the text. To fix this, you should call super.draw(rect) last:



override func draw(_ rect: CGRect) {
if bounds.height > bounds.width {
let y = (bounds.height - bounds.width) / 2
let path = UIBezierPath(ovalIn: CGRect(x: 0, y: y, width: bounds.width, height: bounds.width))
circleColor.setFill()
path.fill()
} else {
let x = (bounds.width - bounds.height) / 2
let path = UIBezierPath(ovalIn: CGRect(x: x, y: 0, width: bounds.height, height: bounds.height))
circleColor.setFill()
path.fill()
}
super.draw(rect) // <------- here!
}


Alternatively, just subclass UIView, draw the circle in draw(_:), and add a UILabel as a subview of that. The advantage if this approach is that it does not depend on the implementation of super.draw(_:), which might change in the future,






share|improve this answer















The text is not seen because the "z-index" of UIBezierPaths depends on the order in which they are drawn. In other words, UIBezierPaths are drawn on top of each other.



super.draw(rect) indeed draws the text. But when you put it as the first statement, it will get drawn first, so everything you draw after that, goes on top of the text. To fix this, you should call super.draw(rect) last:



override func draw(_ rect: CGRect) {
if bounds.height > bounds.width {
let y = (bounds.height - bounds.width) / 2
let path = UIBezierPath(ovalIn: CGRect(x: 0, y: y, width: bounds.width, height: bounds.width))
circleColor.setFill()
path.fill()
} else {
let x = (bounds.width - bounds.height) / 2
let path = UIBezierPath(ovalIn: CGRect(x: x, y: 0, width: bounds.height, height: bounds.height))
circleColor.setFill()
path.fill()
}
super.draw(rect) // <------- here!
}


Alternatively, just subclass UIView, draw the circle in draw(_:), and add a UILabel as a subview of that. The advantage if this approach is that it does not depend on the implementation of super.draw(_:), which might change in the future,







share|improve this answer














share|improve this answer



share|improve this answer








edited Jan 3 at 6:07

























answered Jan 3 at 1:51









SweeperSweeper

70.5k1075143




70.5k1075143













  • Instead of subclassing the UILabel, why not just create a custom view with the UILabel on top, and leave the drawing code in the custom view?

    – meim
    Jan 3 at 5:31











  • @meim I want to make it using as few subviews as possible, because I don't want to add that many constraints on each of them.

    – Sweeper
    Jan 3 at 5:45











  • With this implementation, it's possible in the future your custom drawing code is overwritten by super.draw(rect) since it's a black box inside UILabel's implementation. In the custom view implementation, if you're worried about too many constraints, you can simply set label.frame = bounds in layoutSubviews

    – meim
    Jan 3 at 6:02













  • @meim Oh I see. You do have a point. Edited.

    – Sweeper
    Jan 3 at 6:07



















  • Instead of subclassing the UILabel, why not just create a custom view with the UILabel on top, and leave the drawing code in the custom view?

    – meim
    Jan 3 at 5:31











  • @meim I want to make it using as few subviews as possible, because I don't want to add that many constraints on each of them.

    – Sweeper
    Jan 3 at 5:45











  • With this implementation, it's possible in the future your custom drawing code is overwritten by super.draw(rect) since it's a black box inside UILabel's implementation. In the custom view implementation, if you're worried about too many constraints, you can simply set label.frame = bounds in layoutSubviews

    – meim
    Jan 3 at 6:02













  • @meim Oh I see. You do have a point. Edited.

    – Sweeper
    Jan 3 at 6:07

















Instead of subclassing the UILabel, why not just create a custom view with the UILabel on top, and leave the drawing code in the custom view?

– meim
Jan 3 at 5:31





Instead of subclassing the UILabel, why not just create a custom view with the UILabel on top, and leave the drawing code in the custom view?

– meim
Jan 3 at 5:31













@meim I want to make it using as few subviews as possible, because I don't want to add that many constraints on each of them.

– Sweeper
Jan 3 at 5:45





@meim I want to make it using as few subviews as possible, because I don't want to add that many constraints on each of them.

– Sweeper
Jan 3 at 5:45













With this implementation, it's possible in the future your custom drawing code is overwritten by super.draw(rect) since it's a black box inside UILabel's implementation. In the custom view implementation, if you're worried about too many constraints, you can simply set label.frame = bounds in layoutSubviews

– meim
Jan 3 at 6:02







With this implementation, it's possible in the future your custom drawing code is overwritten by super.draw(rect) since it's a black box inside UILabel's implementation. In the custom view implementation, if you're worried about too many constraints, you can simply set label.frame = bounds in layoutSubviews

– meim
Jan 3 at 6:02















@meim Oh I see. You do have a point. Edited.

– Sweeper
Jan 3 at 6:07





@meim Oh I see. You do have a point. Edited.

– Sweeper
Jan 3 at 6:07




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54015404%2fhow-do-i-draw-stuff-under-the-text-of-a-uilabel%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Monofisismo

Angular Downloading a file using contenturl with Basic Authentication

Olmecas