I am creating an app where I am trying to have a pagescrollviewcontroller swipe through screens and have the top "nav" bar titles scroll real time with the titles
i have the title bar view as a custom view and I am able to access the scroll delegate methods for both the custom scroll view and the pageview controller. However. I don't see how to access the real time scroll pos? I know it is possible because twitter does it (really can't shouldn't be in anyone's vocabulary) but I am not sure how to achieve this.
a picture
the home title swipes at the same scroll pos as the pagecontrollers.
current code:
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
if(scrollView.tag == 100) {
CGPoint point = CGPointMake(mainScrollView.contentOffset.x * 1,0);
[titleSwipe setContentOffset:point animated:YES];
}
else {
mainScrollView.contentOffset = CGPointMake(0,1);
[mainScrollView setContentOffset:titleSwipe.contentOffset animated:YES];
}
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate: (BOOL)decelerate {
CGPoint point = CGPointMake(mainScrollView.contentOffset.x * 2,0);
[titleSwipe setContentOffset:point animated:YES];
}
You'll find the real time position in scrollViewDidScroll:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// X scroll
//
CGFloat percentage = scrollView.contentOffset.x / scrollView.contentSize.width;
NSLog(#"Scrolled percentage: %f", percentage);
}
Hope that helps!
Related
I have two UIScrollViews. Both the scroll views contain an image. Now, I want to zoom second scroll view programmatically if I zoom in the first scroll view manually. I am using -(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView method to manually zoom the first scroll view. The second scroll view should be zoomed to the same point and scale. How can I achieve this?
By using the tag or object of those two scrollviews you can identify the which scroll view you need zoom in viewForZoomingInScrollView method.
e.g
//need to set the tag for scrollviews
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
if(scrollView.tag == 1)
{
return firstImageView;
}
return secondImageView;
}
OR
//need to create the object of used scrollviews
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
if(scrollView == objScrollViewFirst)
{
return firstImageView;
}
return secondImageView;
}
How about something like this:
CGRect zoomRect;
zoomRect.size.height = manualScrollView.frame.size.height / manualScrollView.zoomScale;
zoomRect.size.width = manualScrollView.frame.size.width / manualScrollView.zoomScale;
zoomRect.origin.x = manualScrollView.center.x - (zoomRect.size.width / 2.0);
zoomRect.origin.y = manualScrollView.center.y - (zoomRect.size.height / 2.0);
[autoScrollView zoomToRect:zoomRect animated:YES];
[autoScrollView setZoomScale:manualScrollView.zoomScale animated:YES];
Try something like this in the UIScrollViewDelegate method:
override func scrollViewDidScroll(scrollView: UIScrollView){
otherScrollView.contentOffset = scrollView.contentOffset
otherScrollView.zoomScale = scrollView.zoomScale
}
I'm trying to move a view while the scrollview is being scrolled with the same intensity.
I'm trying:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// here I detect when user scroll
}
How could I get the intensity that the scrollview is being scrolled?
Try to use these methods:
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
//scrolling on
NSLog(#"scrollViewWillBeginDragging");
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if(!decelerate) {
//not scrolling
}
NSLog(#"scrollViewDidEndDragging");
}
You can do that by reading the contentOffset property on the scrollView
// You can save this as a property or an iVar
CGPoint lastContentOffset;
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
lastContentOffset = scrollView.contentOffset;
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGPoint difference = CGPointSubstract(scrollView.contentOffset, lastContentOffset);
lastContentOffset = scrollView.contentOffset;
// Use difference to know by how much the scroll view scrolled
// IMPORTANT: CGPointSubstract is not a standard function, you can implement it yourself.
}
I don't want to give you the full code but i'll help with how to achieve it.
1) You need to use the time.
2) When the time difference is greater than an amount of time passed to measure (0.05s?)
3) Check what the old content offset is compared to the new one
4) The difference is your velocity
5) reset your current timer
6) set current offsets to last offset
Hope this helps
Ben
distance calcs
CGFloat distanceY = currentOffset.y - lastOffset.y;
CGFloat distanceX = currentOffset.X - lastOffset.X;
I am using a UITableView to achieve a scale/unblur effect on my user's profile picture (like in the Spotify App) when I pull down the UITableView to a negative contentOffset.y. This all works fine...
Now, when a user pulls down to a contentOffset.y smaller or equal to a certain value -let's call it maintainOffsetY = 70.0- and he "lets go" of the view, I would like to maintain this contentOffset until the user "pushes" the view up again, instead of the view to automatically bounce back to contentOffset = (0,0) again.
In order to achieve this, I must know when the touches began and ended, which I can do with the following delegate methods:
- (void) scrollViewWillBeginDragging:(UIScrollView *)scrollView {
// is like touches begin
if ([scrollView isEqual:_tableView]) {
NSLog(#"touches began");
_touchesEnded = NO;
}
}
- (void) scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
// is like touches ended
NSLog(#"touches ended");
if ([scrollView isEqual:_tableView]) {
_touchesEnded = YES;
}
}
Then in
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
I check if the contentOffset.y is smaller than or equal to maintainOffsetY and if the user has already "let go" of the table, so it is about to bounce (or already bouncing) back to contentOffset = (0,0).
It does not seem to be possible to let it bounce back only to the maintainOffsetY. Does anybody know a workaround or have an idea on how to solve this?
Any help is much appreciated!
To set a negative offset to a scroll view you can use this.
You need to save the initial content inset of scroll view. It can be not 0 already, if you have translucent nav bar for example.
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
contentInsetTopInitial = self.tableView.contentInset.top;
}
Then write this.
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
CGPoint contentOffset = scrollView.contentOffset; // need to save contentOffset before changing contentInset
CGFloat contentOffsetY = contentOffset.y + contentInsetTopInitial; // calculate pure offset, without inset
if (contentOffsetY < -maintainOffsetY) {
scrollView.contentInset = UIEdgeInsetsMake(contentInsetTopInitial + maintainOffsetY, 0, maintainOffsetY, 0);
[scrollView setContentOffset:contentOffset animated:NO];
}
}
Hope this will help.
I'm developing an iOS 7 app with latest SDK.
I have an UIScrollView with three ImageViews inside it. The UIScrollView has its contentSize set to {960, 568} (each ImageView has a {320, 958}` size).
I can drag over the three images perfectly, but I want to hide the UIScrollView when user drags from right to left on the last image.
To that, I have used UIScrollViewDelegate:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView.contentOffset.x > 640)
scrollView.hidden = YES;
}
But this code hide it immediately and I want to show the following effect:
Continue dragging the image from right to left while the image fades out.
How can I do that?
If you want to have the fade effect proportional to the content offset, use this method:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView.contentOffset.x > 640)
{
scrollView.alpha = 1 / (scrollView.contentOffset.x - 639);
}
// then remove / hide the view completely at a particular offset
// ....
}
and you can change the division to make the animation more/less smooth. This is smoother:
scrollView.alpha = 2 / (scrollView.contentOffset.x - 638);
[UIView animateWithDuration:0.3 animations:^{
self.scrollView.alpha = 0.0;
} completion:^(BOOL finished) {
// remove the scrollView from your view
if(finished) {
[self.scrollView removeFromSuperview];
}
}];
Hopefully this will help
I have a custom control that looks like this:
It allows you to pick multiplier from 1 to 10. Inside it is scroll view with multiple UILabels in it. Each label has tag and using the tag I calculate needed positions for label.
The user may either swipe to move this or tap on the number to make it move automatically.
But I have faced the problem - if the view is scrolling and I tap on the number while it is scrolling, it will stop not on the number I tapped on, but on some other number.
When the scroll view is not scrolling taps work fine. Here is relevant code:
This method is needed to stop on the number when it ends scrolling:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
NSInteger targetIndex = targetContentOffset->x / (self.frame.size.width / 4.0) ;
*targetContentOffset = CGPointMake((targetIndex) * (self.frame.size.width / 4.0), targetContentOffset->y);
if (targetIndex > [self.dataSource numberOfItemsInPicker:self] - 1) {
targetIndex = [self.dataSource numberOfItemsInPicker:self] - 1;
}
if (self.gameName) {
for (int i=0; i<self.labels.count; i++) {
UILabel *label = self.labels[i];
if (i == targetIndex) {
label.textColor = [GeneralHelper colorForGame:self.gameName];
}
else {
if ([self.delegate respondsToSelector:#selector(colorForTextForSmallNumberPicker:)]) {
label.textColor = [self.delegate colorForTextForSmallNumberPicker:self];
}
}
}
}
if (self.delegate) {
[self.delegate smallNumberPickerView:self didPickNumberAtIndex:targetIndex];
}
}
This is the code that determines position of labels in scroll view:
- (CGPoint)offsetForIndex:(NSUInteger)index
{
return CGPointMake(roundf((self.frame.size.width / 4.) * index), 0.);
}
And I think this is the offending code that handles tap gesture recognizer:
- (void)handleTapGesture:(UIGestureRecognizer *)recognizer
{
if (recognizer.state != UIGestureRecognizerStateEnded) {
return;
}
[self.scrollView setContentOffset:[self offsetForIndex:recognizer.view.tag - LABELS_START_TAG] animated:YES];
}
My ideas what happens is that during scrolling frame is wrong, or positions are wrong, but I have no idea how to handle this. I noticed that when I tap I NSLog target offset and it is wrong, and if it is not scrolling - I will get right offset.
What can I do about this?
There was an error in calculations. This line:
return CGPointMake(roundf((self.frame.size.width / 4.) * index), 0.);
It divided by 4 but the labels were actually smaller then 1/4 of the picker, so I got wrong results.