Expand and collapse view in iOS app smoothly?
I have a UIView inside a UIViewController . I want to expand this UIView and collapse. This function is the same as in iOS OS, we drag View from Top, but in iOS this is for the whole app, but I want to put this inside a UIViewController .
LIKE THIS
I tried expanding and collapsing, but resizing the frame, but I can't drag it and up again.
I did it.
- (IBAction)expandCollapseView:(UIButton *)sender {
NSLog(@"Hello");
if (!_isExpended) {
NSLog(@"IF ");
_isExpended = YES;
[UIView beginAnimations:@"animationOff" context:NULL];
[UIView setAnimationDuration:1.3f];
[_expandableView setFrame:CGRectMake(0, 0, 768, 40)];
[UIView commitAnimations];
} else {
NSLog(@"ELSE");
_isExpended = NO;
[UIView beginAnimations:@"animationOff" context:NULL];
[UIView setAnimationDuration:1.3f];
[_expandableView setFrame:CGRectMake(0, 0, 768, 489)];
[UIView commitAnimations];
}
}
// But this code is useless in my sense. as I cannot expand or resize the question in AutoLayout so it needs to be removed.
I need it like below ...
thank
+3
source to share
2 answers
I solved my problem with some stack questions and forums.
In my VSViewController class, I did something like below
//
// VSViewController.h
// Veer
//
// Created by Veer Suthar on 27/08/2014.
// Copyright (c) 2014 Veer. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "VSCategoryTableViewCell.h"
#import "VSSourcesTableViewCell.h"
@interface VSViewController : UIViewController <UIGestureRecognizerDelegate>
// Views
@property (nonatomic, strong) IBOutlet UIView *swipeableView;
@property (nonatomic, strong) IBOutlet UIView *dragableView;
@property (nonatomic, strong) IBOutlet UIView *revealableView;
// Frames
@property (nonatomic) CGRect swipeableViewFrame;
@property (nonatomic) CGRect dragableViewFrame;
@property (nonatomic) CGRect revealableViewFrame;
// State
@property (nonatomic, getter=isDragging) BOOL dragging;
@property (nonatomic, getter=isRevealableViewShowing) BOOL revealableViewShowing;
// Gesture recognizers
@property (nonatomic, strong) UIPanGestureRecognizer *drag;
// Drag and swipe logic
- (void)hideRevealableView;
- (void)showRevealableView;
- (void)offsetFrames:(CGFloat)offset;
- (void)handleDrag:(UIPanGestureRecognizer *)gestureRecognizer;
@end
While in .m I liked below
//
// VSViewController.m
// Veer
//
// Created by Veer Suthar on 27/08/2014.
// Copyright (c) 2014 Veer. All rights reserved.
//
#import "VSViewController.h"
#define UITABLEVIEW_CATEGORIES 1
#define UITABLEVIEW_SOURCES 2
@interface VSViewController ()
@property (weak, nonatomic) IBOutlet UITableView *table_categories;
@property (weak, nonatomic) IBOutlet UITableView *table_sources;
@property (nonatomic, retain) NSMutableArray *array_category;
@property (nonatomic, retain) NSMutableArray *array_sources;
@end
@implementation VSViewController
@synthesize swipeableView = _swipeableView;
@synthesize dragableView = _dragableView;
@synthesize revealableView = _revealableView;
@synthesize swipeableViewFrame = _swipeableViewFrame;
@synthesize dragableViewFrame = _dragableViewFrame;
@synthesize revealableViewFrame = _revealableViewFrame;
@synthesize drag = _drag;
@synthesize dragging = _dragging;
@synthesize revealableViewShowing = _revealableShowing;
- (void)viewDidLoad
{
[super viewDidLoad];
//CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
_array_category = [[NSMutableArray alloc] init];
_array_sources= [[NSMutableArray alloc] init];
for (int x = 0; x<6; x++) {
NSString *str = [NSString stringWithFormat:@"Category %d", x];
[_array_category addObject:str];
}
for (int x = 0; x<5; x++) {
NSString *str = [NSString stringWithFormat:@"Source %d", x];
[_array_sources addObject:str];
}
[_table_categories reloadData];
[_table_sources reloadData];
//Area where all the other views, buttons will show, which will hide and show
self.swipeableViewFrame = CGRectMake(0.0f, 0.0f, 786.0f, 382.0f);
//Area we will hold and drag up and down
self.dragableViewFrame = CGRectMake(365.0f, 382.0f, 38.0f, 40.0f);
//Area for logic, handled at backend. white, so user can't see.
self.revealableViewFrame = CGRectMake(0.0f, 424.0f, 768.0f, 1.0f);
// Add our gesture recognizers on dragableViewFrame so user can drag up and down.
self.drag = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleDrag:)];
[self.dragableView addGestureRecognizer:self.drag];
[self.drag setDelegate:self];
[self.drag setCancelsTouchesInView:NO];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
self.swipeableView = nil;
self.dragableView = nil;
self.revealableView = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void)hideRevealableView
{
[self offsetFrames:0.0f];
//Change image if your put image view, for arrow UP
}
- (void)showRevealableView
{
[self offsetFrames:-self.swipeableViewFrame.size.height];
//Change image if your put image view, for arrow UP
}
- (void)offsetFrames:(CGFloat)offset
{
// Grab our views and drag them
self.swipeableView.frame = CGRectOffset(self.swipeableViewFrame, 0.0f, offset);
self.dragableView.frame = CGRectOffset(self.dragableViewFrame, 0.0f, offset);
self.revealableView.frame = CGRectOffset(self.revealableViewFrame, 0.0f, offset);
}
- (void)handleDrag:(UIPanGestureRecognizer *)gestureRecognizer
{
if (self.isDragging && gestureRecognizer.state == UIGestureRecognizerStateEnded) {
// Reset isDragging
self.dragging = NO;
// If it is over, we check the velocity of the drag
// to see if we want to finish dragging it up or down
CGPoint origin = [gestureRecognizer velocityInView:self.view];
CGFloat velocity = origin.y;
CGFloat vertical;
NSTimeInterval duration;
// If the y value is negative, we are moving up and so attach the view
if (velocity < 0) {
// Calculate how many points we have to go before we hit our destination
vertical = self.revealableView.frame.origin.y - self.view.frame.origin.y;
duration = MIN(ABS(vertical / velocity), 1.0f);
[UIView animateWithDuration:duration
animations:^
{
[self showRevealableView];
}
completion:^(BOOL finished)
{
self.revealableViewShowing = YES;
}
];
}
else {
// Otherwise, at a standstill or moving back, we want to retract the view
vertical = self.revealableView.frame.origin.y - self.dragableView.frame.origin.y;
duration = MIN(ABS(vertical / velocity), 1.0f);
[UIView animateWithDuration:duration
animations:^
{
[self hideRevealableView];
}
completion:^(BOOL finished)
{
self.revealableViewShowing = NO;
}
];
}
}
else if (self.isDragging) {
//[self performSegueWithIdentifier:kRevealShadeViewSegueIdentifier sender:nil];
// Keep track of where we are
CGPoint origin = [gestureRecognizer locationInView:self.view];
// As long as we aren't going above the top of the view, have it follow the drag
if (CGRectContainsPoint(self.view.frame, origin)) {
// Only allow dragging to a certain point. Don't let drag further down.
CGPoint translatedPoint = [gestureRecognizer translationInView:self.view];
// Our offset is different depending on if the revealable view is showing or not
CGFloat offset = (self.isRevealableViewShowing) ? self.swipeableViewFrame.size.height : 0.0f;
if (translatedPoint.y < offset) {
// Track the drag
[self offsetFrames:translatedPoint.y - offset];
}
else {
// Stick to the bottom
[self hideRevealableView];
}
}
}
else if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
// Now, we are dragging
self.dragging = YES;
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if (tableView.tag == UITABLEVIEW_CATEGORIES) {
return [_array_category count];
}else if (tableView.tag == UITABLEVIEW_SOURCES){
return [_array_sources count];
}else
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Configure the cell...
NSLog(@"Hello Cell or row");
if (tableView.tag == UITABLEVIEW_CATEGORIES) {
VSCategoryTableViewCell *cell =NULL;
NSString *identifier=@"VSCategoryTableViewCell";
cell = (VSCategoryTableViewCell *)[tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
NSString *str = [_array_category objectAtIndex:indexPath.row];
[cell.button1 setTitle:str forState:UIControlStateNormal];
[cell.button2 setTitle:str forState:UIControlStateNormal];
[cell.button3 setTitle:str forState:UIControlStateNormal];
return cell;
}else if (tableView.tag == UITABLEVIEW_SOURCES){
VSSourcesTableViewCell *cell =NULL;
NSString *identifier=@"VSSourcesTableViewCell";
cell = (VSSourcesTableViewCell *)[tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
NSString *str = [_array_sources objectAtIndex:indexPath.row];
[cell.button1 setTitle:str forState:UIControlStateNormal];
return cell;
}
return 0;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(@"did select");
}
@end
My storyboard looks low below
when i run it looks like this :)
Happy coding !!!!
+1
source to share
Down below:
CGRect basketTopFrame = _loginViewBack.frame; // _loginViewBack is UIView you Need to Animated View.
basketTopFrame.origin.y = 100;
[UIView animateWithDuration:0.25
delay:0.0
options: UIViewAnimationOptionTransitionCurlDown
animations:^{
_loginViewBack.frame = basketTopFrame;
}
completion:^(BOOL finished)
{
}];
Top down:
CGRect basketTopFrame = _loginViewBack.frame;
basketTopFrame.origin.y = 305;
[UIView animateWithDuration:0.25
delay:0.0
options: UIViewAnimationOptionTransitionCurlUp
animations:^{
_loginViewBack.frame = basketTopFrame;
}
completion:^(BOOL finished)
{
//NSLog(@"Done 1233!");
}];
0
source to share