Change default possition of view in Xcode - iphone

I'm trying to change a default position of my view for a user.
First I tried it with constraint like this:
class ShopSummaryViewController: BaseViewController, OverlayViewController {
// MARK: properties
#IBOutlet weak var heightConstraint: NSLayoutConstraint!
let overlaySize: CGSize? = CGSize(width: UIScreen.main.bounds.width,
height: UIScreen.main.bounds.height)
#IBOutlet weak var trayView: UIView!
override func viewDidLoad() {
let onePercent = UIScreen.main.bounds.height / 100
heightConstraint.constant = onePercent * 4
}
which work, but for my purpose of UIGestureRecognizer it would be better to not use constraint, but something like this
#IBOutlet weak var heightConstraint: NSLayoutConstraint!
let overlaySize: CGSize? = CGSize(width: UIScreen.main.bounds.width,
height: UIScreen.main.bounds.height)
#IBOutlet weak var trayView: UIView!
override func viewDidLoad() {
trayView.center = CGPoint(x: trayView.frame.size.width/2, y: trayView.frame.size.height/2)
}
which doesn't work. Could someone help me move the default position of the view by around 50% down

Related

Why does parent UIStackView not recognize child StackView's height?

I am trying to load a UIStackView from a xib that contains multiple labels into a parent UIStackView. The labels in the child stack get populated with values (or hidden) after the ViewController in the viewDidLoad method via a model object.
I expect that the parent stackview would recognize the change in intrinsic height of the child stackview, and thus move sibling views down. However, the next view (button) covers the content of the child stack. Why does the parent not recognize this change to a subview's height? I am not seeing any error messages, ambiguous constraints, or conflicts.
Here is how the error renders and how the views appear in the View Hierarchy.
I have tried:
Adding a UIView wrapper around the child stack view to see if the parent would register the change in it's height.
Moved ALL the code into the parent view controller, avoiding xib loading and that does appear to work, at the cost of losing modularity and separation of concerns.
Added optional height constraints on the child stackview based on other article recommendations, resulting in the positions not flexing with the content, or not resolving the original issue.
Here is the storyboard layout
Parent View Controller
class AcceptTermsViewController: RegistrationViewController {
#IBOutlet weak var infoView: StackViewInBorderedView!
#IBOutlet weak var termsView: TermsTextView!
#IBOutlet weak var masterStack: UIStackView!
var registration: Registration?
override func viewDidLoad() {
super.viewDidLoad()
self.configView()
self.setupNavBar()
}
func configView() {
if let reg = registration {
infoView.configView(reg)
}
}
}
Child StackView Code
class StackViewInBorderedView: UIStackView {
// loaded from NIB
private weak var view: UIView!
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var emailLabel: UILabel!
#IBOutlet weak var locationLabel: UILabel!
#IBOutlet weak var postalLabel: UILabel!
#IBOutlet weak var idLabel: UILabel!
#IBOutlet weak var npiLabel: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
loadViewFromNib()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
loadViewFromNib()
}
fileprivate func loadViewFromNib() {
self.view = Bundle (for: type(of: self)).loadNibNamed(
"StackViewInBorderedView", owner: self, options: nil)! [0] as? UIView
view.frame = bounds
view.autoresizingMask = [.flexibleWidth]
self.addSubview(view)
}
override func layoutSubviews() {
super.layoutSubviews()
self.layer.cornerRadius = 10
let shadowLayer = CAShapeLayer()
shadowLayer.path = UIBezierPath(roundedRect: self.bounds, cornerRadius: self.frame.height / 12).cgPath
shadowLayer.fillColor = UIColor.white.cgColor
shadowLayer.shadowColor = UIColor.gray.cgColor
shadowLayer.shadowOffset = CGSize.zero
shadowLayer.shadowOpacity = 1
shadowLayer.shadowRadius = 3
shadowLayer.masksToBounds = false
self.layer.insertSublayer(shadowLayer, at: 0)
}
func configView(_ reg: Registration) {
configLabels(reg)
isLayoutMarginsRelativeArrangement = true
directionalLayoutMargins = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 0)
}
func configLabels(_ reg: Registration) {
// Name line
if let degree = reg.degree {
nameLabel.text = "\(reg.firstName!) \(reg.lastName!), \(degree)"
} else {
nameLabel.text = "\(reg.firstName!) \(reg.lastName!)"
}
// Title line
if let title = reg.title {
titleLabel.text = title
} else {
titleLabel.isHidden = true
}
// Email line
if let email = reg.email {
emailLabel.text = email
} else {
emailLabel.isHidden = true
}
// Location line
if let city = reg.city, let state = reg.state, let postal = reg.postalCode,
!city.isEmpty, !state.isEmpty, !postal.isEmpty {
postalLabel.text = "\(city), \(state) \(postal)"
} else if let postal = reg.postalCode {
postalLabel.text = postal
}
// NPI line
if let licenseId = reg.licenseId {
switch reg.countryCode {
case "BR":
idLabel.text = "ID"
default:
idLabel.text = "NPI"
}
npiLabel.text = licenseId
} else {
self.idLabel.isHidden = true
self.npiLabel.isHidden = true
}
}
}
A colleague of mine found the answer.
When loading the view from the nib, I needed to call self.addArrangedSubview instead of self.addSubview which provides the intended behavior.

I cannot set background picture (Swift)

I made a simple timer app and I want to add a background picture or video in the background. However, I cannot do it and I do not know why.
Can someone tell me why the picture does not show up in the background? I set the background in the viewDidLoad method. Maybe the #IBOutlet var backgroundView: UIView! part is wrong? I connected it with the given UIView when I made this Xcode project.
class ViewController: UIViewController, UITableViewDelegate {
let mainStopwatch = Stopwatch()
let lapStopwatch = Stopwatch()
var isPlay: Bool = false
var laps: [String] = []
//UI components
#IBOutlet weak var lapRestButton: UIButton!
#IBOutlet weak var playPauseButton: UIButton!
#IBOutlet weak var lapTimerLabel: UILabel!
#IBOutlet weak var timerLabel: UILabel!
#IBOutlet weak var lapsTableView: UITableView!
#IBOutlet var backgroundView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
self.view.addBackground(name: "nathan-dumlao-iXXyrEwZgiU-unsplash")
lapRestButton.isEnabled = false
lapsTableView.dataSource = self
lapsTableView.delegate = self
}
//UI Settings
override var shouldAutorotate: Bool {
return false
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.portrait
}
//Actions
#IBAction func playPauseTimer(_ sender: Any) {
lapRestButton.isEnabled = true
changeButton(lapRestButton, title: "Lap", color: .black)
}
}
And this is another swift file for setting the background picture.
extension UIView {
func addBackground(name: String) {
let width = UIScreen.main.bounds.size.width
let height = UIScreen.main.bounds.size.height
let imageViewBackground = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height))
imageViewBackground.image = UIImage(named: name)
imageViewBackground.contentMode = .scaleAspectFill
self.addSubview(imageViewBackground)
self.sendSubviewToBack(imageViewBackground)
}
var timer = Timer()
var counter = 0 // the counter is use for the index of array in below code
var imageArr = ["image","image1","image2"] //Image arr
override func viewDidLoad() {
super.viewDidLoad()
self.addBackground(name: "image") // set default image on your view
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true) // timer will start and it will change view background image after one min you can change time according to your requirement.
}
// called every time interval from the timer
#objc func timerAction() {
self.addBackground(name: self.imageArr[counter]) // here we are change our view background image when timer function is run on every min
counter += 1 // every-time counter will increment by one so the image array index will also increment and we will get our new image
}
// that's your code only you need to change one line that last one
func addBackground(name: String) {
let width = UIScreen.main.bounds.size.width
let height = UIScreen.main.bounds.size.height
let imageViewBackground = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height))
imageViewBackground.image = UIImage(named: name)
imageViewBackground.contentMode = .scaleAspectFit
self.viewref.addSubview(imageViewBackground) // here we will set the image view to our view
}
hope this will help you for change your background of view.
Thanks.
Seems like you've don't using your backgroundView to anywhere in class code , So first
Remove backgroundView from storyBoard and also remove code from class file
viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
self.addBackground(name: "nathan-dumlao-iXXyrEwZgiU-unsplash") //Update this line
lapRestButton.isEnabled = false
lapsTableView.dataSource = self
lapsTableView.delegate = self
}
Update your extension code to below one
extension YourViewController {
func addBackground(name: String) {
let width = self.view.frame.size.width
let height = self.view.frame.size.height
let imageViewBackground = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height))
imageViewBackground.image = UIImage(named: name)
imageViewBackground.contentMode = .scaleAspectFill
self.view.addSubview(imageViewBackground)
// self.sendSubviewToBack(imageViewBackground) //Comment this line
}
}

Try to create a scrollView with labels

I'm a little new in swift. I'm trying to make a simple scrollview with a label that changes its value, but I can not get it to work properly.
This is my code:
class ConsejosController: UIViewController, UIScrollViewDelegate {
var asunto = ["value1", "value2"]
#IBOutlet weak var lbl_asunto: UILabel!
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var pageControl: UIPageControl!
var contentWidth: CGFloat = 0.0
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
for etiqueta in 0...1{
contentWidth += view.frame.width
lbl_asunto.text = asunto[etiqueta]
}
scrollView.contentSize = CGSize(width: contentWidth, height: view.frame.height)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
pageControl.currentPage = Int(scrollView.contentOffset.x / CGFloat(375) )
}
}
This don't work properly. Directly show "value2" and don't scroll
Any advice?
I made the for cycle in this way:
for etiqueta in 0...1{
contentWidth += view.frame.width
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 21))
label.center = CGPoint(x: 160, y: 285)
label.textAlignment = .center
label.text = asunto[etiqueta]
self.scrollView.addSubview(label)
}
Now scrolling well, but show two labels 'value1' and 'value2' in the same page one over another, and the second page empty.

Selector not called on touch of UIButton

I have created the UIButton programmatically and set the method to call when user touch on it using remote control. Below is my code.
import UIKit
class ViewController: UIViewController,VLCMediaPlayerDelegate,UICollectionViewDataSource,UICollectionViewDelegate {
#IBOutlet weak var btnClick: UIButton!
#IBOutlet weak var clickBtn: UIButton!
#IBOutlet weak var myLbl: UILabel!
#IBOutlet weak var playBtn: UIButton!
#IBOutlet weak var zoomBtn: UIButton!
#IBOutlet weak var logoutBtn: UIButton!
var movieView: UIView! // Add VLC Player on movieView
var mediaPlayer: VLCMediaPlayer = VLCMediaPlayer() // VLC Media Player
var PlayButton = UIButton()
var isZoom:Bool = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = UIColor( red: CGFloat(68/255.0), green: CGFloat(117/255.0), blue: CGFloat(196/255.0), alpha: CGFloat(1.0))
self.movieView = UIView()
self.movieView.backgroundColor = UIColor.black
self.movieView.frame = CGRect(x: self.view.frame.minX + 400, y: self.view.frame.minY, width: self.view.frame.size.width - 800, height: self.view.frame.height/2)
self.view.addSubview(self.movieView)
mediaPlayer.delegate = self
mediaPlayer.drawable = self.movieView
let url = "http://192.168.1.34:8852/out.ts"
let urls = URL(string: url)
let media = VLCMedia(url: urls!)
mediaPlayer.media = media
mediaPlayer.rate = 0
// mediaPlayer.play()
self.playButtonTapped(sender: mediaPlayer)
PlayButton = UIButton(type: .system)
PlayButton.setTitle("Play", for: .normal)
PlayButton.frame = CGRect(x: self.view.frame.midX - 100, y: self.view.frame.midY - 300, width: 200, height: 86) //midY-20
PlayButton.addTarget(self, action: #selector(pressButton), for: .touchUpInside)
// PlayButton.setImage(UIImage(named: "pause-button.png"/*"Pause-1.png"*/), for: .normal)
self.view.addSubview(PlayButton)
// self.view.bringSubview(toFront: PlayButton)
// self.view.sendSubview(toBack: mediaPlayer.drawable as! UIView)
}
//The target function
#objc func pressButton(){
print("Hello")
}
}
The issue is pressButton method never get called.
I found the issue was with ".touchUpInside" on tvOS, since that doesn't do what we might expect: we need to use ".PrimaryActionTriggered" instead.
Thank you all for your support.

Dynamic View that adjust to how long the Label text Swift

What I want to happen is that the rectangle view will adjust to how long the label is. Here are my codes
#IBOutlet weak var rectangleView: UIView!
#IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let stringNumber = "123ewrqrqwerw4"
let numberFromString = Int(stringNumber)
rectangleView.frame = CGRect(x: 15, y: 100, width: self.view.frame.width * numberFromString, height: 50)
self.label.text = stringNumber
}
but my code is wrong.