Different transition for each view in same view controller swift? - swift

Hi guys ı am stucked when ı try to present view controller . I split my main view to two views my desire is top view comes with .crossdisolve transition and below view comes with fade in transition . But these are in same view controller.Is this possible
.

This is how you try to do it in its simplest form.
You can adapt it with this or if you share a few code examples, I can be more helpful.
class ViewController: UIViewController {
#IBOutlet private weak var topView: UIView!
#IBOutlet private weak var bottomView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
topView.backgroundColor = .red
bottomView.alpha = 0.0
UIView.animate(withDuration: 1, delay: 0, options: .transitionCrossDissolve) { [weak self] in
self?.topView.backgroundColor = .blue
}
UIView.animate(withDuration: 1) { [weak self] in
self?.bottomView.alpha = 1.0
}
}
}

Related

How to use a button created in XIB custom view to control setContentOffset in viewController.swift?

I followed this tutorial to create a Snapchat-Like Menu: https://www.youtube.com/watch?v=1_daE3IL_1s
In short, the idea was to create custom views with XIB, and add them into a scrollview.
I would like to add a "back" button to one of the custom views so that the scrollview will automatically scroll back to its initial view when the button is tapped. The Idea I had was to write a code inside the custom view's IBAction function to call UIScrollview's content offset delegate function.
the following is the code in View Controller:
class ViewController: UIViewController, UIScrollViewDelegate {
//I'm naming the Scroll View as "scrollView"
#IBOutlet weak var scrollView: UIScrollView! {
didSet{
scrollView.delegate = self
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
var v1 : View1 = View1(nibName: "View1", bundle: nil)
var v2 : View2 = View2(nibName: "View2", bundle: nil)
self.addChild(v1)
self.scrollView.addSubview(v1.view)
v1.didMove(toParent: self)
self.addChild(v2)
self.scrollView.addSubview(v2.view)
v1.didMove(toParent: self)
var v2Frame : CGRect = v2.view.frame
v2Frame.origin.x = self.view.frame.width
v2.view.frame = v2Frame
self.scrollView.contentSize = CGSize(width: self.view.frame.width * 2, height: self.view.frame.height)
// self.scrollView.contentSize = CGSize(self.view.frame.width * 2, self.view.frame.size.height)
}
}
The following ht the code in View2:
class View2: UIViewController {
#IBOutlet weak var buttonHome: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func buttonHomeAction(_ sender: Any) {
//how to access scrollview.setContentOffset from ViewController to scroll the view back to the first view?
}
So my question is how to access scrollview.setContentOffset from ViewController to scroll the view back to the first view? Am I on the right track? Or are there any alternative methods where I can tap a button and scroll the view back to its first page?
Thank you!
I can think of two good options here:
1) Hold a weak reference in View2 of the scrollView. in View2 add:
weak var scrollView: UIScrollView?
and in ViewController, after view2 creation add:
view2.scrollView = self.scrollView
now, in buttonHomeAction you'll have access to the scrollView.
2) If you are familiar with Apple's delegation pattern, you can add a delegate, which can be a weak reference of the presenting view controller.
Create a protocol for the delegate, using named by the view holds the delegate. so, in this case: View2Delegate
and add a method that describes the action.
protocol View2Delegate: AnyObject {
func buttonTapped()
}
so, in View2 add:
weak var delegate: View2Delegate?
and in ViewController, after view2 creation add:
view2.delegate = self
now, in ViewController implement the protocol method and access scrollView:
extension ViewController: View2Delegate {
func buttonTapped() {
// access scrollView as self.scrollView
}
}

Swift - scrollViewDidScroll not working with WKWebView

I'm trying to add a shadow to my (custom) nav bar when a user scrolls using scrollViewDidScroll but it doesn't do anything. I have the same exact code on another view controller but it has a tableView instead of a WKWebView and it works fine.
I tried adding webView.scrollView.delegate = self but I just get an error.
My code:
class ViewController: UIViewController {
#IBOutlet weak var webView: WKWebView!
#IBOutlet weak var navBar: UIView!
override func viewDidLoad() {
super.viewDidLoad()
addShadow()
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let navigationBar = navBar
let offset = scrollView.contentOffset.y / 10
if offset > 1.5 {
navigationBar?.layer.shadowOpacity = 0.15
} else {
navigationBar?.layer.shadowOpacity = Float(((3 * offset) / 20)/1.5)
}
}
func addShadow() {
navBar.layer.shadowColor = UIColor.black.cgColor
navBar.layer.shadowOffset = CGSize(width: 0, height: 2.0)
navBar.layer.shadowRadius = 6.0
navBar.layer.masksToBounds = false
}
}
I tried adding webView.scrollView.delegate = self but I just get an error.
You didn't share what the error was. I suspect though that you didn't declare your view controller as UIScrollViewDelegate conforming, which caused the compile time error when trying to set self as the scroll view delegate.
Change your view controller declaration to this:
class ViewController: UIViewController, UIScrollViewDelegate {

How do I completely hide this UIImageView

I have a UITableView with a list of items that can be filtered. When the user chooses a filter, a UIView is exposed using a height NSLayoutConstraint that changes from 0 to 40 pixels:
The circle with the X is the clear button that clears the filter and then closes the UIView by changing the height constraint back to 0.
The problem is that when the UIView closes, that clear button doesn't completely go away:
Here's the relevant code:
class LiftLogViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate {
let coreDataStack = CoreDataStack()
var liftEvents = [LiftEvent]()
//MARK: IB outlets
#IBOutlet var tableView: UITableView!
#IBOutlet weak var navItem: UINavigationItem!
#IBOutlet weak var filterViewHeightConstraint: NSLayoutConstraint!
#IBOutlet weak var clearFilterButton: UIImageView!
#IBOutlet weak var selectedFilter: UILabel!
#IBOutlet weak var clearButtonHeightConstraint: NSLayoutConstraint!
#IBOutlet weak var clearButtonView: UIImageView!
var isFilterViewOpen = false
override func viewDidLoad() {
let doneButton = UIBarButtonItem(title: "Done", style: .Plain, target: self, action: #selector(self.dismissLog(_:)))
let filterImage = UIImage(named: "filter_icon")
let filterButton = UIBarButtonItem(image: filterImage, style: .Plain, target: self, action: #selector(self.actionFilter))
self.navItem.rightBarButtonItems = [doneButton, filterButton]
let buttonTap = UITapGestureRecognizer(target: self, action: #selector(self.clearFilter))
clearFilterButton.addGestureRecognizer(buttonTap)
filterViewHeightConstraint.constant = 0.0
clearButtonHeightConstraint.constant = 0.0
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
let filterPredicate: NSPredicate?
if let logFilter = UserDefaultsManager.sharedInstance.logFilter?.rawValue {
filterPredicate = NSPredicate(format: "lift.liftName = [c] %#", logFilter)
print("viewWillAppear thinks the filter is \(logFilter)")
} else {
filterPredicate = nil
}
reloadData(filterPredicate)
let currentFilter = getCurrentLogFilter()
if currentFilter != nil {
selectedFilter.text = "Filtered by \(currentFilter!)"
isFilterViewOpen = true
clearButtonView.hidden = isFilterViewOpen ? false : true
} else {
selectedFilter.text = nil
}
super.viewWillAppear(animated)
}
override func viewDidAppear(animated: Bool) {
filterViewHeightConstraint.constant = isFilterViewOpen ? 40.0 : 0.0
clearButtonHeightConstraint.constant = isFilterViewOpen ? 21.0 : 0.0
clearButtonView.hidden = isFilterViewOpen ? false : true
UIView.animateWithDuration(0.33, delay: 0, options: [.CurveEaseOut], animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
func clearFilter() {
UserDefaultsManager.sharedInstance.logFilter = nil
isFilterViewOpen = !isFilterViewOpen
UIView.animateWithDuration(0.33, delay: 0, options: [.CurveEaseOut], animations: {
self.view.layoutIfNeeded()
}, completion: nil)
selectedFilter.text = nil
reloadData()
}
You can see I've tried both setting the .hidden value on the UIView that holds the clear button to true and I've tried changing the height constraint to 0.0 but neither of those make it gone completely.
Searching for a while hasn't produced any answers. Can anybody point out what's wrong with what I'm doing? Thanks.
It seems like the hair line color on the navigation bar may be clear resulting in the button still being slightly visible. Maybe change that and see if it covers the button. You can do so like this:
let view = UIView()
view.backgroundColor = UIColor.grayColor()
self.navigationController!.navigationBar.hairlineImageViewInNavigationBar(view)
As Dustin Spengler mentioned, the transparent hairline image view in the navigation bar causes the filter button to be slightly visible beneath it. As a workaround, you can hide the filter view (filterView.hidden = true) when constraint constant is set to 0.0 and unhide the filter view (filterView.hidden = false) when constraint constant is set to 40.0.
Thank you guys for your suggestions. It turns out that the solution was a little different, but your suggestions got me to poke around some more in that area and find the solution.
I neglected to mention that this was a view controller that I add a UIStackView that wrapped my UIView (the grey "filtered by" UIView) and the UITableView:
The problem was that the constraint I created from the top of the UIStackView to the top of its parent view was just slightly too big, pushing the top of the UIStackView just far enough to expose that little sliver. I reduced the Y distance to 63 and it's now perfect:
Thanks again for trying to help.

Reset/Refesh UIscroll view

I Have a scroll view that contains multiple view controllers. On those view controllers I have switches. When on switch is "on" all the other switches turn off. This is all done through the viewDidLoad.
I cannot get this to work though, I have tried putting the code for the switch thingy stuff that I am trying to do in viewWillAppear. It seems though that these two methods are only called at run time.
My alternative idea is to somehow "reset" the scroll view from inside one of the subviews
here is what i have:
class ViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
let vc0 = ViewController0(nibName: "ViewController0", bundle: nil)
self.addChildViewController(vc0)
self.scrollView.addSubview(vc0.view)
vc0.didMoveToParentViewController(self)
let vc1 = ViewController1(nibName: "ViewController1", bundle:nil)
var frame1 = vc1.view.frame
frame1.origin.x = self.view.frame.size.width
vc1.view.frame = frame1
self.addChildViewController(vc1)
self.scrollView.addSubview(vc1.view)
vc1.didMoveToParentViewController(self)
let vc2 = ViewController2(nibName: "ViewController2", bundle:nil)
var frame2 = vc2.view.frame
frame2.origin.x = self.view.frame.size.width * 2
vc2.view.frame = frame2
self.addChildViewController(vc2)
self.scrollView.addSubview(vc2.view)
vc2.didMoveToParentViewController(self)
let vc3 = ViewController2(nibName: "ViewController3", bundle:nil)
var frame3 = vc3.view.frame
frame3.origin.x = self.view.frame.size.width * 3
vc3.view.frame = frame3
self.addChildViewController(vc3)
self.scrollView.addSubview(vc3.view)
vc3.didMoveToParentViewController(self)
self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width * 4, self.view.frame.size.height - 66);
}
}
^for the scrollUI creator class
import UIKit
class ViewController0: UIViewController {
#IBOutlet weak var onoff: UISwitch!
override func viewDidLoad() {
super.viewDidLoad()
onoff.on = false
}
#IBAction func used(sender: AnyObject) {
let parent = self.view.superview
parent?.setNeedsDisplay()
}
}
^this is one of the subclasses
This subclass has a switch and when toggled, it should "reset" the scroll view so all of the subviews viewDidLoad are called again...
This does not work.... Are there any solutions to this??
BTW sorry for the bad formatting for the code blocks.

How to programmatically scroll to next view controller in Scroll View Container

I created a scroll view container that houses three view controllers. It's meant to mimic snapchat's swipe layout. however, I can't seem to get a code to manually switch to the next view controller without actually swiping (which I'm not interested in)
I tried calling the container class and setting it's scroll offset but it crashes... tried creating a delegate protocol, but delegate is returning nil... I'm stumped.
Here is my code:
class AViewController: UIViewController, ABViewControllerDelegate {
#IBOutlet var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
// 1) Create the three views used in the swipe container view
var ATVc : ATViewController = ATViewController(nibName: "ATViewController", bundle: nil);
var ACVc : ACViewController = ACViewController(nibName: "ACViewController", bundle: nil);
var ABVc : ABViewController = ABViewController(nibName: "ABViewController", bundle: nil);
// 2) Add in each view to the container view hierarchy
// Add them in opposite order since the view hieracrhy is a stack
self.addChildViewController(ABVc);
self.scrollView!.addSubview(ABVc.view);
ABVc.didMoveToParentViewController(self);
self.addChildViewController(ACVc);
self.scrollView!.addSubview(ACVc.view);
ACVc.didMoveToParentViewController(self);
self.addChildViewController(ATVc);
self.scrollView!.addSubview(ATVc.view);
ATVc.didMoveToParentViewController(self)
// 3) Set up the frames of the view controllers to align
// with eachother inside the container view
var adminFrame :CGRect = ATVc.view.frame;
adminFrame.origin.y = adminFrame.height;
ACVc.view.frame = adminFrame;
var BFrame :CGRect = ACVc.view.frame;
BFrame.origin.y = 2*BFrame.height;
ABVc.view.frame = BFrame;
// 4) Finally set the size of the scroll view that contains the frames
var scrollWidth: CGFloat = self.view.frame.width
var scrollHeight: CGFloat = 3 * self.view.frame.size.height
self.scrollView!.contentSize = CGSizeMake(scrollWidth, scrollHeight)
self.scrollView!.setContentOffset(CGPointMake(0, self.view.frame.height), animated: false)
var changeMe : String = "okay"
}
func scrollUp() {
println("clicked!")
self.scrollView.contentOffset.y - self.view.frame.height
}
}
and this is the view controller I'm trying to get out off by pressing a button..
protocol ABViewControllerDelegate {
func scrollUp()
}
class ABViewController: UIViewController {
let delegate = ABViewControllerDelegate?()
#IBAction func button(sender: AnyObject) {
println("button clicked!")
delegate!.scrollUp()
}
}
I feel like I'm leading myself on and that it can't be done!