When I swipe, let UIImageView and UIScrollView go below in same speed - ios

When I swipe right direction in iPhone(iOS 7.0), I want let UIImageView and UIScrollView go below in same speed. I sccuessfully made UIScrollView as subClass. (I instanced UIScrollView as "sv" in the code)
Now, UIImageView and UIScrollView go below differently.
May I ask what should I do to ?
if ( distanceHorizontal > distanceVertical ) {
if ( _tEnded.x > _tBegan.x ) {
// Swipe Right
NSLog(#"Swipe Right");
swipeSpeed = distanceHorizontal / dt;
speedLabel.text = [NSString stringWithFormat:#"%d", swipeSpeed];
NSInteger swipeSpeedChanged = swipeSpeed / 200;
NSInteger x = 200 + swipeSpeedChanged;
NSLog(#"swipeSpeedChanged:%d", swipeSpeedChanged);
headSpinImageView.center = CGPointMake(160,200);
CGPoint offset;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:2.0];
headSpinImageView.center = CGPointMake(160,x);
//Scroll UIScrollView
offset.x = 0.0f;
offset.y = swipeSpeedChanged;
[sv setContentOffset:offset animated:YES];
headSpinRect = CGRectMake(160, 200, x, 60);
[UIView commitAnimations];
}

Related

Slide up UIView following finger similar to Control Center in iOS

I have a UITableView that is at the bottom of my main UIViewController, it currently only shows the top two rows. To show the rest I don't want it to scroll, I want the user to be able to "pull" the view up to reveal the additional 4 rows (can then swipe down on it to "push" it back into its original place), and I want the "pull" to be similar to how control center works in iOS. The spring that it has is really great.
Looks like I can add a UIPanGestureRecognizer to do the pull:
UIPanGestureRecognizer * pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(pan:)];
pan.maximumNumberOfTouches = pan.minimumNumberOfTouches = 1;
[self addGestureRecognizer:pan];
- (void)pan:(UIPanGestureRecognizer *)aPan; {
CGPoint currentPoint = [aPan locationInView:self];
[UIView animateWithDuration:0.01f
animations:^{
CGRect oldFrame = _viewToChange.frame;
_viewToChange.frame = CGRectMake(oldFrame.origin.x, currentPoint.y, oldFrame.size.width, ([UIScreen mainScreen].bounds.size.height - currentPoint.y));
}];
}
Ref this question.
Doing this does sort of work, but my UITableView flashes as you pull it up and it eventually disappears.
There is also no spring, and no way to set a "max" so that you can't pull up the view past a certain point.
Does anyone have ideas on how this can be achieved?
this is how i write the pan:. t is tableView(initially user interaction is disabled). 40 in code is for more realistic look in pan. 200 is max value i used and 60 is min value. i directly add t to tableview with height 60 and increased the height with animation.
- (void)pan:(UIPanGestureRecognizer *)aPan; {
CGPoint currentPoint = [aPan locationInView:self.view];
CGRect fr = t.frame;
if ((currentPoint.y - fr.origin.y) < 40 && (fr.size.height <= 200) )
{
float nh = (currentPoint.y >= self.view.frame.size.height - 200) ? self.view.frame.size.height-currentPoint.y : 200;
if (nh < 60) {
nh = 60;
}
[UIView animateWithDuration:0.01f animations:^{
[t setFrame:CGRectMake(0, self.view.frame.size.height-nh, t.frame.size.width, nh)];
}];
if (nh == 200) {
[t setUserInteractionEnabled:YES];
}
else
{
[t setUserInteractionEnabled:NO];
}
}
}
or without pan; with using tableview's scrollview delegate methods, when tableview begin dragging in closed state, opening the large mode and when tableview scroll to top sliding down
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
NSLog(#"scroll");
if (scrollView.contentOffset.y == 0) {
[UIView animateWithDuration:0.2f animations:^{
[scrollView setFrame:CGRectMake(0, self.view.frame.size.height-200, t.frame.size.width, 200)];
}];
}
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView.contentOffset.y == 0) {
[UIView animateWithDuration:0.2f animations:^{
[scrollView setFrame:CGRectMake(0, self.view.frame.size.height-60, t.frame.size.width, 60)];
}];
}
}

Show/Hide Top View and Bottom View while UItableView Scrolling

I did my Top View and Bottom View (UIViews) hide while the UITableView is scrolling. Now, I need to check if the user begin drag the UITableview to up again and back the uiviews for the initial position. I have the following code to do the first step: hidden/show while scrolling uitableview
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
if(!self.isScrollingFast) {
CGRect screenBound = [[UIScreen mainScreen] bounds];
CGSize screenSize = screenBound.size;
CGFloat screenWidth = screenSize.width;
CGFloat screenHeight = screenSize.height;
NSInteger yOffset = scrollView.contentOffset.y;
if (yOffset > 0) {
self.tabBar.frame = CGRectMake(self.tabBar.frame.origin.x, self.originalFrame.origin.y + yOffset, self.tabBar.frame.size.width, self.tabBar.frame.size.height);
self.viewTopo.frame = CGRectMake(self.viewTopo.frame.origin.x, self.originalFrameTopo.origin.y - yOffset, self.viewTopo.frame.size.width, self.viewTopo.frame.size.height);
if(self.originalFrameHidingView.origin.y - yOffset >= 0) {
self.hidingView.frame = CGRectMake(self.hidingView.frame.origin.x, self.originalFrameHidingView.origin.y - yOffset, self.hidingView.frame.size.width, self.hidingView.frame.size.height);
}
else {
self.hidingView.frame = CGRectMake(self.hidingView.frame.origin.x, -10, self.hidingView.frame.size.width, self.hidingView.frame.size.height);
}
[self.tbPertos setFrame:CGRectMake(self.tbPertos.frame.origin.x, self.hidingView.frame.origin.y + self.hidingView.frame.size.height, self.tbPertos.frame.size.width, self.tbPertos.frame.size.height)];
if(self.tbPertos.frame.size.height + self.tbPertos.frame.origin.y + yOffset <= screenHeight)
self.tbPertos.frame = CGRectMake(self.tbPertos.frame.origin.x, self.tbPertos.frame.origin.y, self.tbPertos.frame.size.width, self.tbPertos.frame.size
.height+yOffset);
else {
self.tbPertos.frame = CGRectMake(self.tbPertos.frame.origin.x, self.tbPertos.frame.origin.y, self.tbPertos.frame.size.width, screenHeight - self.tbPertos.frame.origin.y);
}
}
if (yOffset < 1) {
self.tabBar.frame = self.originalFrame;
self.viewTopo.frame = self.originalFrameTopo;
self.hidingView.frame = self.originalFrameHidingView;
self.tbPertos.frame = CGRectMake(self.tbPertos.frame.origin.x, self.hidingView.frame.origin.y + self.hidingView.frame.size.height, self.tbPertos.frame.size.width, screenHeight - self.tbPertos.frame.origin.y);
}
}
}
And there's the code which I'm trying to do the Top and Bottom View reappear when the user begin scroll up. Independently wheres the scroll offset.
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
CGPoint currentOffset = scrollView.contentOffset;
NSTimeInterval currentTime = [NSDate timeIntervalSinceReferenceDate];
NSTimeInterval timeDiff = currentTime - self.lastOffsetCapture;
CGFloat distance = currentOffset.y - self.lastOffset.y;
//The multiply by 10, / 1000 isn't really necessary.......
if (distance < 0) {
if(!self.isScrollingFast) {
NSLog(#"voltar posicao normal");
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelay:1.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
self.tabBar.frame = self.originalFrame;
self.viewTopo.frame = self.originalFrameTopo;
self.hidingView.frame = self.originalFrameHidingView;
self.tbPertos.frame = self.originalFrameTbPertos;
self.isScrollingFast = YES;
[UIView commitAnimations];
}
} else {
self.isScrollingFast = NO;
}
self.lastOffset = currentOffset;
self.lastOffsetCapture = currentTime;
}
Here i implemented code for UIView Hide / Show when tableview scrolling. When tableview scrolling down then UIView is hidden and when scrolling up then UIView show. I hope it's working for you...!
Step 1:- Make one property in .h file
#property (nonatomic) CGFloat previousContentOffset;
Step 2:- Write down this code in scrollViewDidScroll Method.
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat currentContentOffset = scrollView.contentOffset.y;
if (currentContentOffset > self.previousContentOffset) {
// scrolling towards the bottom
[self.subButtonView setHidden:YES];
} else if (currentContentOffset < self.previousContentOffset) {
// scrolling towards the top
[self.subButtonView setHidden:NO];
}
self.previousContentOffset = currentContentOffset;
}

Permanently move a frame of custom UIView on screen

I'm having a little problem about animations on iOS with Objective-c.
I'm trying to create a card game, and as the game start, the deck distributes the cards on the table, with an animation. The problem is that at the beginning the cards are all in row in the bottom side of the screen, then with the animation they distribute all over the table. But when I tap on anyone of them, they return in their initial position, although the game keeps on working because they flip and unflip over, as well as the score works properly. I'm attaching some snippets of the code and of the view.
Here are links to screenshots:
1)cards as the game starts: prntscr.com/68r8yj
2)cards at the end of initial animation: prntscr.com/68r92u
3)cards as I tap on any of them: prntscr.com/68r2hr
Here's my code snippet
-(void)viewDidAppear:(BOOL)animated {
CGPoint startPoint = {21, 34};
for(int i = 0; i < [self.cardsView count]; i++) {
FrenchPlayingCardView *view = [self.cardsView objectAtIndex:i];
int width = view.bounds.size.width;
int height = view.bounds.size.height;
CGRect newFrame = CGRectMake(startPoint.x, startPoint.y, width, height);
/*[UIView animateWithDuration:1.0
delay:1.0
options:UIViewAnimationOptionTransitionNone
animations:^(){
view.frame = newFrame;;
}
completion:nil];*/
[UIView beginAnimations:#"move" context:nil];
[UIView setAnimationDuration:3.0];
view.frame = newFrame;
[UIView commitAnimations];
NSLog(#"index:%d %f %f", i, view.frame.origin.x, view.frame.origin.y);
startPoint.x += 76;
if(i % 4 == 3) {
startPoint.y += 100;
startPoint.x = 21;
}
}
[super viewDidAppear:animated];
}
call [super viewDidAppear] before your animation and close autolayout. I think autolayout can cause this

Second animation

I have several buttons located at different sites in the view (storyboard), and I want that when I click on each of them to go to a given point,
To do this, I keep their location and initial size by:
CGPoint originalCenter1;
CGRect originalsize1;
CGPoint originalCenter2;
CGRect originalsize2;
in viewDidLoad
originalCenter1 = self.boton1.center;
originalsize1 = self.boton1.frame;
originalCenter2 = self.boton2.center;
originalsize2 = self.boton2.frame;
and the IBAction associated with each button, the animation ...
-(IBAction)move:(id)sender{
UIButton * pressedbutton = (UIButton*)sender;
[UIView animateWithDuration:3.0 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
CGAffineTransform scale = CGAffineTransformMakeScale(3.0, 3.0);
pressedbutton.transform = scale;
switch(pressedbutton.tag)
{
case 0:
pressedbutton.center = CGPointMake(784, 340);
break;
case 1:
pressedbutton.center = CGPointMake(784, 340);
break;
When already all have moved, I have a button Refresh that puts me to the initial position.
-(IBAction)refresh:(id)sender{
self.boton1.frame = originalsize1;
self.boton1.center = originalCenter1;
self.boton1.alpha=1;
self.boton2.frame = originalsize2;
self.boton2.center = originalCenter2;
self.boton2.alpha=1;
The problem is that the next time that pulse buttons, move to the position shown in the animation but the "scale" effect, doesn't work !!
Any help ??
Thanks.
I think you should use block try this...
- (IBAction)tap:(UITapGestureRecognizer *)gesture
{
CGPoint tapLocation = [gesture locationInView:self.view1];
for (UIView *view in self.view1.subviews) {
if (CGRectContainsPoint(view.frame, tapLocation)) {
[UIView animateWithDuration:5.0 animations:^{
[self setRandomLocationForView:view];
}];
}
}
}
- (void)setRandomLocationForView:(UIView *)view
{
[view sizeToFit];
CGRect sinkBounds = CGRectInset(self.view1.bounds, view.frame.size.width/2, view.frame.size.height/2);
CGFloat x = your location.x;
CGFloat y = yout location.y;
view.center = CGPointMake(x, y);
}

Scrolling a table view with text fields when "Next" return button in keyboard

I have a grouped table view with custom cells, and these cells have a UITextField. I've set the returnKeyType of the text fields to be UIReturnKeyNext (except for the last row), and I've implemented their textFieldShouldReturn: method this way:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
id firstResponderCell = textField.superview.superview ;
NSInteger firstResponderRow = [self.tableView indexPathForCell:firstResponderCell].row ;
NSIndexPath* nextCellIndexPath = [NSIndexPath indexPathForRow:firstResponderRow+1 inSection:0] ;
CustomCell* nextCell = (CustomCell*)[self.tableView cellForRowAtIndexPath:nextCellIndexPath] ;
if (nextCell) {
[nextCell.cellTextField becomeFirstResponder] ;
}
else
[textField resignFirstResponder] ;
return YES ;
}
But I'm not able to scroll the table view content in order to make the current active text field visible above the keyboard. I successfully managed this when I did not implement the "Next" button functionality in keyboard and keyboard was just hidden when "Enter" button was tapped, and then the keyboard was again shown when another text field was tapped, since I'm listening for UIKeyboardDidShowNotification and UIKeyboardDidHideNotification. But now that I want a "Next" button in keyboard and keyboard is not being hidden when tapping the button, I don´t know how to scroll to the active text field properly.
Thanks in advance
This is the most easiest and efficient way to achieve this:
Add the following constants:
static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216;
static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 162;
Add this to your view controller:
CGFloat animatedDistance;
And add these methods to your code:
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
CGRect textFieldRect =
[self.view.window convertRect:textField.bounds fromView:textField];
CGRect viewRect =
[self.view.window convertRect:self.view.bounds fromView:self.view];
CGFloat midline = textFieldRect.origin.y + 0.5 * textFieldRect.size.height;
CGFloat numerator =
midline - viewRect.origin.y
- MINIMUM_SCROLL_FRACTION * viewRect.size.height;
CGFloat denominator =
(MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION)
* viewRect.size.height;
CGFloat heightFraction = numerator / denominator;
if (heightFraction < 0.0)
{
heightFraction = 0.0;
}
else if (heightFraction > 1.0)
{
heightFraction = 1.0;
}
UIInterfaceOrientation orientation =
[[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationPortrait ||
orientation == UIInterfaceOrientationPortraitUpsideDown)
{
animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
}
else
{
animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction);
}
CGRect viewFrame = self.view.frame;
viewFrame.origin.y -= animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
CGRect viewFrame = self.view.frame;
viewFrame.origin.y += animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
}
P.S: This one is from here.
This isn't a safe way of getting the cell:
id firstResponderCell = textField.superview.superview ;
I.e. It might work now but it might not work in the (near) future.
Once you know the index path you should check that it actually exists. Then you can use scrollToRowAtIndexPath:atScrollPosition:animated: to scroll the row (and make it the top row). Alternatively you can get the frame of the row and then set the contentOffset of the table view.

Resources