Custom view won't add subview - ios

I have a view controller that's inheriting a view from it's preceding view, like a floating, draggable view controller with a video mini player (like the YouTube app). When I show the second vc, I'm actually hiding its own view before adding all of its subviews to a new, custom view so it seems like the first view controller is still present.
This new, custom view is adding my UIButton, but not my two custom UIViews. One of these custom views contains a tableview, which is nowhere to be found. I'm concerned this may be a constraint problem, where I need to add constraints to the new view programmatically or something like that. Any ideas?
onView = first controller's view
class DetailViewController: UIViewController, UIGestureRecognizerDelegate {
var initialFirstViewFrame: CGRect!
var onView: UIView!
var isExpandedMode: Bool!
var player: UIWebView!
var youtubeFrame: CGRect!
var tblFrame: CGRect!
var restrictOffset: CGFloat!
var restrictTrueOffset: CGFloat!
var restictYaxis: CGFloat!
var transparentView: UIView!
#IBOutlet weak var viewTable: UIView!
#IBOutlet weak var tblView: UITableView!
#IBOutlet weak var viewYouTube: UIView!
#IBOutlet weak var btnDown: UIButton!
override func viewDidLoad() {
var dispatchTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(0.8 * Double(NSEC_PER_SEC)))
dispatch_after(dispatchTime, dispatch_get_main_queue(), {
self.calculateFrames()
})
var pan: UIPanGestureRecognizer = UIPanGestureRecognizer(target: self, action: "panAction")
pan.delegate = self
self.viewYouTube.addGestureRecognizer(pan)
isExpandedMode = true
self.btnDown.hidden = true
}
func calculateFrames() {
youtubeFrame = self.viewYouTube.frame
tblFrame = self.viewTable.frame
UIApplication.sharedApplication().setStatusBarHidden(true, withAnimation: UIStatusBarAnimation.Slide)
self.viewYouTube.translatesAutoresizingMaskIntoConstraints() == true
self.viewTable.translatesAutoresizingMaskIntoConstraints() == true
self.viewYouTube.frame = youtubeFrame
self.viewTable.frame = tblFrame
self.player.backgroundColor = UIColor.purpleColor()
self.viewYouTube.backgroundColor = UIColor.greenColor()
restrictOffset=self.initialFirstViewFrame.size.width-200;
restrictTrueOffset = self.initialFirstViewFrame.size.height - 180;
restictYaxis=self.initialFirstViewFrame.size.height-self.viewYouTube.frame.size.height
self.view.hidden = true
transparentView = UIView(frame: self.initialFirstViewFrame)
transparentView.backgroundColor = UIColor.blackColor()
transparentView.alpha = 0.9
self.onView.addSubview(transparentView)
/////// self.viewTable and self.viewYouTube don't load. They have AutoLayout constraints in storyboard and I'm trying to add their views to a different UIView/////////////
self.onView.addSubview(self.viewTable)
self.onView.addSubview(self.viewYouTube)
self.onView.addSubview(self.btnDown)
}

Related

How directly initialize View in PanGestureRecognizer

In my ViewController I have three views.
I want to add UIPanGestureRecognizer in this.
Below is my code...
var circlePanGesture = UIPanGestureRecognizer()
var sqaurePanGesture = UIPanGestureRecognizer()
var trianglePanGesture = UIPanGestureRecognizer()
var destination = [UIView]()
#IBOutlet weak var circle_source: UIView!
#IBOutlet weak var square_source: UIView!
#IBOutlet weak var triangle_source: UIView!
override func viewDidLoad() {
super.viewDidLoad()
panGestureConfiguration()
}
func UIConfiguration() {
circle_source.layer.cornerRadius = circle_source.frame.size.width/2
circle_source.clipsToBounds = true
}
func panGestureConfiguration() {
circlePanGesture.addTarget(self, action: #selector(draggedSourceView(_:)))
circle_source.addGestureRecognizer(circlePanGesture)
sqaurePanGesture.addTarget(self, action: #selector(draggedSourceView(_:)))
square_source.addGestureRecognizer(sqaurePanGesture)
trianglePanGesture.addTarget(self, action: #selector(draggedSourceView(_:)))
triangle_source.addGestureRecognizer(trianglePanGesture)
}
In this ViewController's panGestureConfiguration function I want to use only one UIPanGestureRecognizer object instead of three. So how to do it?
Please give me any solution for this.

Swift - scroll bar swipe function

This is Alibaba.com's ios application. In the app, if I swipe left the bar will scroll left and reveal more clickable options. My question is, how is this made?
Thanks!
I solved it.
1. Firstly make a .xib file, name it to whatever you want, I named mine to unnamedView, then add the labels and imageViews.
2. Then create UnnamedView class file like this and add all labels and images
class unnamedView: UIView {
#IBOutlet weak var firstButton: UIButton!
#IBOutlet weak var firstImage: UIImageView!
#IBOutlet weak var firstLabel: UILabel!
}
3. Then create a array for the UnnamedView in the main view controller.
let unnamed = ["title1":"textTitleToLabel","image1":"nameOfImage"]
var unnamedArray = [Dictionary<String,String>]()
4. Then I added the scroll view to the main view controller
#IBOutlet weak var unnamedScrollView: UIScrollView!
5. Inside viewDidLoad() add following
unnamedArray = [unnamed]
unnamedScrollView.isPagingEnabled = true
unnamedScrollView.contentSize = CGSize(width: unnamedScrollView.bounds.width * CGFloat(unnamedArray.count), height: 100)
unnamedScrollView.showsHorizontalScrollIndicator = false
unnamedScrollView.delegate = self
loadUnnamed()
6. And lastly added following bellow the viewDidLoad
func loadCategories() {
for (index, category) in categoriesArray.enumerated() {
if let unnamedView = Bundle.main.loadNibNamed("unnamedView", owner: self, options: nil)?.first as? unnamedView {
unnamedView.firstImage.image = UIImage(named: category["image1"]!)
unnamedView.firstLabel.text = category["title1"]
unnamedView.firstButton.tag = index
unnamedView.firstButton.addTarget(self, action: #selector(ViewController.gotoCategory(sender:)), for: .touchUpInside)
unnamedScrollView.addSubview(unnamedView)
unnamedView.frame.size.width = self.view.bounds.size.width
unnamedView.frame.origin.x = CGFloat(index) * self.view.bounds.size.width
}
}
}
func gotoCategory (sender:UIButton) {
print("The user wants to buy feature \(sender.tag)")
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "tableView")
self.present(newViewController, animated: true, completion: nil)
}
And also, if you'd like to add page control dots, simply to this.
#IBOutlet weak var featurePageControl: UIPageControl!
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let page = scrollView.contentOffset.x / scrollView.frame.size.width
featurePageControl.currentPage = Int(page)
}

Access ScrollView Delegate Method in another Class

I have a UIScrollView Hooked up to 2 View Controllers. like this
let V1 = self.storyboard?.instantiateViewControllerWithIdentifier("HomeScreen") as UIViewController!
//Add initialized view to main view and its scroll view and also set bounds
self.addChildViewController(V1)
self.scrollVieww.addSubview(V1.view)
V1.didMoveToParentViewController(self)
V1.view.frame = scrollVieww.bounds
//Initialize using Unique ID for the View
let V2 = self.storyboard?.instantiateViewControllerWithIdentifier("MainScreen") as UIViewController!
//Add initialized view to main view and its scroll view also set bounds
self.addChildViewController(V2)
self.scrollVieww.addSubview(V2.view)
V2.didMoveToParentViewController(self)
V2.view.frame = scrollVieww.bounds
//Create frame for the view and define its urigin point with respect to View 1
var V2Frame: CGRect = V2.view.frame
V2Frame.origin.x = self.view.frame.width
V2.view.frame = V2Frame
//The width is set here as we are dealing with Horizontal Scroll
//The Width is x3 as there are 3 sub views in all
self.scrollVieww.contentSize = CGSizeMake((self.view.frame.width) * 2, (self.view.frame.height))
Now i can use The ScrollView Delegate Method which is written inside this class.
So now i went up to my class Main_Screen and subclass it with UIScrollViewDelegate.
Code for Main_Screen Class
import UIKit
public class Main_Screen: UIViewController , UIScrollViewDelegate {
#IBOutlet weak var aboutMebtn: UIButton!
#IBOutlet weak var studybtn: UIButton!
#IBOutlet weak var appsbtn: UIButton!
#IBOutlet weak var skillsbtn: UIButton!
var scrollView : UIScrollView!
#IBOutlet var avatarImageView: UIImageView!
weak var pageControl: UIPageControl!
var mainRead : Bool = false
override public func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// Making the view round
for v : UIView in self.view.subviews {
if v.tag != 1 {
v.layer.cornerRadius = v.frame.size.width/2
v.layer.masksToBounds = true
}
}
}
public func animate(){
// I get a fatal error here
var buttons : Array<UIButton> = [aboutMebtn , studybtn , appsbtn , skillsbtn]
avatarImageView.alpha = 0.0
avatarImageView.transform = CGAffineTransformMakeScale(1.25, 1.25)
UIView.animateWithDuration(1.0, delay: 1.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.0, options: .CurveEaseIn, animations: { () -> Void in
self.avatarImageView.alpha = 1.0
self.avatarImageView.transform = CGAffineTransformMakeScale(0.75, 0.75)
}, completion: nil)
}
public func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
if(scrollView.contentOffset.x == self.view.frame.size.width * 1 ){
print("Main is read")
}
}
But the method of UIScrollView Delegate wont execute. i can do it in ViewController but i cant as i want to run the animate function Above on the scrollViewDidEndDeclerating Method
you must assign your view controller as UIScrollView delegate
self.scrollVieww.delegate = self;
you probably miss it.
you can make it inside viewDidLoad

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

Understanding where auto constraints are being set

In the below autolayout challenge 6, from Ray W, I can't understand where in the code, the width and height change after it is tapped more than once.
It is set to 50 in IB, and on the first run through within the tappedImage method, in the last else condition, width.constant = 100, but when does this ever get redefined back to 50 (width.constant = 50)?!?
AND, after the first tap (i.e., width and height of this image = 100), tapping another image next, the width and height of the first image goes back to 50 while the second image grows to 100. Where in the last else condition does it tell the first image to resize to 50?
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var rayWidth: NSLayoutConstraint!
#IBOutlet weak var rayHeight: NSLayoutConstraint!
#IBOutlet weak var ray: UIImageView!
#IBOutlet weak var vickiWidth: NSLayoutConstraint!
#IBOutlet weak var vickiHeight: NSLayoutConstraint!
#IBOutlet weak var vicki: UIImageView!
#IBOutlet weak var gregWidth: NSLayoutConstraint!
#IBOutlet weak var gregHeight: NSLayoutConstraint!
#IBOutlet weak var greg: UIImageView!
#IBOutlet weak var micWidth: NSLayoutConstraint!
#IBOutlet weak var micHeight: NSLayoutConstraint!
#IBOutlet weak var mic: UIImageView!
#IBOutlet weak var christineWidth: NSLayoutConstraint!
#IBOutlet weak var christineHeight: NSLayoutConstraint!
#IBOutlet weak var christine: UIImageView!
#IBOutlet weak var name: UILabel!
#IBOutlet weak var bio: UITextView!
var heights:[NSLayoutConstraint]!
var widths:[NSLayoutConstraint]!
var bios: [String]!
var names: [String]!
#IBOutlet weak var emailButton: UIButton!
var previousHeight: NSLayoutConstraint?
var previousWidth: NSLayoutConstraint?
override func viewWillAppear(animated: Bool) {
bios = ["Ray is an indie software developer currently focusing on iPhone and iPad development, and the administrator of this site. He’s the founder of a small iPhone development studio called Razeware, and is passionate both about making apps and teaching others the techniques to make them.", "Vicki Wenderlich discovered a love of digital art in 2009, and has been making app art and digital illustrations ever since. She is passionate about helping people pursue their dreams, and makes free app art for developers available on her website, http://www.vickiwenderlich.com.", "Greg is an iOS developer and trainer, and has been on the raywenderlich.com editorial team since 2012. He has been nerding out with computers since the Commodore 64 era in the 80s and continues to this day on the web and on iOS. He likes caffeine, codes with two-space tabs, and writes with semicolons.", "Mic Pringle is a developer, editor, podcaster, and video tutorial maker. He's also Razeware's third full-time employee. When not knee-deep in Swift or stood in-front of his green screen, he enjoys spending time with his wife Lucy and their daughter Evie, as-well as attending the football matches of his beloved Fulham FC. You can find Mic on Twitter, GitHub, and Stack Overflow.", "Christine is Ray's administrative assistant. She tries to keep order in the ever expanding world of raywenderlich.com so that Ray and the team can stay focused on making more tutorials, books, and apps!"]
names = ["Ray Wenderlich", "Vicki Wenderlich", "Greg Heo", "Mic Pringle", "Christine Sweigart"]
name.text = ""
emailButton.hidden = true
}
override func viewDidLoad() {
super.viewDidLoad()
var razeware = [ray, vicki, greg, mic, christine]
heights = [rayHeight, vickiHeight, gregHeight,micHeight,christineHeight]
widths = [rayWidth, vickiWidth, gregWidth,micWidth,christineWidth]
for image in razeware {
var tapGesture = UITapGestureRecognizer(target: self, action: "tappedImage:")
image.userInteractionEnabled = true
image.addGestureRecognizer(tapGesture)
}
}
func tappedImage(sender:UITapGestureRecognizer!) {
var tag = 0
// index / tag who's been tapped
if let senderTag = sender.view?.tag {
tag = senderTag
}
let width = widths[tag] // get the width constraint from the array
let height = heights[tag]
print(width)
view.setNeedsUpdateConstraints()
if previousHeight == height {
if previousHeight?.constant == 100 {
previousHeight?.constant = 50
previousWidth?.constant = 50
print("through here")
//UIView.animateWithDuration(3.0, animations: { () -> Void in
self.name.text = ""
self.bio.text = ""
self.emailButton.hidden = true
// self.view.layoutIfNeeded()
// })
} else {
previousHeight?.constant = 100
previousWidth?.constant = 100
print("Going here")
name.text = names[tag]
bio.text = bios[tag]
bio.font = UIFont.systemFontOfSize(15.0)
bio.textColor = UIColor.whiteColor()
emailButton.hidden = false
}
} else {
previousHeight?.constant = 50
previousWidth?.constant = 50
UIView.animateWithDuration(5.0, animations: { () -> Void in
width.constant = 100
height.constant = 100
self.name.text = self.names[tag]
self.bio.text = self.bios[tag]
self.bio.font = UIFont.systemFontOfSize(15.0)
self.bio.textColor = UIColor.whiteColor()
self.emailButton.hidden = false
self.view.layoutIfNeeded()
})
}
print(width)
previousHeight = height
previousWidth = width
print("Previous: \(previousHeight)")
print("Height: \(height)")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Even if a constraint was re-defined in code elsewhere previously, layoutIfNeeded() will revert to the original IB defined constraint value - unless the constraint is re-defined again (to maintain its new value) after setNeedsUpdateContraints().
This is based on a lot of trial an even more error. Perhaps there is still a chance for a better answer...

Resources