Swift ios 10 NavBar Item keeps growing - swift

I have a navBar Controller connected to a UIView, I have a right bar button item that is a chevron. I have programmatically created a search bar. If you click the chevron about 20-100 times it keeps growing until it is off the screen. I can see each time I click the chevron a slight bump in my search bar. Since you can not place constraints on navBar and fixed Space bar button item does not work either. Any suggestions on where to look or how to fix this?
func rotateChevron(animated: Bool = true) {
let chevAnimate = animated ? 0.3 : 0.0
let chevIsDown = messagePicker.frame.origin.y == self.view.frame.height - (tabBarController?.tabBar.frame.height ?? 0)
let rotation: CGFloat = chevIsDown ? 0.0 : 180.001
UIView.animate(withDuration: chevAnimate, animations: {
self.filterChevron.customView?.transform = CGAffineTransform(rotationAngle: rotation.degreesToRadians)
}, completion: nil)
}

After some research I placed within the animation blocks a forced CGSize (w/h) and this seems to have solved the issue. I also found that transform animation should not be used with frames because it moved the bounds of the image each time which is why the chevron was acting up.
func rotateChevron(animated: Bool = true) {
let chevAnimate = animated ? 0.3 : 0.0
let chevIsDown = messagePicker.frame.origin.y == self.view.frame.height - (tabBarController?.tabBar.frame.height ?? 0)
let rotation: CGFloat = chevIsDown ? 0.0 : 180.001
filterChevron.customView?.frame.size = CGSize(width: 35, height: 30)
UIView.animate(withDuration: chevAnimate, animations: {
self.filterChevron.customView?.transform = CGAffineTransform(rotationAngle: rotation.degreesToRadians)
}, completion: nil)
}

Related

show UIView like its coming from another view

I am creating a popout view for some selection purpose now what I have done is hide the whole UI to the right side of the mobile view and when the user taps on the button slide UI in the visile area for which I have written
For open :
let originalTransform = self.rightPopView.transform
let scaledAndTranslatedTransform = originalTransform.translatedBy(x: -330, y: 0)
UIView.animate(withDuration: 0.5, animations: {
self.rightPopView.transform = scaledAndTranslatedTransform
})
For close :
let originalTransform = self.rightPopView.transform
let scaledAndTranslatedTransform = originalTransform.translatedBy(x: 330, y: 0)
UIView.animate(withDuration: 0.5, animations: {
self.rightPopView.transform = scaledAndTranslatedTransform
})
with this, I have achieved this result
as you can see in this image view I am trying to show hide is visible on the back of the vertical bar view
what i want is uiview should open from a vertical bar, not screen.

how to fix view under navigation bar swift

i make popup using EzPopup library, i get problem when i put popup under navigation bar.
this my code
#IBAction func showTopRightButton(_ sender: Any){
guard let pickerVC = pickerVC else { return }
pickerVC.delegate = self
let popupVC = PopupViewController(contentController: pickerVC, position: .topRight(CGPoint(x: 0, y: navigationController!.navigationBar.frame.height+20)), popupWidth: 100, popupHeight: 200)
popupVC.cornerRadius = 5
present(popupVC, animated: true, completion: nil)
}
i got a problem like my image
enter image description here
how to make same in iphone x and iphone x
In iPhone X portrait mode, the status bar is taller — 44 pts, not 20 pts
You need to add the statusBar Frame height also. Try below code:
//1.0 Get the Top bar height
let topBarHeight = UIApplication.shared.statusBarFrame.size.height + (self.navigationController?.navigationBar.frame.height ?? 0.0)
let popupVC = PopupViewController(contentController: pickerVC, position: .topRight(CGPoint(x: 0, y: topBarHeight)), popupWidth: 100, popupHeight: 200)
You can read more information on UILayout here.

UIView.animateWithDuration not animating after initial animation

I have two methods:
private func showPicker() {
UIView.animate(withDuration: 0.3,
animations: {
var pickerFrame = self.vPickerWrapper.frame
pickerFrame.origin.y = self.view.frame.size.height - 300.0
self.vPickerWrapper.frame = pickerFrame
self.bIsShowingPicker = true
self.view.layoutIfNeeded()
self.view.updateConstraintsIfNeeded()
})
}
private func closeThePicker() {
UIView.animate(withDuration: 0.3,
animations: {
var pickerFrame = self.vPickerWrapper.frame
pickerFrame.origin.y = self.view.frame.size.height + 1
self.vPickerWrapper.frame = pickerFrame
self.bIsShowingPicker = false
self.view.layoutIfNeeded()
self.view.updateConstraintsIfNeeded()
})
....
the first method is called when the user touches a text field that requires them to populate from the pickerview. The second method is called when either the close or select button is touched within the wrapper.
The wrapper is created in storyboard and has constraints (trailing, leading bottom) to position it off screen. I initially made the bottom constraint a IBOutlet and wanted to change its constant to handle the animation. (Which I do with other objects in this VC). I then tried to work with CGAffineTransform.translate and .identity and finally dropped down to working with the frame. In all three cases the wrapper will display but not close (move back off screen).
Here's the value of vPickerWrapper after I set its frame to pickerFrame:
pickerFrame CGRect (origin = (x = 0, y = 668), size = (width = 375, height = 300))
which is what I am expecting, just not any animation in the sim. The view never moves. Any idea why the display is not showing it in the new coordinates?

Weird UIVisualEffectView behavior in multitasking

I have an AccountsViewController which has UIVisualEffectView with blur effect in background (subview at index 0), so that it covers previous controller with blur during transition. But when I then switch to another app and open multitasking menu again to switch back to my app, its blurry UIVisualEffectView seem to be damaged (as shown on the screenshot 1). When I make my app active again, the view gets "repaired" and looks ok again (as shown on the second screenshot)
Some code from my custom transitioning class where I add the blur view
// in the animateTransition.. method
guard let container = transitionContext.containerView() else {
return
}
let blurEffectView: UIVisualEffectView
if container.viewWithTag(101) != nil {
blurEffectView = container.viewWithTag(101)! as! UIVisualEffectView
}
else {
blurEffectView = UIVisualEffectView(frame: container.frame)
blurEffectView.translatesAutoresizingMaskIntoConstraints = false
blurEffectView.tag = 101
container.addSubview(blurEffectView)
}
if self.isPresenting {
// We're presenting a view controller over another
toViewController.view.transform = CGAffineTransformMakeScale(0.7, 0.7)
container.addSubview(toViewController.view)
container.sendSubviewToBack(blurEffectView)
toViewController.view.alpha = 0
UIView.animateWithDuration(self.transitionDuration(transitionContext), delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.8, options: [], animations: { () -> Void in
fromViewController.view.transform = CGAffineTransformMakeScale(0.8, 0.8)
toViewController.view.transform = CGAffineTransformMakeScale(1, 1)
blurEffectView.effect = UIBlurEffect(style: .Dark)
toViewController.view.alpha = 1
}, completion: { (completed) -> Void in
self.context?.completeTransition(completed)
})
}
else {
// We're dismissing a view controller
UIView.animateWithDuration(self.transitionDuration(transitionContext), delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.8, options: [], animations: { () -> Void in
fromViewController.view.transform = CGAffineTransformMakeScale(0.7, 0.7)
toViewController.view.transform = CGAffineTransformMakeScale(1, 1)
blurEffectView.effect = nil
fromViewController.view.alpha = 0
}, completion: { (completed) -> Void in
fromViewController.view.removeFromSuperview()
self.context?.completeTransition(completed)
})
}
Seems like I've figured it out myself: this issue appears only when there is an UIWindow back (which is black) showing through.
In this question I had a transition animation container with these views:
fromViewController's view (with a scale transform 0.8;0.8)
UIVisualEffectView with .Dark style blur applied to it
toViewController's view
Because of fromViewController's view size (which was smaller than the screen because of scale transform), the black UIWindow view was showing through. And according to my research this causes UIVisualEffectView to produce a glitch described in this question.
The solution is to add a black UIView with the frame of an UIWindow and add it to the bottom of the container's view hierarchy:
let blackView = UIView(frame: container.frame)
blackView.backgroundColor = UIColor.blackColor()
container.insertSubview(blackView, atIndex: 0)
And then this glitch seem to appear no longer.

UIScrollView with "Circular" scrolling

I am trying to make "Circular" scrolling in my UIScrollView, but unsuccessful.
What I want to do:
if uiscrollview reaches end, it should move to start
if uiscrollview at start and moving back, it should move to end
Appending scrollview isn't good way in my situation (other methods should get "page id")
Have you any ideas?
I've implemented this method, but it requires paging enabled. Lets assume you have five elements A,B,C,D and E. When you set up your view, you add the last element to the beginning and the first element to the end, and adjust the content offset to view the first element, like this E,[A],B,C,D,E,A. In the UIScrollViewDelegate, check if the user reach any of the ends, and move the offset without animation to the other end.
Imagine the [ ] indicates the view being shown:
E,A,B,C,[D],E,A
User swipes right
E,A,B,C,D,[E],A
User swipes right
E,A,B,C,D,E,[A]
Then, automatically set the content offset to the second element
E,[A],B,C,D,E,A
This way the user can swipe both ways creating the illusion of an infinite scroll.
E,A,[B],C,D,E,A
Update
I've uploaded a complete implementation of this algorithm. It's a very complicated class, because it also has on-click selection, infinite circular scroll and cell reuse. You can use the code as is, modify it or extract the code that you need. The most interesting code is in the class TCHorizontalSelectorView.
Link to the file
Enjoy it!
Update 2
UICollectionView is now the recommended way to achieve this and it can be used to obtain the very same behavior. This tutorial describes in details how to achieve it.
Apple has a Street Scroller demo that appears to have exactly what you want.
There's also a video from WWDC 2011 that demos their demo. ;) They cover infinite scrolling first in the video.
Try to use following code..
Sample code..
- (void)scrollViewDidEndDecelerating:(UIScrollView *)sender
{
if (scrollView.contentOffset.x == 0) {
// user is scrolling to the left from image 1 to image n(last image).
// reposition offset to show image 10 that is on the right in the scroll view
[scrollView scrollRectToVisible:CGRectMake(4000,0,320,480) animated:NO];// you can define your `contensize` for scrollview
}
else if (scrollView.contentOffset.x == 4320) {
// user is scrolling to the right from image n(last image) to image 1.
// reposition offset to show image 1 that is on the left in the scroll view
[scrollView scrollRectToVisible:CGRectMake(320,0,320,480) animated:NO];
}
}
Hope, this will help you...
With reference from #redent84, find the code logic.
override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
scrollView.contentSize = CGSize(width: scrollView.frame.width * CGFloat(imagesArray.count), height: scrollView.frame.height)
scrollView.isPagingEnabled = true
// imagesArray.insert(imagesArray.last as? UIImage, at: 0)
// imagesArray.insert(imagesArray.first as? UIImage, at: imagesArray.count - 1)
var testArr = ["A", "B", "C", "D"]
let firstItem = testArr.first
let lastItem = testArr.last
testArr.insert(lastItem as! String, at: 0)
testArr.append(firstItem as! String)
print(testArr)
for i in 0..<imagesArray.count{
let imageview = UIImageView()
imageview.image = imagesArray[i]
imageview.contentMode = .scaleAspectFit
imageview.clipsToBounds = true
let xPosition = self.scrollView.frame.width * CGFloat(i)
imageview.frame = CGRect(x: xPosition, y: 0, width: self.scrollView.frame.width, height: self.scrollView.frame.height)
print(imageview)
scrollView.addSubview(imageview)
print("Imageview frames of i \(i) is \(imageview.frame)")
}
newStartScrolling()
}
func newStartScrolling()
{
ViewController.i += 1
let x = CGFloat(ViewController.i) * scrollView.frame.size.width
scrollView.setContentOffset(CGPoint(x: x, y: 0), animated: true)
print("X is \(x) and i is \(ViewController.i)")
if ViewController.i == imagesArray.count - 1 {
ViewController.i = 0
let x = CGFloat(ViewController.i) * scrollView.frame.size.width
//scrollView.setContentOffset(CGPoint(x: x, y: 0), animated: false)
print("X (rotate) is \(x) and i is \(ViewController.i)")
scrollView.contentOffset.x = x
self.newStartScrolling()
}
}
func backScrolling() {
ViewController.i -= 1
let x = CGFloat(ViewController.i) * scrollView.frame.size.width
scrollView.setContentOffset(CGPoint(x: x, y: 0), animated: true)
print("X is \(x) and i is \(ViewController.i)")
if ViewController.i <= 0 {
ViewController.i = imagesArray.count - 1
let x = CGFloat(ViewController.i) * scrollView.frame.size.width
scrollView.setContentOffset(CGPoint(x: x, y: 0), animated: false)
print("X (rotate) is \(x) and i is \(ViewController.i)")
self.backScrolling()
//scrollView.contentOffset.x = x
return
}
}