UIView animate is not animating - animation

I want to hide logo(Imageview) and show search bar by animately.But when code run to be hidden animations works immediately (it must be in 2 seconds).search bar is visible in 2 seconds by animately.what is wrong in this code?
UIView.transition(with: self.logo, duration: 2, options: .transitionCrossDissolve, animations: {
self.logo.isHidden = true
}) { (completed) in
UIView.transition(with: self.searchBar, duration: 2, options: .transitionCrossDissolve, animations: {
self.searchBar.isHidden = false
},completion: nil)
}

As pointed in the comments , you need to use the alpha property to create an effect of appearance/disappearance. So your code will look something like:
UIView.transition(with: self.logo, duration: 2, options: .transitionCrossDissolve, animations: {
self.logo.alpha = 0
}) { (completed) in
UIView.transition(with: self.searchBar, duration: 2, options: .transitionCrossDissolve, animations: {
self.searchBar.alpha = 1
},completion: nil)
}
As stated in the apple docs here: https://developer.apple.com/documentation/uikit/uiview , the
The following properties of the UIView class are animatable: frame, bounds,center, transform,alpha , background colour

Related

Animation is lost when view is not displayed (yet) in SwiftUI

I have a button implemented like so:
struct CircleButtonView: View {
init(_ content: Image, tutorial: Bool = false, _ action: (() -> ())? = nil) {
self.content = content
self.repetitions = tutorial ? 6.0 : 0.0
self.action = action
}
let content: Image
var repetitions: CGFloat
let action: (() -> ())?
var body: some View {
Button(action: {
action?()
}) {
Circle()
.fill(.white)
.shadow(color: Color(hex: 0x000000, alpha: 0.1), radius: 10, x: 0, y: 10)
.overlay(
GeometryReader { proxy in
content
.resizable()
.aspectRatio(contentMode: .fit) // 1:1
.frame(width: proxy.size.width * 0.4)
.position(x: proxy.size.width / 2, y: proxy.size.height / 2)
}
)
.aspectRatio(1 / 1, contentMode: .fit)
}
.shake(repetitions: repetitions)
.animation(repetitions != 0 ? .linear(duration: 1).delay(2).repeatForever(autoreverses: false) : .default, value: repetitions)
}
}
Via the tutorial bool i want to manipulate whether the button animates (an initial shake animation used to explain the button, if the user clicked it once i remove the animation).
This works nicely. However i have to use a "hack", which i dont like and will describe now.
I call the button in some parent view like so:
CircleButtonView(Image("flash.selected"), tutorial: <condition for tutorial> && appeared) {
// vm.boost()
}
.onAppear {
appeared = true
}
As you can see, despite my condition i also have to check wheter the button has appeared. If i would not do that, the animation would be lost ... (this is, as the init block runs and the view did not appear yet, any future calls, where the view appeared, do work perfectly)
As this does not feel right, is this the correct way ?
In order to animate, SwiftUI needs to observe a before state of the view and an after state. As you've seen, SwiftUI needs to see the repetitions value change from 0 to 6 in order to perform the animation. Processing the .onAppear { } from the user of CircleButtonView is the wrong place. Put that code inside of CircleButtonView.
Make repetitions into an #State private var. Don't set it in init().
#State private var repetitions = 0
In init(), store tutorial in a local let:
self.tutorial = tutorial
Then add this .onAppear to your Button:
}
.shake(repetitions: repetitions)
.animation(repetitions != 0 ? .linear(duration: 1).delay(2).repeatForever(autoreverses: false) : .default, value: repetitions)
.onAppear {
repetitions = tutorial ? 6.0 : 0.0
}

Method collectionView (didSelectItemAt...) doesn't Work at iTunesConnect; However, It does Work on Debug

I've updated my Xcode to the latest version, currently it's 10.2.1(10E1001) and migrated my project from Swift 4 to Swift 5.
It made me some troubles, but finally I've built my project and it works correctly from debug version on my iPhone.
After that I've had few troubles with archiving my project (maybe it could be a reason)
I've upload it in App Store and after that tried my app at TestFlight.
Plus, for some reason few code in my project works wrong.
It seems like collectionView(didSelectItemAtIndexPath...) doesn't work (but it perfectly works in Xcode) and my custom layout of collectionView doesn't work too (but also works on Debug).
It seems like layout works wrong, but I can't understand what's the difference between Debug and Release version except provisioning profile.
I can share you more videos, code, w/e you need, I really need to resolve this issue.
I've not found anything else like that in the web
I've taken that custom layout code from here https://codereview.stackexchange.com/questions/197017/page-and-center-uicollectionview-like-app-store
class SnapPagingLayout: UICollectionViewFlowLayout {
private var centerPosition = true
private var peekWidth: CGFloat = 0
private var indexOfCellBeforeDragging = 0
convenience init(centerPosition: Bool = true, peekWidth: CGFloat = 40, spacing: CGFloat? = nil, inset: CGFloat? = nil) {
self.init()
self.scrollDirection = .horizontal
self.centerPosition = centerPosition
self.peekWidth = peekWidth
if let spacing = spacing {
self.minimumLineSpacing = spacing
}
if let inset = inset {
self.sectionInset = UIEdgeInsets(top: 0, left: inset, bottom: 0, right: inset)
}
}
override func prepare() {
super.prepare()
guard let collectionView = collectionView else { return }
self.itemSize = calculateItemSize(from: collectionView.bounds.size)
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
guard let collectionView = collectionView,
!newBounds.size.equalTo(collectionView.bounds.size) else {
return false
}
itemSize = calculateItemSize(from: collectionView.bounds.size)
return true
}
}
private extension SnapPagingLayout {
func calculateItemSize(from bounds: CGSize) -> CGSize {
return CGSize(
width: bounds.width - peekWidth * 2,
height: (bounds.width - peekWidth * 2) / 1.77
)
}
func indexOfMajorCell() -> Int {
guard let collectionView = collectionView else { return 0 }
let proportionalOffset = collectionView.contentOffset.x
/ (itemSize.width + minimumLineSpacing)
return Int(round(proportionalOffset))
}
}
extension SnapPagingLayout {
func willBeginDragging() {
indexOfCellBeforeDragging = indexOfMajorCell()
}
func willEndDragging(withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
guard let collectionView = collectionView else { return }
// Stop scrollView sliding
targetContentOffset.pointee = collectionView.contentOffset
// Calculate where scrollView should snap to
let indexOfMajorCell = self.indexOfMajorCell()
guard let dataSourceCount = collectionView.dataSource?.collectionView(collectionView, numberOfItemsInSection: 0),
dataSourceCount > 0 else {
return
}
// Calculate conditions
let swipeVelocityThreshold: CGFloat = 0.3 // After some trail and error
let hasEnoughVelocityToSlideToTheNextCell = indexOfCellBeforeDragging + 1 < dataSourceCount && velocity.x > swipeVelocityThreshold
let hasEnoughVelocityToSlideToThePreviousCell = indexOfCellBeforeDragging - 1 >= 0 && velocity.x < -swipeVelocityThreshold
let majorCellIsTheCellBeforeDragging = indexOfMajorCell == indexOfCellBeforeDragging
let didUseSwipeToSkipCell = majorCellIsTheCellBeforeDragging
&& (hasEnoughVelocityToSlideToTheNextCell || hasEnoughVelocityToSlideToThePreviousCell)
guard didUseSwipeToSkipCell else {
// Better way to scroll to a cell
collectionView.scrollToItem(
at: IndexPath(row: indexOfMajorCell, section: 0),
at: centerPosition ? .centeredHorizontally : .left, // TODO: Left ignores inset
animated: true
)
return
}
let snapToIndex = indexOfCellBeforeDragging + (hasEnoughVelocityToSlideToTheNextCell ? 1 : -1)
var toValue = CGFloat(snapToIndex) * (itemSize.width + minimumLineSpacing)
if centerPosition {
// Back up a bit to center
toValue = toValue - peekWidth + sectionInset.left
}
// Damping equal 1 => no oscillations => decay animation
UIView.animate(
withDuration: 0.3,
delay: 0,
usingSpringWithDamping: 1,
initialSpringVelocity: velocity.x,
options: .allowUserInteraction,
animations: {
collectionView.contentOffset = CGPoint(x: toValue, y: 0)
collectionView.layoutIfNeeded()
},
completion: nil
)
}
}
I wanna see page and center collection view like in App Store. And also I wanna make my didSelect-method work correctly.
This is a bug for Swift 5.0 compiler related to this references:
https://bugs.swift.org/browse/SR-10257
.
Update:
Further searching found an temporary answer at this link on Stackoverflow
You can work around it by explicitly tagging it with #objc for now.

Override show segue ( transmition left to right )

I want to override the Show Segue , And change it to be from left to right .
I tried to make a custom segue and it worked pretty well but without the navigation bar
So , I need a segue from left to right and a navigation bar with button on the top right (to go back) .
My Code
import UIKit
class SegueFromLeft: UIStoryboardSegue
{
override func perform()
{
let src = self.sourceViewController
let dst = self.destinationViewController
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransformMakeTranslation(-src.view.frame.size.width, 0)
UIView.animateWithDuration(0.25,
delay: 0.0,
options: UIViewAnimationOptions.CurveEaseInOut,
animations: {
dst.view.transform = CGAffineTransformMakeTranslation(0, 0)
},
completion: { finished in
src.presentViewController(dst, animated: false, completion: nil)
}
)
}
}

How to hide the second uibaritem in swift 2

I have 2 bar items as shown below how can I hide the second one when I click on the first one ? ( i tried earthBtn.hidden = true but its not working. Here is my code:
let earthImg = UIImage(named: "earth0")
let earthBtn = UIBarButtonItem(image: earthImg, style: .Plain, target: self, action: "earthBtn_click")
let messageImg = UIImage(named: "categories1")
let messageBtn = UIBarButtonItem(image: messageImg, style: .Plain, target: self, action: "messageBtn_click")
let buttonArray = NSArray(objects: earthBtn,messageBtn)
self.navigationItem.rightBarButtonItems = buttonArray as? [UIBarButtonItem]
func messageBtn_click() {
earthBtn.hidden = true // is not working
}
thank you.
Alright, you cannot hide a UIBarButtonItem and what you can do is make the color transparent and disable it, and when you wanna use it back then you have to enable it and then give it a color:
Define it globally as class variable :
let earthBtn = UIBarButtonItem()
Use it like :
earthBtn = UIBarButtonItem(image: earthImg, style: .Plain, target: self, action: "earthBtn_click")
hide the button:
func messageBtn_click() {
earthBtn.enabled = false
earthBtn.color = UIColor.clearColor()
}

runAction(_:completion:) does not show Animation correctly

I would like to run two actions at the same time and after them another two actions at the same time. Basically I would like to have two groups of action and run them in sequence. I could not manage to group my actions so I used the runAction(_:completion:) function:
self.orangeQuestionmark.runAction(group, completion: {
})
self.blueQuestionmark.runAction(group, completion: {
bubbleArray[0].hidden = false
pony.runAction(ponyMove)
})
This works fine unless this call:
pony.runAction(ponyMove)
With this call I call the animation. See code:
let ponyMove = ponyClass.movingPony("ponyScene3Move1", secondImage: "ponyScene3Move2")
class Pony: SKSpriteNode {
func movingPony(firstImage: String, secondImage: String) ->SKAction{
let movePony = SKAction.animateWithTextures([SKTexture(imageNamed: secondImage), SKTexture(imageNamed: firstImage)], timePerFrame: 0.4, resize: true, restore: false)
moving.append(movePony)
moving.append(SKAction.repeatAction(movePony, count: 6))
let group = SKAction.group(moving)
return group
}
}
However when I run this function outside my runAction(_:completion:) call it works perfectly fine.
Does anyone know what my fault is?

Resources