I have a view that has a bunch of labels and buttons on it with existing data. What I would like to do is to have a rounded rect with a group of labels and buttons inside them, I have about 2 groups and I would like each group to have their own rounded rect. Also I would like a line to separate the rounded rects from each other, but I heard that a label can do that just fine.
The reason I ask of this is because various tutorials and methods online specify to override the drawRect function. However, I am not sure if this will override any of my labels and buttons being rendered or their functionality.
Overriding drawRect for a view does not affect how any of its subviews are drawn, if that answers your question.
In other words, drawing a line in the background of a view will not change how labels or buttons inside that view are drawn.
However, for this effect I don't know if you need to use drawRect. If you import the QuartzCore library, you can draw a rounded rect using an ordinary view:
Just create an ordinary view behind or as a container for your buttons and labels and set it's layer.borderWidth, layer.borderColor and layer.cornerRadius properties.
Related
In this view
there are multiple subviews. Now I configured the views to drop a shadow as shown in the screenshot: The views are dropping the shadow also over the other views. Do you see a way to easily drop the shadow behind all views? So z-index of all the shadows < z-index of all the views.
I already tried to create an additional view for each box and placed all of this shadow views behind all boxes. This kind of works. But there is a lack when moving the boxes around using a PanGesture. Also this design looks a it messy. At the moment, it's a clear design to have one UIView for each box.
You're thinking about the solution wrong. However in your own words, 'behind all views' is the answer.
As you noticed, applying a shadow to each view will have overlapping shadows due to each views z-index.
You mentioned creating an additional view for each box which is close to another solution but not quite. You could create a single container view and place all of the boxes inside this one container view. Then apply your shadow to the container view. This will give you your result, but will have horrible performance! Every time layoutSubviews is called, such as when a views frame changes, the shadows are recalculated. As you mentioned, you're using a pan gesture, so moving a box slightly will layout the subviews a few dozen times.
The solution you should go with is to create 2 container views which are sibling views. For every colored view you create, add it to the top container view and create another view which will be added to the bottom container view, lets call it the shadow container view. Use constraints on the views inside of the shadow container so their top, leading, bottom and trailing are equal to their equivalent view in the top container view. Next add a shadow to the views inside of the shadow container view and make sure to apply the layer.shadowPath! This shadow path is the key to prevent the shadow from being redrawn when you pan.
If you don't understand and need an example let me know and I'll give you one.
Hey Chris, Try this
yourView.layer.shadowColor = UIColor(white: 0.0, alpha: 0.5).CGColor
yourView.layer.shadowOffset = CGSizeMake(0.0, 0.0)
yourView.layer.shadowOpacity = 1.0
yourView.layer.shadowRadius = 6.0 //increase the width & height of shadow
You can simply add views with shadow first then add your actual view above them. Or, you can try to alter the zPosition of layer of all the view after setting shadows.
I wonder what the best way to create a horizontal line is?
I have a few labels / text and I would like to add a horizontal line between them. More or less like a when using twitter bootstrap.
Right now I am using a UIview and setting it as 1 in height with a black background color. But I guess this isnt the best way to do it?
That is the way to do it in iOS. UIView is the class which represent something to be shown on the screen. Every UI component is direct or indirect descendant of UIView. So, you should use UIView.
UIView is backed by CALayer to render the content to screen. You could also use CALayer, CAShapeLayer or other layer classes to create a border. But, I would not recommend to use CALayer just to show a border as it is simpler to use UIView with height of 1, on the top of that, you get some nice addition such as autolayout. If you use CALayer, you will have to set frame to layer at appropriate time when the view bounds change. It could also be tricky due to some intrinsic animation within CALayer.
I am looking for simple way how to create a button (or other subclass of UIView) that is not drawn in all its frame but only within specified inner (inset) rectangle. The inner (inset) rectangle will have rounded corners of some custom radius. Picture below demonstrates it:
To summarise:
control will respond to touch events within all its frame (the outer rectangle)
content, background, etc. of the control will only by drawn in the inner (inset) rectangle
size of inner rectangle and its corner radius must be customisable
Subclassing is an option but it there is simpler solution I will go with that.
This can be achieved by one of the following ways :
Add a subView inside custom button and provide its corner radius some value so that it becomes rounded. You can add the background , content etc. to this view. But this has to be a custom button and you need to handle the addition of contents by providing some API's.
Another option will be to add a layer with rounded corner inside button but with this limitation comes. You cannot add a subview to your inset rectangle(sublayer). You can only add layers to it not a view.
I created a container view that holds a bunch of child views - a collection view, a custom toolbar and some bits and pieces.
The design has a border on the top, left and right sides, but not the bottom, so I overrode drawRect to include border.
When I added the toolbar I noticed that it appears over the top of the border. (For some reason I initially thought it wouldn't but of course it does!).
Is there anyway I can tell drawRect to draw over the top of my subviews?
Of course there's loads of other ways to solve my problem (adjust the toolbar's frame for example) however I'm asking this question in order to get a deep understanding of how drawing works in relation to compositing and the view hierarchy.
Drawing happens beneath all subviews of a UIView. Think of it as being on the very base - an actual part of your view - and then each subview is added on top of your view. To make the drawing above the subviews is the same as wanting for the subviews to appear under the view, while still being subviews. Perhaps that analogy makes it clearer why it must always be on the bottom. And it also leads you logically to the solution:
To get the drawing to appear above subviews, simply create a new UIView subclass to place the drawing code inside, and place this above all other subviews.
It might also be a good idea to override your UIView's addSubview: implementation, to ensure your subview always remains on top.
I believe you can't, since the drawRect is called first for the view and when it has finished drawing drawRect is called for subviews to draw over it. Maybe just make another subview on top of that view that has the borders you need and is transparent everywhere else?
Subviews are drawn on top of their super views. So the answer to your question is no.
At the time when you draw the border on your container view, Cocoa hasn't even started drawing the toolbar yet.
I guess you could make the top of the border a subview or move the toolbar down a bit.
I have a UIView that I draw a CGPath to and would like to draw an overlay onto the entire view itself, one z level above the rendered CGPath.
How is this done? Should I use a layer? I would like to draw or fill parts of the view repeatedly, so I am not sure if it might be better to use some kind of fill method. Is there a more efficient way to fill parts of the view other than drawing a new path?
I want to create the effect similar to a progress bar, extending the overlays width during runtime depending on a value.
You could use a subview (or, similarly, a sub-layer) for this. A subview of a view will appear above the content rendered in drawRect:.
If you can get away with using a UIImage background (say, one created with resizableImageWithCapInsets:), and simply changing the size of that view over time, it will likely be more efficient than redrawing in drawRect:.