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
Related
I need to create a right slide animation for TextField 1 and left slide animation for TextField2 . I tried to accomplish first right slide animation, but there is a problem. I have an slide animation, but there is another textfield under my animation textfield which doesn't move from it's constraints. I do not really understand why.
here is the code:
class ViewController: UIViewController {
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var PasswordField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
emailField.center.x = self.view.frame.width + 50
UIView.animate(withDuration: 1.0, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 1.0, options: .allowAnimatedContent, animations: {
self.emailField.center.x = self.view.frame.width/2
self.view.layoutIfNeeded()
}, completion: nil)
}
}
Assuming your Storyboard looks similar to this:
Two text fields, with Top constraints, Width constraints equal to 80% of the view width, and CenterX constraints to the view's CenterX
Ctrl-Drag from each .centerX constraint to your view controller code to create #IBOutlet connections to the constraints:
#IBOutlet var emailCenterX: NSLayoutConstraint!
#IBOutlet var passwordCenterX: NSLayoutConstraint!
Your Storyboard will now look like this:
And you can move / animate the views by setting their .constant values at run-time:
class AViewController: UIViewController {
#IBOutlet var emailField: UITextField!
#IBOutlet var PasswordField: UITextField!
#IBOutlet var emailCenterX: NSLayoutConstraint!
#IBOutlet var passwordCenterX: NSLayoutConstraint!
var viewWidth: CGFloat = 0
override func viewDidLoad() {
super.viewDidLoad()
// move the textFields "off-screen"
emailCenterX.constant = UIScreen.main.bounds.width
passwordCenterX.constant = -UIScreen.main.bounds.width
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// reset the centerX constraints to the center of the view
emailCenterX.constant = 0
passwordCenterX.constant = 0
UIView.animate(withDuration: 1.0, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 1.0, options: .allowAnimatedContent, animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
}
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)
}
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
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)
}
I am new to iOS and Swift. I am trying to add a background image for a slide right effect. I want that image to stick to the right of the screen no matter what orientation. The image will always be a set size (now its (382x145px). How can I adjust it on landscape orientation so that the picture stays to the right.
Here is my custom view cell class.
class CustomRouteViewCell: UITableViewCell {
#IBOutlet var downImage: UIImageView!
#IBOutlet var downTime: UILabel!
#IBOutlet weak var leadingSpaceConstraint: NSLayoutConstraint!
#IBOutlet weak var trailingSpaceConstraint: NSLayoutConstraint!
#IBOutlet var locationTitle: UILabel!
#IBOutlet weak var panView: UIView!
#IBOutlet var timerLabel: UILabel!
var indexRow: Int = 0
var timeInterval: Int = 0
override func awakeFromNib() {
super.awakeFromNib()
self.selectedBackgroundView = nil
var img = UIImage(named: "tableSwipeArrow.png")!
self.panView.backgroundColor = UIColor(patternImage: img)
if self.respondsToSelector(Selector("setLayoutMargins:")) {
layoutMargins = UIEdgeInsetsZero
}
if self.respondsToSelector(Selector("setPreservesSuperviewLayoutMargins:")) {
preservesSuperviewLayoutMargins = false
}
var panGestureRecognizer = UIPanGestureRecognizer(target: self, action: "handlePanGesture:")
panGestureRecognizer.delegate = self
addGestureRecognizer(panGestureRecognizer)
}
func handlePanGesture(recognizer: UIPanGestureRecognizer) {
switch(recognizer.state) {
case UIGestureRecognizerState.Changed:
var translation = recognizer.translationInView(recognizer.view!)
var little = CGFloat(trailingSpaceConstraint.constant + translation.x * -1)
trailingSpaceConstraint.constant = fmax(0, little)
leadingSpaceConstraint.constant = fmin(0, leadingSpaceConstraint.constant + translation.x)
recognizer.setTranslation(CGPointZero, inView: recognizer.view!)
timeInterval = Int(trailingSpaceConstraint.constant / 30) * 5
timerLabel.text! = "\(timeInterval)"
case UIGestureRecognizerState.Ended, UIGestureRecognizerState.Cancelled:
var refreshAlert = Alarm.getReminderView(self.timeInterval, view: self.parentViewController!.view)
self.parentViewController?.presentViewController(refreshAlert, animated: true, completion: nil)
leadingSpaceConstraint.constant = 0
trailingSpaceConstraint.constant = 0
UIView.animateWithDuration(0.25, animations: { () -> Void in
self.layoutIfNeeded()
})
default:
trailingSpaceConstraint.constant = 0
leadingSpaceConstraint.constant = 0
}
}
}
extension CustomRouteViewCell: UIGestureRecognizerDelegate
{
override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer.isKindOfClass(UIPanGestureRecognizer) {
var velocity = (gestureRecognizer as! UIPanGestureRecognizer).velocityInView(gestureRecognizer.view!)
return fabs(velocity.x) > fabs(velocity.y)
}
return true;
}
}
Use auto layout to link the position of the images.
In your case you can connect the trailing of the background image with the container view.
Hold Control on image and link the Trailing Attribute with the main view
Just adjust the constant to 0.