It's my first try on IOS animation, so if I'm worry from the very beginning, just tell me the right direction.
All I want: when I click ButtonOne, Label disappears slowly.
The code as below:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var labelHeight: NSLayoutConstraint!
private var isHidden: Bool = false
#IBAction func clickButtonOne(sender: UIButton) {
isHidden = !isHidden
if isHidden {
labelHeight.constant = 0
} else {
labelHeight.constant = 60
}
UIView.animateWithDuration(1.0, animations: {
() -> Void in
self.view.layoutIfNeeded()
}, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
Before I click ButtonOne:
After I click ButtonOne(label shrinks from bottom to top):
The UILabel is disappearing, but it's content is still visible.
You need to set the clipsToBounds property of the UILabel to true.
label.clipsToBounds = true
You can set the same property in the interface builder by checking the Clip Subviews property in the attributes inspector.
I think you should also animate UIView.alpha property:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var button: UIButton!
#IBOutlet weak var labelHeight: NSLayoutConstraint!
private var isHidden: Bool = false
#IBAction func clickButtonOne(sender: UIButton) {
isHidden = !isHidden
var alpha: CGFloat = 1
if isHidden {
alpha = 0
labelHeight.constant = 0
} else {
labelHeight.constant = 60
}
UIView.animateWithDuration(1.0, animations: {
() -> Void in
self.button.alpha = alpha
self.view.layoutIfNeeded()
}, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
Related
Main.StoryBoard in this way
class ForgotPasswordContainerControl: UIViewController {
#IBOutlet var screenStep1: UIView?
#IBOutlet var screenStep2: UIView?
#IBOutlet var screenStep3: UIView?
override func viewDidLoad() {
super.viewDidLoad()
self.screenStep1?.alpha = 1.0
self.screenStep2?.alpha = 0.0
self.screenStep3?.alpha = 0.0
}
#IBAction func step1ButtonClick(_ sender: UIButton) {
UIView.animate(withDuration: 0.5, animations: {
self.screenStep1?.alpha = 0.0
self.screenStep2?.alpha = 1.0
self.screenStep3?.alpha = 0.0
print("clicked button1 ")
})
print("clicked button2 ")
}
}
My code is working in viewdDidLoad, clicking the button prints is working
but Alpha does not work, how can i do?
I want to update the layout of a popover, I've already tried using the setNeedsLayout() and layoutIfNeeded() methods but couldn't find a solution.
I have a simple screen with 4 buttons that call a popover, within the popover there are 2 extra buttons:
Button -> hides button3, and moves button1 and button2 to the left.
reposition -> changes the sourceview of the popover from the button1/2/3/4 (sender) to button4.
Picture of the layout
The problem I have is that I'm not able to update/refresh the screen, and the popover keeps pointing to the former source view position.
Picture of the popover
Somehow I need a method that updates my view and which is stronger than layoutIfNeeded() because if the screen is changed from portrait/landscape the popover changes automatically. Here I changed portrait/landscape/portrait
GitHub of the project. GitHub
The code used is the following:
class ViewController: UIViewController, ButtonDidDisappearDelegate {
#IBOutlet weak var button1: UIButton!
#IBOutlet weak var button2: UIButton!
#IBOutlet weak var button3: UIButton!
#IBOutlet weak var button4: UIButton!
#IBOutlet weak var constrain2: NSLayoutConstraint!
var popVC: PopVC?
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func buttonPopover(_ sender: UIButton) {
configureAndPresentPopover(from: sender)
}
func buttonDisappear() {
self.constrain2.constant = 100
self.button3.isHidden = !self.button3.isHidden
if !self.button3.isHidden {
self.constrain2.constant = 10
}
}
func repositionPopover() {
DispatchQueue.main.async {
if let popVC = self.popVC {
self.self.popoverPresentationController(popVC.popoverPresentationController!, willRepositionPopoverTo: self.button4.bounds, in: self.button4)
}
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
}
}
}
extension ViewController: UIPopoverPresentationControllerDelegate {
func configureAndPresentPopover(from sender: UIButton) {
popVC = storyboard?.instantiateViewController(withIdentifier: "popVC") as? PopVC
guard let popVC = popVC else {
return
}
popVC.popOverDelegate = self
popVC.modalPresentationStyle = .popover
let popOverVC = popVC.popoverPresentationController
popOverVC?.delegate = self
popOverVC?.sourceView = sender
popOverVC?.sourceRect = sender.bounds
popVC.preferredContentSize = CGSize(width: 300, height: 60)
popOverVC?.permittedArrowDirections = .down
self.present(popVC, animated: true)
}
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
func popoverPresentationController(_ popoverPresentationController: UIPopoverPresentationController,
willRepositionPopoverTo rect: CGRect,
in view: UIView) {
popoverPresentationController.sourceView = view
popoverPresentationController.sourceRect = rect
}
}
and the popover controller:
protocol ButtonDidDisappearDelegate: class {
func configureAndPresentPopover(from sender: UIButton)
func buttonDisappear()
func repositionPopover()
}
class PopVC: UIViewController {
weak var popOverDelegate: ButtonDidDisappearDelegate?
override func viewDidLoad() {
super.viewDidLoad()
}
#IBOutlet weak var popoverButton: UIButton!
#IBAction func popoverAction(_ sender: Any) {
popOverDelegate?.buttonDisappear()
DispatchQueue.main.async {
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
}
}
#IBAction func reposition(_ sender: Any) {
popOverDelegate?.repositionPopover()
}
}
You need to specify the new position of the arrow and ask for the layout of the presentation controller's view, not only the presented view.
Try :
func repositionPopover() {
let popOverController = presentedViewController?.presentationController as? UIPopoverPresentationController
popOverController?.sourceView = button4
popOverController?.containerView?.setNeedsLayout()
popOverController?.containerView?.layoutIfNeeded()
}
You can try setting the sourceview and sourcerect once again. call this function when the sourcview bounds are changed.
A function whose argument is used for Extension of another class is described.
I want to change the value of the UIView property (alpha) that exists in that function "at the button tap in another class".
However, this function can be changed at ViewDidLoad time.
How can I change the value when tapping buttons?
If possible please write the code.
ViewController Class
class ViewController: UIViewController {
#IBOutlet weak var vHome: UICollectionView!
#IBOutlet weak var vSearch: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
selectRd(rd: 3) //This time can change calue of alpha.
}
}
extension ViewController {
func selectRd(rd reader:Int){
var animateView:UIView!
let animateVHome = vHome
let animateVSearch = vSearch
UIView.animate(withDuration: 0.3, delay: 0.0, animations: {
animateVHome.alpha = 0.0
animateVSearch.alpha = 0.0
}, completion: nil)
switch reader {
case 2:
animateView = animateVHome
case 3:
animateView = animateVSearch
default:
break
}
UIView.animate(withDuration: 0.3, delay: 0.3, animations: {
animateView.alpha = 1.0
}, completion: nil)
}
}
Another Class
class Another{
#objc func buttonTapped(sender : HeaderButton) {
let vC = ViewController
vC.selectRd(rd: 2) //This time can not!!
}
}
Please comment if you can not understand the question.
The problem is that you can't access a function of a class if its currently active , as this will result in a crash , so Add a var in viewControler
class ViewController: UIViewController {
#IBOutlet weak var vHome: UICollectionView!
#IBOutlet weak var vSearch: UICollectionView!
var index:Int?
override func viewDidLoad() {
super.viewDidLoad()
selectRd(rd: self.index) //This time can change calue of alpha.
}
}
..
class Another{
#objc func buttonTapped(sender : HeaderButton) {
let vC = ViewController
vC.index = 2 //This time can not!!
}
}
Another problem arrived me. I have a view covering my hole screen. In it a webView for showing a youTube video and a button for closing. The view is load via loadNibNamed() and no matter what I'm doing, my IBAction never called by pressing that button.
I tried to make an IBAction via storyboard, also via addTarget to a buttonoutlet. Both never called. My button is reachable when I click it, it show the default touchanimation. Also printing the button outlet in viewDidLoad() says <UIButton: 0x17d25430; frame = (15 8; 39 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x17d25ae0>> so it is not nil.
My Layout looks like the following.
MainScreen: UIViewController, UITableViewDelegate, UITableViewDataSource, UIWebViewDelegate{}
In one of mainScreens tableView is a customCell named videoViewCell implemented with:
let cell = NSBundle.mainBundle().loadNibNamed("VideoViewCell", owner: self, options: nil)!.first as! VideoViewCell
videoViewCell: UITableViewCell , UITableViewDelegate, UITableViewDataSource {} has:
weak var delegate: ActivityDetailVideoCellDelegate?
...
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
delegate?.selectedCellAtIndex(indexPath.row)
}
...
protocol ActivityDetailVideoCellDelegate: class {
func selectedCellAtIndex(index: Int)
}
My mainScreen class has:
extension MainScreen: ActivityDetailVideoCellDelegate {
func selectedCellAtIndex(index: Int) {
let youtubeLink: String = "http://www.youtube.com/embed/\(selectedVideo)"
let youtubePopup = YouTubePopUpController()
youtubePopup.view.frame = self.view.bounds
youtubePopup.view.alpha = 0
youtubePopup.view.transform = CGAffineTransformMakeScale(1.3, 1.3)
let code: String = "<iframe width=\(youtubePopup.webView.bounds.width) height=\(youtubePopup.webView.bounds.height) src=\(youtubeLink) frameborder=0 allowfullscreen></iframe> <style>body { margin: 0; padding: 0; }</style>"
youtubePopup.webView.loadHTMLString(code, baseURL: nil)
self.view.addSubview(youtubePopup.view)
UIView.animateWithDuration(0.25, animations: { () -> Void in
youtubePopup.view.alpha = 1
youtubePopup.view.transform = CGAffineTransformMakeScale(1, 1)
})
}
}
YouTubePopUpController: UIViewController:
#IBOutlet weak var backgroundView: UIView!
#IBOutlet weak var webView: UIWebView!
#IBOutlet weak var closeButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
print(closeButton)
closeButton.addTarget(self, action: #selector(self.closeButtonClicked(_:)), forControlEvents: .TouchUpInside)
}
#IBAction func closeButtonClicked(sender: AnyObject) {
print("close clicked")
UIView.animateWithDuration(0.25, animations: { () -> Void in
self.view.transform = CGAffineTransformMakeScale(1.3, 1.3)
self.view.alpha = 0
}) { (finished) -> Void in
self.view.removeFromSuperview()
}
}
my xib:
Finally solved my Problem by writing the #IBAction func closeButtonClicked(sender: AnyObject) {} inside my MainScreenViewController an adding Target inside func selectedCellAtIndex(index: Int) {} to call my youtubePopUp inside closeButtonClicked I made it global:
#IBAction func closeButtonClicked(sender: AnyObject) {
print("close clicked")
youtubePopup!.webView.loadHTMLString("about:blank", baseURL: nil)
youtubePopup!.webView.mediaPlaybackRequiresUserAction = false
UIView.animateWithDuration(0.25, animations: { () -> Void in
self.youtubePopup!.view.transform = CGAffineTransformMakeScale(1.3, 1.3)
self.youtubePopup!.view.alpha = 0
}) { (finished) -> Void in
self.youtubePopup!.view.removeFromSuperview()
}
}
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.