Resize a UIView inside a stackview - ios

I need help to accomplish this:
Its a group of 3 photos. The first photo is the button screen before the click, the second photo is the screen after the click and the third photo is the way i've designed in the IB using stackview
I've being trying to create this and this is the result i've got so far. I still haven't created anything as the After button click image shows because of this:
My Result now
As you can see in the gif when i press the button, the UIView height constraint.constant is set to a higher value and the UIView get higher. All i want is the stripped background to get higher as well.
This is the way the view is disposed in IB.
And finally, this is the way i've coded
class LetterScreenViewController: UIViewController, ResizeWordViewDelegate {
#IBOutlet weak var youTubeView: YouTubeView!
#IBOutlet weak var phonemeView: PhonemeView!
#IBOutlet weak var wordView: WordView!
var letterPresenter: LetterPresenter?
#IBOutlet weak var heightWordViewConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
delegateWordObj()
if let presenter = letterPresenter {
presenter.setupView()
}
}
#IBAction func dismissLetter(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
func delegateWordObj() {
wordView.resizeWordViewDelegate = self
}
func didPressButton() {
if heightWordViewConstraint.constant <= 0 {
heightWordViewConstraint.constant = 30
}else{
heightWordViewConstraint.constant = 0
}
}
}
import UIKit
protocol ResizeWordViewDelegate {
func didPressButton()
}
class WordView: UIView {
#IBOutlet weak var backgroundListras: UIImageView!
#IBOutlet var WordView: UIView!
#IBOutlet weak var showWordButton: UIButton!
var resizeWordViewDelegate: ResizeWordViewDelegate!
override init(frame: CGRect) {
super.init(frame: frame)
xibInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
xibInit()
}
func xibInit() {
Bundle.main.loadNibNamed("WordView", owner: self, options: nil)
addSubview(WordView)
WordView.frame = self.bounds
WordView.round(corners: [.topLeft,.topRight], radius: 120)
WordView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
}
#IBAction func showWordButtonAction(_ sender: Any) {
resizeWordViewDelegate.didPressButton()
self.frame.size = CGSize(width: 375, height: 200)
self.backgroundListras.frame.size = CGSize(width: 375, height: 200)
}
}
I want to know a way to resize this UIView with all the content in it. After finding a solution to increase the height i'll be able to put all the others components shown when i press the button.

I believe that your goal is to create something like this:
All I had to do was change the height of the constraint programmatically
Check the solution in the project below:
https://gitlab.com/DanielLimaDF/ResizeTest.git
Important: Beware of addSubview, it can remove constraints from a View if the constraints were created before calling addSubview

Related

How do I fire an event from a button inside a child view to trigger an event on parent View? Button is not working

I am trying to create a verification process in 4 steps, in order to make my code more efficient, I decided to use Child views and just update the UI accordingly.
I managed to add my child view to my MasterView, however, I am unable to click the button inside my child view.
I already checked the view hierarchy and there is nothing on top of my button. I also tried to add the action programmatically, re-added the button but I can't make it work. I am new to swift development so probably I am missing something.
Child view Code
protocol IdentityVerificationIntroChildViewControllerDelegate{
func startVIProcess(_ sender: Any)
}
class IdentityVerificationIntroChildViewController: UIView{
#IBOutlet var contentView: UIView!
var delegate: IdentityVerificationIntroChildViewControllerDelegate?
#IBOutlet weak var mStartVIBtn: UIButton!
override init(frame: CGRect){
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder){
super.init(coder: aDecoder)
commonInit()
}
private func commonInit(){
Bundle.main.loadNibNamed("IdentityVerificationIntroChildView", owner: self, options: nil)
mStartVIBtn.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
addSubview(contentView)
contentView.frame = self.bounds
contentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
}
#objc func buttonAction(sender: UIButton!) {
print("works")
}
}
Master view code
final class MasterIdentityVerificationViewController: UIViewController {
#IBOutlet weak var mContainerView: UIView!
#IBOutlet weak var mStepIndicator: StepIndicatorView!
private var currentView: UIView?
override func viewDidLoad() {
super.viewDidLoad()
setChildView(subView: IdentityVerificationIntroChildViewController())
}
private func setChildView(subView: UIView){
currentView?.removeFromSuperview()
currentView = subView
currentView?.translatesAutoresizingMaskIntoConstraints = false
guard let currentView = currentView else { return }
mContainerView.addSubview(currentView)
NSLayoutConstraint.activate([
currentView.topAnchor.constraint(equalTo: mContainerView.topAnchor),
currentView.trailingAnchor.constraint(equalTo: mContainerView.trailingAnchor),
currentView.leadingAnchor.constraint(equalTo: mContainerView.leadingAnchor),
currentView.bottomAnchor.constraint(equalTo: mContainerView.bottomAnchor)
])
}
}
extension MasterIdentityVerificationViewController: IdentityVerificationIntroChildViewControllerDelegate{
func startVIProcess(_ sender: Any) {
performSegue(withIdentifier: "fromVIIntroToVIIDCapture", sender: sender)
print("adfsdfs")
}
}
View Hierarchy, the problematic button is Highlighted
Green Area is where Child views are getting switched
I would really appreciate any help. Thanks

setTitle for UIButton results in it disappearing

I have changed the alpha of the button successfully so I know I can modify it. But when I use setTitle, the button just disappears.
I have a tableview with collection views in each cell. I have a custom header cell that when tapped, presents options including the button that disappears when tapping on it.
Here is the function in the main view controller that is called properly and works (I know because I can change the alpha of the button and even make it hidden).
func deleteScenes(){
if let header = whichHeaderTapped {
header.deleteScenesOutlet.setTitle("fuckssake", for: .normal)
header.deleteActOutlet.alpha = 0.0
header.editButtonOutlet.alpha = 0.0
}
}
Here is the class for the header cell.
class HeaderCell: UITableViewCell {
static var shared = HeaderCell()
#IBOutlet var headerName: UILabel!
#IBOutlet var newOptions: UIStackView!
#IBOutlet var deleteScenesOutlet: UIButton!
#IBOutlet var deleteActOutlet: UIButton!
#IBOutlet var editButtonOutlet: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
self.newOptions.frame.origin = CGPoint(x: 285, y: 0)
}
override func layoutSubviews() {
super.layoutSubviews()
}
#IBAction func deleteScenesButton(_ sender: UIButton) {
if deleteScenesOutlet.titleLabel?.text == "Delete Scenes" {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "deleteScenesButtonEnabled"), object: nil)
}
else {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "deleteScenesButtonDisabled"), object: nil)
}
}
}
Your code seems to be fine. Can you check what is the color of your button title. If it is white and your background view color is also white then there is a chance you were not able to see the button.

Trouble getting button in custom uiview to respond to touch

So I have a custom UIView with a button in it, called the home button. In other view controllers, this home button within this particular UIView works just fine. In one particular view controller, however, the home button is non responsive to touches- the app acts as though the button is not even there.
class TemplateChooserViewController: UIViewController, HeaderViewDelegate {
...
#IBOutlet weak var myHeader: HeaderView!
override func viewDidLoad() {
super.viewDidLoad()
myHeader.delegate = self
myHeader.Title.text = "Template Chooser"
... //All the rest of this function has been commented out and the home button still didn't work
}
func homeButtonTapped()
{
let home = self.navigationController?.viewControllers.first //code never reaches here
self.navigationController?.popToViewController(home!, animated: false)
}
And the HeaderView file looks like:
protocol HeaderViewDelegate: class {
func homeButtonTapped()
func informationButtonTapped()
}
class HeaderView: UIView {
weak var delegate: HeaderViewDelegate?
#IBOutlet var view: UIView!
#IBOutlet weak var Title: UILabel!
#IBOutlet weak var flameDecal: UIImageView!
#IBOutlet weak var homeButton: UIButton!
required init(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)!
Bundle.main.loadNibNamed("HeaderView", owner: self, options: nil)
self.addSubview(self.view)
}
#IBAction func homeButtonTouched(_ sender: UIButton)
{
delegate?.homeButtonTapped() //Code also doesn't reach here
}
#IBAction func infoButtonTouched(_ sender: UIButton) {
delegate?.informationButtonTapped()
}
}
Keep in mind the code compiles fine, so I did have the infoButtonTouched function implemented, I just didn't see the point in showing it. I have no idea why the button is unresponsive. Any ideas on how to get the button to respond would be most helpful. Thanks for your consideration of this matter.
Sincerely,
Sean

UIView doesn't center properly in UIScrollView with autolayout

I'm making an application where I need an x amount of custom UIView and place them in a scrollView. The layout of the scrollView and the UIView xib are set with AutoLayout. The result I'm getting now is this:
First View is well centred in ScrollView
Second View is wrong and has a lot of space in between
See my VC Code under here.
let sponsors = Sponsors.createSponsors() <-- Array
override func viewDidLoad() {
super.viewDidLoad()
configureSponsors()
}
//MARK: Load the AddView in ScrollView
func configureSponsors() {
self.scrollView.contentSize = CGSizeMake(CGFloat(sponsors.count) * self.scrollView.frame.size.width, self.scrollView.frame.size.height)
for sponsor in sponsors {
numberOfItems++
let addView = NSBundle.mainBundle().loadNibNamed("AddView", owner: self, options: nil).last as! AddView
addView.addDataToAddView(sponsor)
addView.frame = CGRectMake(CGFloat(numberOfItems - 1) * scrollView.frame.size.width, 0, scrollView.frame.size.width, scrollView.frame.size.height)
self.scrollView.addSubview(addView)
}
}
And here is my UIView code:
//MARK: Outlets
#IBOutlet weak var backgroundImageView: UIImageView!
#IBOutlet weak var sponsorTitle: UILabel!
#IBOutlet weak var sponsorLogo: UIImageView!
#IBOutlet weak var sponsorSubtitle: UILabel!
#IBOutlet weak var roundView: UIView!
#IBOutlet weak var playMusicButton: UIButton!
//MARK: Properties
var cornerRadius: CGFloat = 3.0
func addDataToAddView(sponsor: Sponsors) {
backgroundImageView.image = UIImage(named: sponsor.backgroundImage)
sponsorLogo.image = UIImage(named: sponsor.logoImage)
sponsorTitle.text = sponsor.title
sponsorSubtitle.text = sponsor.subTitle
}
override func layoutSubviews() {
roundView.layer.cornerRadius = roundView.frame.size.width / 2
roundView.alpha = 0.7
roundView.clipsToBounds = true
}
//MARK: PlayVideo
#IBAction func playVideo(sender: UIButton) {
//play music
}
I've already searched for the same problems. I found out that I have to use the Pure Auto Layout Approach. Should that mean I need to programatically set the constraints for the UIView?
Many thanks,
Dax
Update:
Pictures for scrollView setup:
You should not perform layout calculations in viewDidLoad as frames are not set correctly till then.
Correct place to do this is either viewWillLayoutSubviews or viewDidLayoutSubviews as you will get the correct frame data when these functions are called

Swift: Append Custom UIView programmatically

This is a near duplicate of this other SO question, however I'm running into some issues that it makes it appear like I'm not doing it correctly. For reference, I followed this excellent tutorial on creating re-usable views from a custom class and xib file (it's only a few minutes :) and I have no problems at all dragging that into another view onto my storyboard (as demonstrated at the end of the video)
Nevertheless for my case — I'm trying to call my custom class programmatically, and add it as a subview to one of my ScrollView instances.
class MainController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
first.directionalLockEnabled = true
first.pagingEnabled = true
var item = MyCustomView(frame: CGRectMake(0, 0, self.view.frame.width, 200))
self.scrollView.addSubview(item)
}
}
My Custom view looks like this:
import UIKit
class MyCustomView: UIView {
#IBOutlet var view: UIView!
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var dressTitle: UILabel!
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
NSBundle.mainBundle().loadNibNamed("MyCustomView", owner: self, options: nil)
self.view.frame = bounds
self.addSubview(self.view)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
}
There is an associated .xib file with it too that has the label and image.
So my question is, my view never appears in my ScrollView. I've double checked the constraints on my scroll view... I can even append simple UIView's with obvious visible dimensions CGRectMake(0, 0, 100, 100)... and nothing ever gives. What am I missing?
With some messing around I accidentally got it to work by duplicating the loadFromNib method to a second initializer in the CustomView.swift file. As seen in the video tutorial posted in the original question it shows just one of the initializers.... but in my case I had to add extra code to the init(frame). Eg:
// once with a NSCoder
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
NSBundle.mainBundle().loadNibNamed("Item", owner: self, options: nil)
self.view.frame = bounds
self.addSubview(self.view)
}
// for this to work programmatically I had to do the same...
override init(frame: CGRect) {
super.init(frame: frame)
NSBundle.mainBundle().loadNibNamed("Item", owner: self, options: nil)
self.view.frame = bounds
self.addSubview(self.view)
}

Resources