I have a UIView that should show two colours, red and orange, based on the value of rating: Double The problem is that when I run the app nothing is showing up. In my output log the function prints that it has run and that the rating value is what it should be. So I am not sure why nothing is showing up when I run the app, I just see white.
class RatingViewController: UIView {
var rating: Double = 1.0
var rate: Double? {
didSet {
rating = rate!
setUpView()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
private func setUpView() {
Self.backgroundcolor = UIColor.yellow
print("rating is \(rating), and width is \((UIScreen.main.bounds.width * CGFloat(rating/10)))")
let width = (UIScreen.main.bounds.width * CGFloat(rating/10))
var view: UIView
view = UIView(frame: CGRect(x: 0, y: 0, width: width, height: self.frame.size.height))
view.backgroundColor = UIColor.red
self.addSubview(view)
}
}
You have to add setUpView in init(: method
class RatingViewController: UIView {
var rating: Double = 1.0
required init?(coder: NSCoder) {
super.init(coder: coder)
}
init(frame: CGRect, rate: Double) {
super.init(frame: frame)
self.rating = rate
setUpView()
}
private func setUpView() {
self.backgroundColor = UIColor.yellow
print("rating is \(rating), and width is \((UIScreen.main.bounds.width * CGFloat(rating/10)))")
let width = (UIScreen.main.bounds.width * CGFloat(rating/10))
var view: UIView
view = UIView(frame: CGRect(x: 0, y: 0, width: width, height: self.frame.size.height))
view.backgroundColor = UIColor.red
self.addSubview(view)
}
}
Now you can call this class with custom init method like that:
// chnage frame and rate according to your requirment
let rView = RatingViewController(frame: CGRect(x: 0, y: 0, width: 320, height: 300), rate: 2.0)
Related
I added a view as parent red view in CollectionViewCell and the next blue subview at the center of the parent view. It works correctly and the sub view goes at the center of the parent view before collection cell size is not changed. But, The cell size is changed by conforming the method from UICollectionViewDelegateFlowLayout protocol and the view is not centered of the cell correctly. How I can solve this issue ?
class ItemCollectionViewCell: UICollectionViewCell {
var parentView: UIView!
var circularView: UIView!
var itemImage: UIImageView!
var itemName: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
// self.updateView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.updateView()
}
func updateView(){
self.clipsToBounds = true
self.parentView = UIView(frame: CGRect(x: 0.0, y: 0.0, width:
self.frame.size.width, height: self.frame.size.height))
self.parentView.backgroundColor = UIColor.red
self.circularView = UIView(frame: CGRect(x: 0, y: 0, width:
self.parentView.frame.size.width / 4 , height:
self.parentView.frame.size.width / 4 ))
self.circularView.backgroundColor = UIColor.blue
self.addSubview(parentView)
self.parentView.addSubview(self.circularView)
self.circularView.center = self.parentView.center
}
}
1]2
Try this code
self.circularView.center = CGPoint(x: self. parentView.bounds.midX, y: self. parentView.bounds.midY)
self.parentView.addSubview(self.circularView)
self.addSubview(parentView)
Try doing:
self.circularView.center = CGPointMake(CGRectGetMidX(self.parentView.bounds), CGRectGetMidY(self.parentView.bounds))
Why this should work? Try checking values of self.parentView.center for each cell, they might not be what you want them to be, because center property gives values with respect to parent view coordinate system.
Remove the following line from updateView()
self.circularView.center = self.parentView.center
Please add it to the following method:
override func layoutSubviews() {
super.layoutSubviews()
self.circularView.center = self.parentView.center
}
e.g.
class ItemCollectionViewCell: UICollectionViewCell {
var parentView: UIView!
var circularView: UIView!
var itemImage: UIImageView!
var itemName: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
// self.updateView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.updateView()
}
func updateView(){
self.clipsToBounds = true
self.parentView = UIView(frame: CGRect(x: 0.0, y: 0.0, width:
self.frame.size.width, height: self.frame.size.height))
self.parentView.backgroundColor = UIColor.red
self.circularView = UIView(frame: CGRect(x: 0, y: 0, width:
self.parentView.frame.size.width / 4 , height:
self.parentView.frame.size.width / 4 ))
self.circularView.backgroundColor = UIColor.blue
self.addSubview(parentView)
self.parentView.addSubview(self.circularView)
}
override func layoutSubviews() {
super.layoutSubviews()
self.circularView.center = self.parentView.center
}
}
I am trying to make a custom title view for my nav bar with an image an some text next to it and this is how I did it thank to https://stackoverflow.com/a/47404105 :
class CustomTitleView: UIView
{
var title_label = CustomLabel()
var left_imageView = UIImageView()
override init(frame: CGRect){
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder){
super.init(coder: aDecoder)
setup()
}
func setup(){
self.addSubview(title_label)
self.addSubview(left_imageView)
}
func loadWith(title: String, leftImage: UIImage?)
{
title_label.text = title
title_label.font = UIFont.systemFont(ofSize: FontManager.fontSize + 5)
left_imageView.image = leftImage
setupFrames()
}
func setupFrames()
{
let height: CGFloat = 44
let image_size: CGFloat = height * 0.8
left_imageView.frame = CGRect(x: 0,
y: (height - image_size) / 2,
width: (left_imageView.image == nil) ? 0 : image_size,
height: image_size)
let titleWidth: CGFloat = title_label.intrinsicContentSize.width + 10
title_label.frame = CGRect(x: left_imageView.frame.maxX + 5,
y: 0,
width: titleWidth,
height: height)
contentWidth = Int(left_imageView.frame.width)
self.frame = CGRect(x: 0, y: 0, width: CGFloat(contentWidth), height: height)
}
var contentWidth: Int = 0
override func layoutSubviews() {
super.layoutSubviews()
self.frame.size.width = CGFloat(contentWidth)
}
But the problem is that I don't want to hardcode the frame, I want to use constraints but I have no idea where to start.
First take a imageView and set it's constraints according to your requirement and then take a Label besides that imageView set it's constraints too. Do this in your navigationBar where you want to show them.
I have a grid of custom "text below image" UIButtons inside a static UITableViewCell.
To make 8 UIButtons form 4x2 grid, I put them into 2 horizontal UIStackViews and wrapped them with a vertical UIStackView.
You can see details in the screenshots below.
It runs perfect on simulator and real devices, but not rendered properly in Storyboard. I'd like to know if these are something missing in my code or some settings I should check/uncheck in Storyboard.
Runtime behavior(works well)
In Storyboard(chaos)
Outline
Custom Button:
import UIKit
#IBDesignable class YPTextBelowImageButton: UIButton {
#IBInspectable var heightRatio: CGFloat = 0.8 {
didSet {
self.setNeedsDisplay()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
self.frame = frame
self.imageView?.contentMode = .scaleAspectFit
self.titleLabel?.textAlignment = .center
self.setNeedsDisplay()
self.setNeedsLayout()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.imageView?.contentMode = .scaleAspectFit
self.titleLabel?.textAlignment = .center
self.setNeedsDisplay()
self.setNeedsLayout()
}
override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
return CGRect(x: 0, y: 0, width: contentRect.size.width, height: contentRect.size.height * heightRatio)
}
override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
return CGRect(x: 0, y: contentRect.size.height * heightRatio, width: contentRect.size.width, height: contentRect.size.height * (1 - heightRatio))
}
}
Preview:
func prepareForInterfaceBuilder not working
override func prepareForInterfaceBuilder() {
self.imageView?.contentMode = .scaleAspectFit
self.titleLabel?.textAlignment = .center
self.setNeedsDisplay()
self.setNeedsLayout()
}
I have a view class which is used for showing a spinner with a blurred background view. I add this to another view during runtime and everything works fine. When I add this view to another ViewControllers view somehow the effect is not visible.The view does get added, I check it by setting the background colour to green and it is there.But the effect itself is not visible.I add the view in this manner
Ex:
self.view.addSubview(self.loadingView)
self.loadingView.frame = CGRect(origin: .zero, size:self.view.frame.size)
.The Implementation is as below,
final class LoaderView: UIView {
fileprivate let spinner = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
fileprivate let effect = UIBlurEffect(style: .light)
fileprivate let backgroundView = UIVisualEffectView(frame:.zero)
override init(frame: CGRect) {
spinner.startAnimating()
super.init(frame: frame)
backgroundView.effect = effect
addSubview(backgroundView)
addSubview(spinner)
}
#available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setSpinnerColor(color:UIColor){
spinner.color = color
}
override func layoutSubviews() {
super.layoutSubviews()
backgroundView.frame = CGRect(x: 0, y: 0, width: self.bounds.height/5, height: self.bounds.height/5)
backgroundView.center = CGPoint(x:self.bounds.size.width / 2.0, y: self.bounds.size.height / 2.0)
backgroundView.clipsToBounds = true
backgroundView.cornerRadius = 10
spinner.center = center
}
}
I am working on creating a customized button in Swift.
When I subclassed UIButton class, it works fine.
But it crashed when I replace super class with BFPaperButton (https://github.com/bfeher/BFPaperButton)
I have fixed the init method name conversion error with:
#define initFlat initWithFlat
#define initFlatWithFrame initWithFlatWithFrame
#define initRaised initWithRaised
#define initRaisedWithFrame initWithRaisedWithFrame
Then I got EXC_BAD_ACCESS when accessing the new defined property:
(An UserCountButton Instance).countLabel.text = ...
This is my implementation:
import UIKit
class UserButton: BFPaperButton {
let footerLabel = UILabel()
override init() {
super.init(flatWithFrame: CGRect(x: 0, y: 0, width: UIScreen.mainScreen().bounds.width / 3, height: 100))
addSubview(footerLabel)
layer.contentsScale = UIScreen.mainScreen().scale
footerLabel.frame = CGRect(x: 0, y: 60, width: bounds.width, height: 40)
footerLabel.textColor = UIColor.grayColor()
footerLabel.textAlignment = .Center
footerLabel.font = UIFont.systemFontOfSize(12)
}
override init(raisedWithFrame frame: CGRect) {
super.init(raisedWithFrame: frame)
}
override init(flat: ()) {
super.init(flat: ())
}
override init(flatWithFrame frame: CGRect) {
super.init(flatWithFrame: frame)
}
required init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
}
class UserCountButton: UserButton {
let countLabel = UILabel()
override init() {
super.init()
addSubview(countLabel)
countLabel.frame = CGRect(x: 0, y: 0, width: bounds.width, height: 90)
countLabel.textColor = UIColor.darkGrayColor()
countLabel.textAlignment = .Center
countLabel.font = UIFont.systemFontOfSize(32)
}
required init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
}
Is that a bug or some what? How can I fix it? (I'm using Xcode 6 Beta 5)
From what I can tell, the problem is that you are trying to change stuff on your countLabel, but you have defined it via let which makes it immutable. Try changing that to var, and then setting all of it's properties.
Also, it should be noted that I believe you need to do all the subview initialization BEFORE you call addSubview, for both your UserCountButton and your UserButton.