What am I doing wrong with making the corner radius exposed in Interface Builder? - uiimageview

This is driving me nutty. I added a new framework and added a UIImageView subclass to be part of it. I then created a UITableViewCell, made it an instance of my custom UIImageView and set its exposed corner radius to 5.
In my subclass I just have:
#IBDesignable class MediaPostCellImageView: UIImageView {
#IBInspectable var cornerRadius: CGFloat = 3.0 {
didSet {
self.layer.cornerRadius = cornerRadius
}
}
}
Here's an example project showing it: http://cl.ly/3Z053m1O3C0i
Why is this not showing it in Interface Builder?

You need to set layer.masksToBounds property to true.
Also, if you still can't see the rounded corner, try to change the background colour, just in case it actually has rounded corners but you can't see it because the colours are the same with the superview.

#IBInspectable var cornerRadius: CGFloat {
get { layer.cornerRadius }
set {
layer.cornerRadius = newValue
if newValue > 0 {
layer.masksToBounds = true
}
}
}
You can use something like this in the extension. Once the new value is set for the corner radius and it's greater than 0, layer.maskToBounds is set to true.

Related

How to Apply card view cornerRadius & shadow like iOS appstore in swift 4

I want to apply "cornerRadius" and card view "shadow" in my collection view cell like iOS appstore today View.
Just add a subview to the cell and manipulate it's layer property. Tweak the values to your liking. The following code should give a similar result to how it looks in the App Store:
// The subview inside the collection view cell
myView.layer.cornerRadius = 20.0
myView.layer.shadowColor = UIColor.gray.cgColor
myView.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
myView.layer.shadowRadius = 12.0
myView.layer.shadowOpacity = 0.7
Create a new UIView subclass named "CardView" like below:
import Foundation
import UIKit
#IBDesignable
class CardView: UIView {
#IBInspectable var cornerRadius: CGFloat {
get {
return layer.cornerRadius
}
set {
layer.cornerRadius = newValue
layer.shadowRadius = newValue
layer.masksToBounds = false
}
}
#IBInspectable var shadowOpacity: Float {
get {
return layer.shadowOpacity
}
set {
layer.shadowOpacity = newValue
layer.shadowColor = UIColor.darkGray.cgColor
}
}
#IBInspectable var shadowOffset: CGSize {
get {
return layer.shadowOffset
}
set {
layer.shadowOffset = newValue
layer.shadowColor = UIColor.black.cgColor
layer.masksToBounds = false
}
}
}
Then just set "CardView" as Custom Class for your view from XCode Interface Builder. It's simple and easily configurable!
- SwiftUI
struct SimpleRedView: View {
var body: some View {
Rectangle()
.foregroundColor(.red)
.frame(width: 340, height: 500, alignment: .center)
}
}
struct ContentView: View {
var body: some View {
SimpleRedView()
.cornerRadius(28)
.shadow(radius: 16, y: 16)
}
}
SimpleRedView() is just for placeholder and you can replace it with any kind of View you like.
To add onto #oyvindhauge 's great answer -- make sure none of the subviews inside myView extend to the edges. For instance, my card view contained a table view that fills the card -- so it's necessary to set the tableView.layer.cornerRadius = 20.0 as well. This applies to any subview that fills the card.

Changed Anchor Point of CALayer in Layer-backed NSView

I am trying to have a zoom animation run on a layer-backed NSView by animating the transform of the backing layer. The issue I am having with this, is that the animation zooms into the bottom left corner instead of the center of the view. I figured out that this is because NSView sets its backing layer's anchor point to (0, 0), even after I change it to some other value. This post talks about a similar issue.
I know that to get around this, I could make the view a layer-hosting view. However, I would like to use auto layout, which is why that is not really an option.
Does anyone know another way to get around this behavior and keep the anchor point of the view's backing layer at (0.5, 0.5)? The excerpt from apple's documentation in the post I linked above talks about NSView cover methods. What could such cover method be for the anchor point?
Thanks a lot!
The trick is to override the backing layer and pass an anchor point of choice (to be able to zoom from top left, for instance). Here's what I use:
extension CGPoint {
static let topLeftAnchor: Self = .init(x: 0.0, y: 1.0)
static let bottomLeftAnchor: Self = .init(x: 0.0, y: 0.0)
static let topRightAnchor: Self = .init(x: 1.0, y: 1.0)
static let bottomRightAnchor: Self = .init(x: 1.0, y: 0.0)
static let centerAnchor: Self = .init(x: 0.5, y: 0.5)
}
class AnchoredLayer: CALayer {
public var customAnchorPoint = CGPoint.topLeftAnchor
override var anchorPoint: CGPoint {
get { customAnchorPoint }
set { super.anchorPoint = customAnchorPoint }
}
}
class AnchoredView: NSView {
required convenience init(anchoredTo point: CGPoint) {
self.init(frame: .zero)
self.wantsLayer = true
self.anchorPoint = point
}
public override func makeBackingLayer() -> CALayer {
let roundedLayer = AnchoredLayer()
return roundedLayer
}
public var anchorPoint: CGPoint {
get { (layer as! AnchoredLayer).customAnchorPoint }
set { (layer as! AnchoredLayer).customAnchorPoint = newValue }
}
}
Then use AnchoredView as normal:
let myView = AnchoredView(anchoredTo: .topLeftAnchor)
// Create the scale animation
let transformScaleXyAnimation = CASpringAnimation()
transformScaleXyAnimation.fillMode = .forwards
transformScaleXyAnimation.keyPath = "transform.scale.xy"
transformScaleXyAnimation.toValue = 1
transformScaleXyAnimation.fromValue = 0.8
transformScaleXyAnimation.stiffness = 300
transformScaleXyAnimation.damping = 55
transformScaleXyAnimation.mass = 0.8
transformScaleXyAnimation.initialVelocity = 4
transformScaleXyAnimation.duration = transformScaleXyAnimation.settlingDuration
myView.layer?.add(transformScaleXyAnimation, forKey: "transformScaleXyAnimation")
...

Xamarin iOS - UITextField padding with left image

I'm already setting the LeftView of my UITextField so that I can draw a little icon next to the text.
Password.LeftView = new UIImageView(UIImage.FromBundle("LockAndKey"));
Password.LeftViewMode = UITextFieldViewMode.Always;
This works great but the problem now is that the placeholder and actual text is too close to the image - I'd like to indent over the text.
What do I need to do in Xamarin/iOS for my subclassed UITextField to indent the text with a margin? I know there are various functions I can override but haven't had success with it for the text so far.
Thanks!
You need to extend/subclass the UITextField class and override the method called DrawText . There you add the padding you need.
public override void DrawText(CGRect rect)
{
var padding = new UIEdgeInsets (0, 10, 0, 0);
base.DrawText( padding.InsetRect(rect));
}
This will add a 10 points padding to the left.
To make it more customizable I'd add a property called Padding where basically you can set the padding you need depending on the situation.
* UPDATE #1 *
In the case you want to have the space while typing you can just make the UIImageView that represent your LeftView a little bigger in width and play with the ViewContentMode
Using your example:
var leftView = new UIImageView(UIImage.FromBundle("LockAndKey"));
leftView.Frame = new CGRect (leftView.Frame.X, leftView.Frame.Y, leftView.Frame.Width + 15, leftView.Frame.Height);
leftView.ContentMode = UIViewContentMode.Center;
Password.LeftView = leftView
Password.LeftViewMode = UITextFieldViewMode.Always;
With this configuration you will have 7.5 points on each size of the ImageView. You can use others ContentMode to make it work as you'd like.
**** UPDATE #2 ****
Just found another way.
In your subclass UITextField override these two methods:
public override CGRect TextRect (CGRect forBounds)
{
var padding = new UIEdgeInsets (0, 20, 0, 0);
return base.TextRect (padding.InsetRect(forBounds));
}
public override CGRect EditingRect (CGRect forBounds)
{
return TextRect (forBounds);
}
This one is cleaner and as the first solution you can customize it.

iOS 8 Swift Xcode 6 - Set top nav bar bg color and height

I have looked everywhere and tested all the code snippets posted on Stack, but nothing works for me as I need it to work.
I simply want to set:
Nav bar height
Nav bar bg color in RGB
Nav bar centered logo
I'm working with iOS8, Xcode 6 and Swift.
Many thanks for a clear answer!
This is my code in ViewController.swift
// Set nav bar height
navigationController?.navigationBar.frame.origin.y = -10
// Set nav bar bg color
var navBarColor = UIColor(red: 4 / 255, green: 47 / 255, blue: 66 / 255, alpha: 1)
navigationController?.navigationBar.barTintColor = navBarColor
// Set nav bar logo
let navBarImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
navBarImageView.contentMode = .ScaleAspectFit
let navBarImage = UIImage(named: "navBarLogo.png")
navBarImageView.image = navBarImage
navigationItem.titleView = navBarImageView
After applying the code in the accepted answer, the height doesn't seem to change at all..
It's not an easy job...and I've surveyed several articles online (most of them in Objective-C).
The most useful one is this: http://www.emdentec.com/blog/2014/2/25/hacking-uinavigationbar
But its final solution does not put items in the middle, and it's not in Swift.
So I come up with a workable version in Swift. Hope it helps some people as I was saved so many precious time on SO.
Solution in Swift:
The following code will solve some issues you may have encountered:
The title & items are not placed in the middle of the navigation bar
The title & items would flick when the user navigates between view controllers
You need to subclass the UINavigationBar first, and in your storyboard, select the navigation bar element, and in the "Identity Inspector" tab, set the new class as the Custom Class
import UIKit
class UINavigationBarTaller: UINavigationBar {
///The height you want your navigation bar to be of
static let navigationBarHeight: CGFloat = 64
///The difference between new height and default height
static let heightIncrease:CGFloat = navigationBarHeight - 44
override init(frame: CGRect) {
super.init(frame: frame)
initialize()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initialize()
}
private func initialize() {
let shift = UINavigationBarTaller.heightIncrease/2
///Transform all view to shift upward for [shift] point
self.transform =
CGAffineTransformMakeTranslation(0, -shift)
}
override func layoutSubviews() {
super.layoutSubviews()
let shift = UINavigationBarTaller.heightIncrease/2
///Move the background down for [shift] point
let classNamesToReposition: [String] = ["_UINavigationBarBackground"]
for view: UIView in self.subviews {
if classNamesToReposition.contains(NSStringFromClass(view.dynamicType)) {
let bounds: CGRect = self.bounds
var frame: CGRect = view.frame
frame.origin.y = bounds.origin.y + shift - 20.0
frame.size.height = bounds.size.height + 20.0
view.frame = frame
}
}
}
override func sizeThatFits(size: CGSize) -> CGSize {
let amendedSize:CGSize = super.sizeThatFits(size)
let newSize:CGSize = CGSizeMake(amendedSize.width, UINavigationBarTaller.navigationBarHeight);
return newSize;
}
}
Also on my gist: https://gist.github.com/pai911/8fa123d4068b61ad0ff7
iOS 10 Update:
Unfortunately, this code breaks in iOS 10, there is someone who helps fix it, here you go:
iOS 10 custom navigation bar height
And to be clear, this code is kind of hacky since it depends on the navigation bar's internal structure...so if you decide to use it anyway, be prepared for any upcoming changes that may break this code...
Nav bar height:
In a custom navigation controller subclass...
The trick with this one is to NOT change the actual height of the navigation bar and instead adjust its origin.
func viewDidLoad() {
super.viewDidLoad()
navigationBar.frame.origin.y = -10
}
Nav bar bg color in RGB:
In a custom navigation controller subclass...
func viewDidLoad() {
super.viewDidLoad()
navigationBar.barTintColor = // YOUR COLOR
}
or use the appearance proxy
UINavigationBar.appearance().barTintColor = // YOUR COLOR
Nav bar centered logo
In a custom view controller...
func viewDidLoad() {
super.viewDidLoad()
navigationItem.titleView = UIImageView(image: // YOUR LOGO)
}
Great answer from Bon Bon!
In Swift 3 however make sure you replace
let classNamesToReposition: [String] = ["_UINavigationBarBackground"]
with
let classNamesToReposition: [ String ] = [ "_UIBarBackground" ]
Otherwise, it wont work.

rotate label to landscape in Interface builder

I just need help with interface builder. I am trying to rotate only a label for my apps but I can't find the rotate function any where..
Can anyone help me to rotate a label, do I need code in xcode to rotate it?
In Swift 4, add the following code to your View Controller:
#IBDesignable
class DesignableLabel: UILabel {
}
extension UIView {
#IBInspectable
var rotation: Int {
get {
return 0
} set {
let radians = ((CGFloat.pi) * CGFloat(newValue) / CGFloat(180.0))
self.transform = CGAffineTransform(rotationAngle: radians)
}
}
}
Then in interface builder, change your label class type in the Identity Inspector to "DesignableLabel". Your label should then be rotatable in interface builder.
I don't think you can rotate it in IB. You need to appy a transform to the view to get it to rotate.
view.transform = CGAffineTransformMakeRotation(3.14/2);

Resources