Swift contentOffset scroll - swift

I am developing a small application for tvOS where I need to show a UITextView.
Unfortunately sometimes this text can't fit inside the screen, that's why I need a way to scroll to the bottom of it programmatically.
I've tried using the following code:
self.setContentOffset(offset, animated: true)
It's actually working as intended, except for the fact that I need to handle the animation speed, so that the user can actually read; at the moment it's too fast.
This is what I tried to do, but with little success:
let offset = CGPoint(x: 0, y: contentSize.height - bounds.size.height)
UIView.animate(withDuration: 4, animations: {
self.setContentOffset(offset, animated: false)
})
I need a way to keep the text in place and scroll it to show the missing lines.
I am using a UITextView inside an UIScrollView.
Thanks.

If anyone is looking for a solution, this is what I ended up using:
var textTopDistance = 100
//calculate height of the text not being displayed
textNotVisibleHeight = descriptionLabel.contentSize.height - scrollView.bounds.size.height
func scrollText() {
//start new thread
DispatchQueue.main.async() {
//animation
UIView.animate(withDuration: 6, delay: 2, options: UIViewAnimationOptions.curveLinear, animations: {
//set scrollView offset to move the text
self.scrollView.contentOffset.y = CGFloat(self.textNotVisibleHeight - self.textTopDistance)
}, completion: nil)
}
}
It's not perfect I know, but at least it's working as intended.

Related

How To Implement Auto Scroll to TextView in Swift?

I want to implement a program that lets the user click on a button and the textView should auto scroll to the bottom. I have tried many things available on the internet but not working as I want, I am new to Xcode, Please help...
This is what I have tried:
self.textView.isScrollEnabled = false
UIView.animate(withDuration: 12.0, delay: 0,options: ([UIView.AnimationOptions .repeat]), animations: {() -> Void in
self.textView.contentOffset = CGPointMake(0, self.textView.bounds.size.height)
}, completion: { _ in })
This is working but not as I want. It only scrolls the text which is on the screen not all the text.. please help..
I have also tried this:
scrollView.contentOffset = CGPointMake(0,0);
CGPoint point = textfield.frame.origin ;
scrollView.contentOffset = point
I got this from the internet but it does not work.
Firstly, bounds.size.height and frame.size.height here is just the size of your TextView in your parent view.
The thing you should notice here is the content inside your textView which is your contentSize. You just need to scroll to the end of your contentSize.height
Code will be like this
// scroll to the end of your content size height
self.textView.setContentOffset(CGPoint(x: 0, y: self.textView.contentSize.height), animated: true)

When I scroll my UIScrollView, animations that are connected to a timer and animate views inside of the scrollview, suddenly stop ticking

I have a UIScrollView containing views, which are connected to timers that call a function every x seconds. Everything works perfectly, until I start scrolling the scroll view, upon which the timers stop ticking, meaning that the animations stop happening. I do not know if this is clear enough, but I will show you some code below to try to clarify.
#objc func lowBeatingAnimation(){
for i in lowWindow{
let List = i as? [Any] ?? []
let View = List[0] as! UIView
let width = List[1] as! NSLayoutConstraint
let height = List[2] as! NSLayoutConstraint
let label = List[3] as! UILabel
self.view.layoutIfNeeded()
UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseIn, animations: {
View.layer.shadowRadius = 50
width.constant += -20
height.constant += -20
label.alpha = 0.65
View.layer.cornerRadius += -10
self.view.layoutIfNeeded()
}, completion: { finished in
UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseOut, animations: {
View.layer.shadowRadius = 10
width.constant += 20
View.layer.cornerRadius += 10
label.alpha = 0.85
height.constant += 20
self.view.layoutIfNeeded()
}, completion: { finished in
})
})
}
}
That is the function I call every second. lowWindow is an array, consisting of arrays with the following format: [UIView, NSLayoutConstraint (belonging to the first element in the list), NSLayoutConstraint (also belonging to the first element in the list), UILabel]
The first element in lowWindow is a UIView, which is a subview of the scroll view, which causes the animation to stop whenever it gets scrolled.
I think the issue can be boiled down to the following question, although I am not entirely sure: Why does an external timer stop working whenever the position of the scrollview gets edited?
I have also tried different things in terms of whether the views that get animated are direct subviews of the scrollview, or if they are subviews of a subview of the scrollview. Nothing works so far. If you have any ideas on how to solve this and would like to share it, that would be highly appreciated. Thanks.
I solved this by adding the timers to Runloop.
RunLoop.main.add(lowTimer, forMode: .common)
RunLoop.main.add(mediumTimer, forMode: .common)
RunLoop.main.add(highTimer, forMode: .common)

Programmatic scrolling Apple TV Flicking cells

I'm creating an UICollectionView that moves automatically, without user interaction, using:
private func startWaterfallAnimation() {
var timer = Timer.init()
timer = Timer.scheduledTimer(withTimeInterval: 0.06, repeats: true) { (_) in
if !self.isPaused{
UIView.animate(withDuration: 0.06, delay: 0, options: [.curveLinear], animations: {
self.setContentOffset(CGPoint(x: self.contentOffset.x, y: self.contentOffset.y - CGFloat(self.speed)), animated: false)
}, completion: nil)
} else {
timer.invalidate()
}
}
}
Unfortunately, this is the behaviour: https://giphy.com/gifs/1xV9RiPlOoSTugIx1s, cells flick when moving.
My question is: How can I programmatically scroll in a smooth way at Apple TV, without the flick? Maybe another approach?
This is not a code problem, I've tried many approaches. It has to do with the TV resolution, pixels are bigger and when trying to scroll something programmatically in a smooth way, if you do it slow it will flick in most TVs.

Swift: "Freeze" bouncing in a scrollView

I am trying to work a little bit with scrollViews. So I have a ScrollView on my Controller with bouncing enabled. So now then I scroll the view bounces at the end of the page like I want to.
But now I want to freeze my bouncing. I try to explain it a little bit more:
I scroll up in my ScrollView. The end of the page begins. So now the bouncing begins and its scrolling a little bit up. Then I undrag the scrollView the view bounces back. But I want the scrollView to stay in this position (because I push the view away and it looks weird when its bouncing while I push it).
Things I tried:
1.Set the frame on the scroll view to the current bouncing position. This just edits the frame but still bounces the scrollView.
v2.view.frame = CGRect(x: CGFloat(0), y: CGFloat(CURRENTBOUNCING), width: width, height: height)
2.Turn bounces off. This just ends the current bounce and after you can't bounce anymore. So if I don't want it to bounce back this doesn't work.
scrollView.bounces = false
3.Set contentOffset manually. Changes nothing for me even if I write it after initializing
scrollView.contentOffset.y -= 100 // Or something like this
4.Change the contentSize. This changes nothing I think because of the constraints
scrollView.contentSize = CGSize(width: self.view.frame.width, height: self.view.frame.height - 200)
5.Turn always bouncing vertically off. Same like 2.
scrollView.alwaysBounceVertical = false
6.Paging. I tried this because now I page manually. But then I miss the bouncing into nothing before paging. With paging you can see the next page while scrolling behind the end. But the next page should be loaded after dragging.
Hope someone can help me :)
EDIT
7.Taking a picture of my current scrollview to display it on my screen over the scrollview. This takes an image with an delay and not at the right moment ( so the bounces is at the half then capturing or already done.
let renderer = UIGraphicsImageRenderer(size: scrollView.bounds.size)
pufferImage.image = renderer.image { ctx in
scrollView.drawHierarchy(in: scrollView.bounds, afterScreenUpdates: true) }
Ran into the same problem. The solve is to record the content offset and change the vertical offset of the scrollview to that value while simultaneously turning scrolling off.
private var dismissTriggerd = false
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "contentOffset" {
if scrollView.contentOffset.y < -70 && dismissTriggerd == false {
scrollViewTop.constant = scrollView.contentOffset.y * -1
scrollView.isScrollEnabled = false
dismissTriggerd = true
dismiss(animated: true)
}
}
}
deinit {
scrollView.removeObserver(self, forKeyPath: "contentOffset")
}
I had a similar use case, the key was to switch the contentOffset into contentInset this negated the effect of the bounce back
maybe not a 100% complete solution, but i leave it here for inspiration
case UIGestureRecognizerStateEnded:
self.interactor.hasStarted = NO;
if (self.interactor.shouldFinish) {
UIEdgeInsets ei = self.scrollView.contentInset;
ei.top -= self.scrollView.contentOffset.y;
self.scrollView.contentInset = ei;
[self.interactor finishInteractiveTransition];
} else {
[self.interactor cancelInteractiveTransition];
}
break;
default:

How to add Instagram like animation that minimizes the title "Instagram" on scroll down in Swift 2?

I am trying to add the Instagram like animation on my app that minimizes the title "Instagram" and moves the display to the entire page.
In my app, i have two UILabels - chapterNameNumberLabel and chapterNameLabels and a UITextView. On scrolling in the UITextView, i want the chapterNameNumberLabel and the chapterNameLabels to minimize and the entire page to be filled with the UITextView contents.
I have tried the below:(used pointers mentioned in the answer here Finding the direction of scrolling in a UIScrollView?
Obtained the below in viewDidLoad():
xLabel = self.chapNameNumberLabel.center.x;
yLabel = self.chapNameNumberLabel.center.y;
widthLabel = self.chapNameNumberLabel.frame.width;
heightLabel = self.chapNameNumberLabel.frame.height;
xNameLabel = self.chapterNameLabel.center.x;
yNameLabel = self.chapterNameLabel.center.y;
widthNameLabel = self.chapterNameLabel.frame.width;
heightNameLabel = self.chapterNameLabel.frame.height;
And called the below method:
func scrollViewDidScroll(scrollView: UIScrollView) {
if(self.lastContentOffset > 0 ){
if (self.lastContentOffset > scrollView.contentOffset.y) {
//print("Up");
UIView.animateWithDuration(0.5, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
self.chapNameNumberLabel.frame = CGRectMake(self.xLabel - 100, self.yLabel - 10, self.widthLabel, self.heightLabel);
self.chapterNameLabel.frame = CGRectMake(self.xNameLabel - 140, self.yNameLabel - 10 , self.widthNameLabel, self.heightNameLabel);
}, completion: nil)
}
else if (self.lastContentOffset < scrollView.contentOffset.y){
print("Down");
UIView.animateWithDuration(0.5, delay: 0.0, options: UIViewAnimationOptions.CurveEaseIn, animations: {
self.chapNameNumberLabel.frame = CGRectMake( 100 , -10, 5, 5);
self.chapterNameLabel.frame = CGRectMake(50, -10, 5, 5);
}, completion: nil);
}
}
// update the new position acquired
self.lastContentOffset = scrollView.contentOffset.y
}
The animation is okay, but the problem that i am facing are:
I am unable to get the 'font size minimizing' effect on the labels. The labels in my app just disappear without reducing the font size. What animation type should be used for achieving this font size minimization on scrolling?
Also, the values that i have set on scrolling down(within the scrollViewDidScroll) are
self.chapNameNumberLabel.frame = CGRectMake( 100 , -10, 5, 5);
self.chapterNameLabel.frame = CGRectMake(50, -10, 5, 5); and on scrolling up are trial and error values. The labels are not properly aligned when i rotate the screen left and right(on simulator). Could some one please tell me how to calculate this so that it works on all screen orientations?
I have used Swift 2 , Auto layout.