A programmatically UISlider not changing width - swift

My swift code is all code no storyboard. My slider sx should change the width of the imagview when the value is changed. That is not happening no change is visible on the imageview. The imageview should increase / decrease when the slider value is changed.
import UIKit
class ViewController: UIViewController {
var sx = UISlider()
var pic = UIImageView()
var ww = 80
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
[sx,pic].forEach{
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
$0.backgroundColor = UIColor.systemPink
}
pic.frame = CGRect(x: view.center.x-115, y: view.center.y-200, width: CGFloat(ww), height: 50)
sx.frame = CGRect(x: view.center.x-115, y: view.center.y + 200, width: 80, height: 50)
sx.addTarget(self, action: #selector(ji), for: .valueChanged)
}
#objc func ji(sender : UISlider){
ww = Int(sx.value)
}
}

Reset frame inside ji function as code inside viewDidLoad won't be triggered again it's called only once when the vc is loaded
#objc func ji(sender : UISlider){
ww = Int(sx.value)! * 80
pic.frame = CGRect(x: view.center.x-115, y: view.center.y-200, width: CGFloat(ww), height: 50)
}

Related

How to update ScrollView Width after device rotation?

I am following a tutorial to create a swift app that adds a number of views to a scroll view and then allows me to scroll between them. I have the app working and understand it for the most part. When I change the orientation of the device the views width don't get updated so I have parts of more than one view controller on the screen? Does anybody know how to fix this? From my understanding I need to call something in the viewsDidTransition method to redraw the views. Any help would be greatly appreciated. Thanks!
Here is what I have so far:
import UIKit
class ViewController: UIViewController {
private let scrollView = UIScrollView()
private let pageControl: UIPageControl = {
let pageControl = UIPageControl()
pageControl.numberOfPages = 5
pageControl.backgroundColor = .systemBlue
return pageControl
}()
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
pageControl.addTarget(self,
action: #selector(pageControlDidChange(_:)),
for: .valueChanged)
scrollView.backgroundColor = .red
view.addSubview(scrollView)
view.addSubview(pageControl)
}
#objc private func pageControlDidChange(_ sender: UIPageControl){
let current = sender.currentPage
scrollView.setContentOffset(CGPoint(x: CGFloat(current) * view.frame.size.width,
y: 0), animated: true)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
pageControl.frame = CGRect(x: 10, y: view.frame.size.height - 100, width: view.frame.size.width - 20, height: 70)
scrollView.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height - 100)
if scrollView.subviews.count == 2 {
configureScrollView()
}
}
private func configureScrollView(){
scrollView.contentSize = CGSize(width: view.frame.size.width*5, height: scrollView.frame.size.height)
scrollView.isPagingEnabled = true
let colors: [UIColor] = [.systemRed, .systemGray, .systemGreen, .systemOrange, .systemPurple]
for x in 0..<5{
let page = UIView(frame: CGRect(x: CGFloat(x) * view.frame.size.width, y: 0, width: view.frame.size.width, height: scrollView.frame.size.height))
page.backgroundColor = colors[x]
scrollView.addSubview(page)
}
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
print("hello world")
}
}
extension ViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
pageControl.currentPage = Int(floorf(Float(scrollView.contentOffset.x) / Float(scrollView.frame.size.width)))
}
}

use 2 different UIPanGestureRecongizer on 2 different imageviews in a viewController

my code below initializes 2 different imageviews pg and tim. I have create a seperate var for the UIPanGestureRecognizer to be used for each imageview and func to move the imageview around using UIPanGestureRecongizer. Right now I can not move the imageviews around. When I click on pg it disapers. I just want to develop a function that allows me to move each imageview around freely. All of my code is programmatically so you can just copy the code.
import UIKit
class ViewController: UIViewController {
var pg = UIImageView()
var pgGesture = UIPanGestureRecognizer()
var pgCon = [NSLayoutConstraint]()
var tim = UIImageView()
var timGesture = UIPanGestureRecognizer()
var timCon = [NSLayoutConstraint]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
[pg,tim].forEach({
$0.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview($0)
$0.backgroundColor = UIColor.systemPink
$0.isUserInteractionEnabled = true
})
pgGesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.pgGestureMethod(_:)))
pg.addGestureRecognizer(pgGesture)
timGesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.timGestureMethod(_:)))
tim.addGestureRecognizer(timGesture)
pgCon = [
pg.trailingAnchor.constraint(equalTo: view.centerXAnchor, constant :37.5),
pg.topAnchor.constraint(equalTo: view.centerYAnchor, constant : 225),
pg.widthAnchor.constraint(equalToConstant: 75),
pg.heightAnchor.constraint(equalToConstant: 50),
]
NSLayoutConstraint.activate(pgCon)
timCon = [
tim.trailingAnchor.constraint(equalTo: view.centerXAnchor, constant :120),
tim.topAnchor.constraint(equalTo: view.centerYAnchor, constant : 225),
tim.widthAnchor.constraint(equalToConstant: 75),
tim.heightAnchor.constraint(equalToConstant: 50),
]
NSLayoutConstraint.activate(timCon)
}
#objc func pgGestureMethod(_ sender: UIPanGestureRecognizer){
NSLayoutConstraint.deactivate(pgCon)
NSLayoutConstraint.deactivate(timCon)
self.view.bringSubviewToFront(pg)
let tranistioon = sender.translation(in: self.view)
pg.center = CGPoint(x: pg.center.x + tranistioon.x, y: pg.center.y + tranistioon.y)
sender.setTranslation(CGPoint.zero,in: self.view)
}
#objc func timGestureMethod(_ sender: UIPanGestureRecognizer){
NSLayoutConstraint.deactivate(timCon)
NSLayoutConstraint.deactivate(pgCon)
self.view.bringSubviewToFront(tim)
let tranistioon = sender.translation(in: self.view)
tim.center = CGPoint(x: tim.center.x + tranistioon.x, y: tim.center.y + tranistioon.y)
sender.setTranslation(CGPoint.zero,in: self.view)
}
}
Instead of constraints, try giving the frame to both imageViews, i.e.
override func viewDidLoad() {
super.viewDidLoad()
pg.frame = CGRect(x: 100, y: 100, width: 75, height: 50) //here....
tim.frame = CGRect(x: 200, y: 200, width: 75, height: 50) //here....
//rest of the code...
}
In the above code,
change the frame as per your requirement.
from viewDidLoad() remove the code for applying constraints.

UILabel isn't Displaying at Center of View - Xcode Playground

I have the following code running on Xcode Playground. However, even though I specify that the label is centered at the center of the view, it doesn't appear there.
import UIKit
import PlaygroundSupport
class TestViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 20))
label.center = CGPoint(x: view.frame.width / 2, y: view.frame.height / 2)
label.text = "Hello World!"
label.textColor = UIColor.black
view.addSubview(label)
}
}
PlaygroundPage.current.liveView = TestViewController()
The view controller's view's frame is not final in viewDidLoad.
You either need to set the label's autoresizingMask or apply constraints to keep it in the center.
And since you made the label wider than the text, you also need to set the label's textAlignment to center.
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 20))
label.center = view.center
label.text = "Hello World!"
label.textColor = .black
label.textAlignment = .center // or call label.sizeToFit()
label.autoresizingMask = [ .flexibleTopMargin, .flexibleBottomMargin, .flexibleLeftMargin, .flexibleRightMargin, ]
view.addSubview(label)
view frame is not finalized when viewDidLoad is triggered, you need to set the frame of the label inside the method viewDidLayoutSubviews as this method is being invoked when view bound was finalized.
Try
class TestViewController: UIViewController {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 20))
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
label.text = "Hello World!"
label.textColor = UIColor.black
self.view.addSubview(label)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.label.center = self.view.center
}
}

Swift: Setting progress of NSProgressIndicator

I have tried to setup my own NSProgressIndicator with the following method.
class ProgressViewController : NSViewController
{
override func loadView()
{
let view = NSView(frame: NSMakeRect(0,0,300,120))
view.wantsLayer = true
view.layer?.borderWidth = 0
self.view = view
let text = NSTextField(frame: NSRect(x: 20, y: 45, width: 260, height: 20))
text.drawsBackground = true
text.isBordered = false
text.backgroundColor = NSColor.controlColor
text.isEditable = false
self.view.addSubview(text)
text.stringValue = "Progress Text"
let indicator = NSProgressIndicator(frame: NSRect(x: 20, y: 20, width: 260, height: 20))
indicator.minValue = 0.0
indicator.maxValue = 100.0
indicator.doubleValue = 33.0
self.view.addSubview(indicator)
}
}
My problem is that the indicator is always shown full. Am I missing a trick?
The default style is indeterminate. Set it to false and everything should be OK:
indicator.isIndeterminate = false

UISwipeGestureRecognizer not recognized when added to UIView's subviews

I currently have a subclass of UIView which contains numerous subviews. I wish to add a UISwipeGesture to the subviews but unfortunately the swipe gesture is not recognized. I've set userInteractionEnabled = true and direction of the swipe gesture but nothing works.
public class CardStackView: UIView{
public var dataSource = [UIImage]()
private var swipeGuesture: UISwipeGestureRecognizer!
override public func layoutSubviews() {
for img in dataSource{
let view = AppView(image: img, frame: self.frame)
self.addSubview(view)
}
animateSubview()
self.userInteractionEnabled = true
}
func animateSubview(){
for (index, sView) in self.subviews.enumerate() {
swipeGuesture = UISwipeGestureRecognizer(target: self, action: #selector(self.swipeGuestureDidSwipeRight(_:)))
swipeGuesture.direction = .Right
sView.addGestureRecognizer(swipeGuesture)
sView.userInteractionEnabled = true
let move: CGFloat = CGFloat(-20 + index * 20)
let opacity = Float(1 - 0.2 * CGFloat(index))
sView.shadowOpacity(opacity).shadowOffset(CGSizeMake(20 - CGFloat(index) * 5, 20 - CGFloat(index) * 5)).shadowRadius(5).moveX(-move).moveY(-move).gravity().shadowColor(UIColor.grayColor()).duration(1)
.completion({
}).animate()
}
}
func swipeGuestureDidSwipeRight(gesture: UISwipeGestureRecognizer) {
print("Swiped right")
let subview = self.subviews[0]
subview.moveX(-60).duration(1).animate()
}
}
Example
class ExampleController: UIViewController {
var stackView: CardStackView!
override func viewDidLoad() {
super.viewDidLoad()
stackView = CardStackView(frame: CGRect(x: 20, y: 80, width: 200, height: 200))
stackView.dataSource = [UIImage(named: "2008")!, UIImage(named: "2008")!]
self.view.addSubview(stackView)
}
}
self.view.bringSubviewToFront(yourSubview)
try this code for all your subviews and if it doesn't work try this in your controller class for your CardStackView.
Try to call setNeedsLayout for stackView:
override func viewDidLoad() {
super.viewDidLoad()
stackView = CardStackView(frame: CGRect(x: 20, y: 80, width: 200, height: 200))
stackView.dataSource = [UIImage(named: "2008")!, UIImage(named: "2008")!]
stackView.setNeedsLayout()
self.view.addSubview(stackView)
}