UIImageView Fading based on ScrollView Position - ios

I have a UIPageControl that flips through different pages. I'd like to have a UIImageView begin to fade as the user scrolls from page 1 to page 2. I'm struggling trying to figure out the proper way to add a layer based on the position. Any help would be most appreciated...
[UIView beginAnimations:#"fade out" context:nil];
[UIView setAnimationDuration:1.0]; // some how based on position??
imageView.alpha = 1.0; // here to?
[UIView commitAnimations];
Edit:
Set the delegate:
self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageController.dataSource = self;

You need the delegate to override the following method:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
Then you should check against the scrollView.contentOffset.x value to determine how much the scroll view has scrolled horizontally, and use it to determine your imageView's alpha as follows:
CGFloat newAlpha = scrollView.contentOffset.x / scrollView.frame.size.width; // This will need to be adapted depending on the content size of your scroll view -- do not just copy and paste this expecting it to work :)
imageView.alpha = newAlpha;

Related

Make half of UIView go out of screen

I created a floating view for my application which always displays on screen.
Now I want to make a half of it go outside my screen when it is interactive for 3-4 seconds. I think I should use a NSTimer to hide out this view, but it is not the problem.
The problem is how should I set origin.x of this view to go outside of the screen? I've tried to set the frame in my initWithSuperView like this:
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenX = screenRect.origin.x;
[self setFrame:CGRectMake(-screenX - size.width, 0, size.width, size.height)];
However, it doesn't work. How should I do it to get my desired result? See image below for more information:
you can use uiview animation similar to this:
dispatch_async(mainQueue, ^{
__weak __typeof(self) weakSelf = self;
[UIView animateWithDuration:3.f animations:^{
// change uiview frame here
weakSelf.frame = hiddenFrame;
} completion:^(BOOL finished) {
// setup completion
[weakSelf.view layoutIfNeeded];
}];
});
also you can setup NSLayoutConstraint to the x constraint of uiview and update it with negative value when you need.

Transforming a subview of UIScrollView

I am trying to reproduce an effect like the iOS 7 app switcher where I can scroll between smaller, transformed views. My current obstacle is getting the contentOffset
In order to do this, I have added a scrollView to my view, and sized it to the bounds of the view. I then create a container view that holds on to all the 'cards' -- it is this container view to which I apply the transform.
Anyway, the issue I am having is with adjusting where a particular card appears after it has the transform applied -- right now, I am unable to adjust the contentOffset during the transform in a manner that is smooth.
Anyway, code would help! Here it is:
NSInteger idx = selectedCardIndex;
if (TransformApplied)
{
[UIView animateWithDuration:0.5 animations:^{
[self.container setTransform:CGAffineTransformIdentity];
[self.container setFrame:CGRectOffset(self.container.frame, (1-ScaleFactor)/2 * NumCards * ScreenWidth, 0)];
[self.scrollView setContentSize:self.container.frame.size];
[self.scrollView setContentOffset:CGPointMake(ScreenWidth * idx, 0) animated:NO];
[self.scrollView setPagingEnabled:YES];
} completion:^(BOOL finished) {
TransformApplied = NO;
}];
}
else
{
[UIView animateWithDuration:0.5 animations:^{
[self.container setTransform:CGAffineTransformMakeScale(ScaleFactor, ScaleFactor)];
[self.container setFrame:CGRectOffset(self.container.frame, (-1)*((1-ScaleFactor)/2) * NumCards * ScreenWidth, 0)];
[self.scrollView setContentSize:CGSizeMake(ScreenWidth * ScaleFactor * NumCards, ScreenHeight * ScaleFactor)];
[self.scrollView setContentOffset:CGPointMake(ScaleFactor * ScreenWidth * idx, 0) animated:NO];
[self.scrollView setPagingEnabled:NO];
} completion:^(BOOL finished) {
TransformApplied = YES;
}];
}
More
I am noticing that everything is smooth when applying the identity transform, but not when applying the smaller transform, I get a weird 'jump' in the frame before the animation.
If i comment out the content offset adjustment in the scale transform (the bottom block) then everything runs smoothly, but the contentOffset is wrong after the scale transform.
Lastly, calling setContentOffset:animated: results in a wonky animation so that is a no-go.
Any help greatly appreciated!!!!
UPDATE
I've looked in to anchor point/ position properties on CALayer, and I've got the animation effects working perfectly with this:
NSInteger idx = selectedCardIndex;
if (TransformApplied)
{
[UIView dd_AnimateWithDuration:0.5 animations:^{
[self.container setTransform:CGAffineTransformIdentity];
[self.scrollView setContentOffset:CGPointMake(ScreenWidth * idx, 0) animated:NO];
[self.scrollView setPagingEnabled:YES];
} completion:^(BOOL finished) {
TransformApplied = NO;
}];
}
else
{
CGPoint anchor = CGPointMake((idx * ScreenWidth + ScreenWidth/2)/CGRectGetWidth(self.container.frame), 0.5f);
[self.container.layer setAnchorPoint:anchor];
CGPoint position = CGPointMake((anchor.x) * self.container.frame.size.width, self.container.layer.position.y);
[self.container.layer setPosition:position];
[UIView dd_AnimateWithDuration:0.5 animations:^{
[self.container setTransform:CGAffineTransformMakeScale(ScaleFactor, ScaleFactor)];
[self.scrollView setPagingEnabled:NO];
} completion:^(BOOL finished) {
TransformApplied = YES;
}];
}
However, now i've got to figure out a way to get rid of all the extra space in the scrollview without allowing the position of the container to change....
I have had a similar issue a long time ago about the position of a view. After a long research, I ended up with the UIView documentation. It says about transform and frame properties of a UIView with a warning:
Warning:
If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.
Changing the frame rectangle automatically redisplays the receiver without invoking the drawRect: method. If you want the drawRect: method invoked when the frame rectangle changes, set the contentMode property to UIViewContentModeRedraw.
Changes to this property can be animated. However, if the transform property contains a non-identity transform, the value of the frame property is undefined and should not be modified. In that case, you can reposition the view using the center property and adjust the size using the bounds property instead.
So, the basic idea is that, you shouldn't rely on or change frame when your view's transform contains a non-identity transform.
And the more important idea, always give a chance to the official documentation before looking elsewhere.
I hope this helps.

UIView +animateWithDuration: isn't animating a recently allocated view correctly

I'm attempting to allocate a webview with a specific frame, and then animate both its y position and height. When I do so, the webview instantly snaps to its "final" position, not animating the y, but it is animating the height.
Also, just so there's no confusion, I use UIView+Positioning (https://github.com/freak4pc/UIView-Positioning) to set my x,y,height, and width, instead of fiddling with the CGRects :)
Here is a screen capture of the animation, the issue is that the webview is instantly created at y=260/height=0px, where it should start at y=340/height=0px and transition to y=260 and height=maxHeight. y=340px is where the top and bottom split, and is where the "close" animation on the webview focuses to.
The code
for (PageViewController * page in pages) {
[page preFullscreen];
}
[UIView animateWithDuration:0.5f animations: ^() {
for (PageViewController * page in pages) {
[page fullScreen];
}
}];
...
- (void)preFullscreen {
_webView = [[UIWebView alloc] initWithFrame:CGRectMake(0.0f, 340.0f, 320.0f, 0.0f)];
_webView.delegate = self;
_webView.scrollView.bounces = NO;
_webView.scrollView.scrollEnabled = NO;
_webView.scalesPageToFit = YES;
_webView.backgroundColor = [UIColor whiteColor];
[_scrollView addSubview:_webView];
[_webView loadHTMLString:[entry storyHTML] baseURL:nil];
}
- (void)fullScreen {
_darkOverlayview.alpha = 0.0f;
_webView.y=260.0f;
_webView.height = [[UIScreen mainScreen] bounds].size.height - 260.0f;
_scrollView.delegate = hsVC;
_textareaView.hidden = YES;
_frontImage.height = 260.0f;
self.view.height = [[UIScreen mainScreen] bounds].size.height;
_scrollView.height = [[UIScreen mainScreen] bounds].size.height;
}
I think the problem is precisely that you are using the UIView+Positioning additions? Internally it ends up setting the frame multiple times within the animation block, so the start position is lost. Use the regular setFrame: to set the entire frame once per view in the animation block.
As for animating the UIWebView, I also recommend setting it to full height in preFullscreen (so that it's below the bottom edge of the screen) and only animating the y coordinate. In my experience resizing webviews during animation can be problematic since the web content is also resized.

iOS animate button while scrolling list

I have view with UITableView. Above this list I have UIButton. I need to implement an animation what will move button vertically according to scrolling on list and return to base location when scrolling is finished. I show scrolling down in pictures bellow:
This is not scrolled list:
This is list scrolled to half:
This is list fully scrolled:
For now I detect start and stop scrolling list events and do animation like that:
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
CGRect newFrame = button.frame;
newFrame.origin.y = screenHeight - (newFrame.size.height/2.0);
[UIView animateWithDuration:2
animations:^{
button.frame = newFrame;
}];
}
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
CGRect newFrame = storedButtonFrame;
[UIView animateWithDuration:2
animations:^{
button.frame = newFrame;
}];
}
I have few issues with this First is that when I scrolling down my animation is animating to then end and I want to animate based on scrolled list eg. when I scroll down list for 10px I would like to move button only for 10px not to the end of list. Second is that I get stop scroll event when begin scroll animation is still running the start animation is blink to the end and the end animation is start animating what is definitly what I dont want. I dont have to much experiance in iOS and I really dont have any ide how can I do this. Have any idea how can I do something like this?
Instead of using scrollViewWillBeginDragging: you could use scrollViewDidScroll: like so:
/// Animate the button position as the scroll view scrolls
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat percentage = scrollView.contentOffset.y / scrollView.contentSize.height;
CGRect frame = _button.frame;
frame.origin.y = scrollView.contentOffset.y + percentage * self.tableView.frame.size.height;
_button.frame = frame;
}
/// Animate the button back to the top-right corner
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
CGRect frame = _button.frame;
frame.origin.y = scrollView.contentOffset.y;
[UIView animateWithDuration:0.4f
animations:^{
_button.frame = frame;
}];
}
This makes the button follow the scroll indicator as you scroll the list. scrollViewDidScroll: fires very often so the movement is smooth.
When the list stops, it goes back to its default position at the top-right, which you get from contentOffset.y.

Animate size of View keeping its bottom left point fixed

I have a UIView at the bottom left of its superview, i.e.its frame is like
[myView setFrame:CGRectMake(0,superView.bounds.size.height-myViewHeight,myViewWidth,myViewHeight)];
I want to animate its size such that its bottom left point remains fixed at its position. I am not sure how to play with anchor point property of layers.
Currently I am increasing its size using the following lines of code.
[UIView animateWithDuration:0.2 animations:^{
[bottomLbl setFrame:CGRectMake(0, bottomView.bounds.size.height-250, 300, 250)];
This works fine but when I try to bring back to its original size, its bottom point gets lifted at the start of animation and settles down at the end of animation.
First define the point for the bottom left corner...
CGPoint bottomLeft = CGPointMake(0, 480); // this can be anything.
Then you need to define the sizes (big and small).
CGSize bigSize = CGSizeMake(280, 280);
CGSize smallSize = CGSizeMake(50, 50); // again, these can be anything.
Then animate them...
// create the rect for the frame
CGRect bigFrame = CGRectMake(bottomLeft.x, bottomLeft.y - bigSize.height, bigSize.width, bigSize.height);
CGRect smallFrame = CGRectMake(bottomLeft.x, bottomLeft.y - smallSize.height, smallSize.width, smallSize.height);
[UIView animateWithDuration:0.2
animations:^{
// set the rect onto the view
bottomLbl.frame = bigFrame;
// or
bottomLbl.frame = smallFrame;
}];
As long as you set the frame and the calculated end frames are correct and it's all done in one animation then the bottom left corner won't move.
If this doesn't help can you please post a video of what is happening (and all your animation code).
EDIT
[UIView animateWithDuration:0.2
delay:0.0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
// set the rect onto the view
bottomLbl.frame = bigFrame;
// or
bottomLbl.frame = smallFrame;
}
completion:nil];

Resources