Animating the height change of a UICollectionView - ios

I have a UICollectionView which is a subview of a UIScrollView (this is required because of stuff above and below the collection view.
Anyway...
The collection view shows three items per row and only two rows to begin with.
The first five items are actual items and the last item is a "See More" item.
When the last item is pressed I change the number of items shown and update the collection view...
NSMutableArray *indexPaths = [NSMutableArray array];
for (int i = 5 ; i<self.facilities.count ; i++) {
[indexPaths addObject:[NSIndexPath indexPathForItem:i inSection:0]];
}
// changing the tableCollapsed bool updates the number of items
if (self.isTableCollapsed) {
self.tableCollapsed = NO;
[self.collectionView insertItemsAtIndexPaths:indexPaths];
} else {
self.tableCollapsed = YES;
[self.collectionView deleteItemsAtIndexPaths:indexPaths];
}
I then run...
[self setHeightAnimated:YES];
Which does this...
- (void)setHeightAnimated:(BOOL)animated
{
NSInteger numberOfRows = (NSInteger) ceilf((CGFloat)[self getNumberOfItems] / self.numberOfItemsPerRow);
self.heightConstraint.constant = numberOfRows * self.rowHeight;
if (animated) {
[UIView animateWithDuration:0.2
animations:^{
[self layoutIfNeeded];
}];
} else {
[self layoutIfNeeded];
}
}
This always works and sets the right height and it gets the correct value of animated when it should be YES or NO. However, it never animates. It just switches to the new height immediately.
I'm guessing this is because of some layout code that is run or something but I was wondering if anyone knows how best to do this so that the height changes properly with the animation I have specified.
Thanks

OK! After a couple of hours I found a solution.
I have moved the insertion block into a method like this...
- (void)addItemsAtIndexPaths:(NSArray *)indexPaths {
[UIView performWithoutAnimation:^{
[self.collectionView insertItemsAtIndexPaths:indexPaths];
}];
[self setHeightAnimated:YES completion:nil];
}
This uses a method that I didn't know about the performWithoutAnimation to add items to the collection view. Then I animate the height independently of that.
Works like a charm.
The reverse works also...
- (void)removeItemsAtIndexPaths:(NSArray *)indexPaths {
[self setHeightAnimated:YES completion:^(BOOL finished) {
[UIView performWithoutAnimation:^{
[self.collectionView deleteItemsAtIndexPaths:indexPaths];
}];
}];
}
This animates the height first and then removes the items without animation.

Related

Scrolling a UIView along with UITableView scroll

I have a tableview in which UITableViewCell contains a textfield. When user tap on the textfield and keyboard appears, I scroll to the tapped in row after setting proper content inset.
Now, I have a UIView shown on top of my table view which I need to adjust accordingly when table scrolls.
To do this, I implemented scrollViewDidScroll: method as below. While this works in certain situations, it do not work or give random results in some situations. Am I doing something wrong here?
- (void)scrollViewDidScroll:(UIScrollView *)iScrollView {
if (self.hollowView) {
CGPoint offset = iScrollView.contentOffset;
CGRect hollowViewFrame = self.hollowView.hollowFrame;
hollowViewFrame.origin.y += self.previousOffset - offset.y;
self.previousOffset = offset.y;
[self.hollowView resetToFrame:hollowViewFrame];
}
}
- (void)keyboardDidHide:(NSNotification *)iNotification {
self.previousOffset = 0.0;
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
}
If you want to scroll the both view simultaneously then you should have to take both views with same size and in following method just set the scrollview content offset to them. It will surly work
enter code here - (void)scrollViewDidScroll:(UIScrollView *)iScrollView {
if (self.scrollView) // Check for the scrolled view
{
// Set the Tableview offset directly
tableview.contentOffset = iScrollView.contentOffset
}
else {
//Set view scroll as per tableview scroll
view.contentOffset = iScrollView.contentOffset } }
//Note :- Make sure view should be scrollview type or if view is getting scared or shows black screen
Thanks..
Use this library:
https://github.com/hackiftekhar/IQKeyboardManager
It will handle the position of Views when tapped on a textfield.
So, this piece worked for me for anyone who is struggling with same situation:
- (void)scrollViewDidScroll:(UIScrollView *)iScrollView {
if (self.hollowView) {
CGRect frame = [self.tableView rectForRowAtIndexPath:self.expandedCellIndexPath];
frame.origin.y -= self.tableView.contentOffset.y;
[self.hollowView resetToFrame:frame];
}
}
you can use this for scrolling table in ios.
-(void )keyboardWillShow:(NSNotification *)notification
{
NSDictionary* keyboardInfo = [notification userInfo];
NSValue* keyboardFrameBegin =[keyboardInfovalueForKey:UIKeyboardFrameEndUserInfoKey];
keyBoardHeight = keyboardFrameBegin.CGRectValue.size.height;
vwSendBottomSpaceContraint.constant = keyBoardHeight
[self performSelector:#selector(scrollToBottomAnimated) withObject:nil afterDelay:0.1];
}
-(void)keyboardWillHide:(NSNotification*)notification
{
vwSendBottomSpaceContraint.constant = 0;
[self performSelector:#selector(scrollToBottomAnimated) withObject:nil afterDelay:0.1];
}
-(void)scrollToBottomAnimated
{
NSInteger rows = [tableview numberOfRowsInSection:0];
if(rows > 0)
{
[tableview scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:rows - 1 inSection:0] atScrollPosition:UITableViewScrollPositionBottomanimated:YES];
}
}

UITable view scrolled up by half of UISectionHeader

I have a problem that My UITableView is always scrolled up by maybe the half of Section Header.
I have a custom Section Header which is 44 pixel height.
After a scrolling down and release the focus the table view gets to his good position. The bug happes only after init.
here is my viewDidLoad code :
[self.tableView removeUsslessSeparators];
[self.tableView setEstimatedRowHeight:50];
[self.tableView setEstimatedSectionHeaderHeight:0];
[self.tableView setSectionIndexColor:[UIColor colorWithHexString:#"#000000"]];
[self.tableView setSectionIndexBackgroundColor:[UIColor whiteColor]];
[self.tableView setRowHeight:UITableViewAutomaticDimension];
[self.tableView setSectionHeaderHeight:UITableViewAutomaticDimension];
[self.tableView registerNib:[VOIOrbitContactsListSectionHeader nibRepresentation] forHeaderFooterViewReuseIdentifier:[VOIOrbitContactsListSectionHeader preferredIdentifier]];
[self.tableView registerNib:[VOIOrbitContactCell nibRepresentation] forCellReuseIdentifier:[VOIOrbitContactCell preferredIdentifier]];
self.searchBarController = [VOISearchBarController searchViewControllerWithDelegate:self];
[self containerAddChildViewController:self.searchBarController toContainerView:self.searchControllerContainer useAutolayout:YES];
[self.searchControllerContainerTopOffsetConstraint setConstant:75];
[self.tableViewTopOffsetConstraint setConstant:self.searchControllerContainerTopOffsetConstraint.constant + 4] ;
[self.tableView setContentInset:UIEdgeInsetsMake( self.searchControllerContainerHeightConstraint.constant , 0, 50, 0)];
// CGPoint offset = self.tableView.contentOffset;
// self.tableView.contentOffset = offset;
// [self.tableView setContentOffset:CGPointZero animated:NO];
[self checkIfPlusButtonNeedsToBeHidden];
[NSNotificationCenter addObserverForName:VOCChangeNotificationNameForEntity([VOCOrbit class]) usingBlock:^(NSNotification *note) {
[self.tableView reloadData];
}];
I was trying to use different solutions to scroll down a bit the table view programatically. but none of them works.
[self.searchControllerContainerTopOffsetConstraint setConstant:75];
[self.tableViewTopOffsetConstraint setConstant:self.searchControllerContainerTopOffsetConstraint.constant + 4] ;
Dont use the content offsets rather give the position of the table directly to:
[self.table setframe:CGRectMake(0,0,width,height)];
Then, Pass your header frame as Header Of Table
table.tableHeaderView = yourHeaderView;
Hope, this will work for you.

Stack UITableView Cells on top of eachother

I am creating an app where I am using a list view as a screen. When I click the item I want the items to "stack on eachother" (think of metal flaps),
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
{
int i = 0;
for(UITableViewCell *v in [self.tableView subviews])
{
NSLog(#"%d",i);
[UIView animateWithDuration:0.5 animations:^{
if(i == 0)
{
[v setFrame:CGRectMake(0, self.view.frame.size.height - 50 - (indexPath.row + 200)-i, self.view.frame.size.height, 100)];
}
} completion:^(BOOL finished) {
}];
[self.tableView setScrollEnabled:NO];
i++;
}
}
The table view cells do translate, how ever I cannot achieve the "semi overlapping effect", (I am guessing apple makes table view cells linear layouts relative to each other). Is there a way to override this and make them semi over lap at the bottom of the screen?
You can add a subview to the cell's contentView that extends below the bottom of the cell if you want it to overlap the cell below. Be sure to set the contentView's clipsToBounds property to NO (it's YES by default).

iOS Textfield / select combo to filter through large set of data

I'm fairly new to iOS programming so please excuse anything idiotic that will precede :)
I have a form, where one of the fields can only be a certain predefined value. The list has over 500 options.
I have implemented the use of Search Bar and Display controller in Storyboard and have parsed the data into NSArray for it to be filtered.
Issue I had was the appearance. So what I've done is applied another View (only View that is in storyboard - not sure if this is correct?) and have placed the TableView and Search box into the view). This way I can show / hide the view.
I then created a button (which will look like a field - if that makes sense) where I've applied action to it to show the view.
I can show the view and search / select a cell (which is subsequently updating the button value)
Issue is, after I've selected a option, I can't do this again, i.e. no further click (IBAction) are coming through. Here's my code:
- (IBAction)selectionClick:(id)sender
{
[UIView animateWithDuration:0.25 animations:^{
_searchView.alpha = 1.0f;
} completion:^(BOOL finished) {
[_searchView setHidden:NO];
}];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = cell.textLabel.text;
[_SelectionValue setTitle:cellText forState:UIControlStateNormal];
[self.view endEditing:YES];
tableView.hidden = YES;
[UIView animateWithDuration:0.25 animations:^{
_SearchView.alpha = 0.0f;
} completion:^(BOOL finished) {
[_SearchView setHidden:YES];
}];
}
}
If you need any further info please let me know :)
Setting to 0 alpha and hiding the view doesn't remove the view from the view controller. The view is still present but invisible and block any actions to the view behind hit.
Try
[_SearchView removeFromSuperview];
Instead of
[UIView animateWithDuration:0.25 animations:^{
_SearchView.alpha = 0.0f;
} completion:^(BOOL finished) {
[_SearchView setHidden:YES];
}];
also
variable names normally start lowercased letter. Most examples follow this format.

animating UITableViewHeader to grow/shrink

Im very new to iOS and am trying to figure out how I can animate the tableView header to appear like its sliding down from the top of the view, stay there for 3 seconds, then slide back up and disappear.
I havent done any animation of any kind before so I could really use some help. I dont know where to start. Ive looked at other answers on here but cant seem to figure out how to do it.
ive got my table view appearing just fine with this code in my viewDidLoad of my UITableViewController class
self.headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320,15)];
self.headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 15)];
self.headerLabel.textAlignment = NSTextAlignmentCenter;
self.headerLabel.text = #"some text";
[self.headerView addSubview:self.headerLabel];
self.tableView.tableHeaderView = self.headerView;
self.tableView.tableHeaderView.frame = CGRectMake(0, 0, 320, 15);
I assume I need to animate the height of my frame.
edit: I found this code which seems like it should work, however it crashes my app when the animation runs
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[UIView animateWithDuration:3.0f
delay:0.0f
options: UIViewAnimationOptionBeginFromCurrentState
animations:^{
self.headerView.frame = CGRectMake(0.0f, 0.0f, 320.f, 0.0f);
}
completion:^(BOOL finished) {
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}];
}
I don't know if you can animate a table view's header view like you want to. With a complex UI object like a Table view Apple tends to treat the views that make up the object as private, and bad things tend to happen when you try to manipulate the view hierarch.
If you're not using auto-layout and you want to animate another view that is part of YOUR view hierarchy then your code might be as simple as something like this:
CGPoint center = myView.center;
CGFloat myViewBottom = myView.frame.origin.y + myView.frame.origin.size.height;
//Move the view above the top of it's superview before starting the animation.
center.y -= myViewBottom;
//Animate the view down into position
[UIView animateWithDuration: .2
animations:
^{
myView.center += myViewBottom;
};
completion:
^{
//As the completion block for the first animation, trigger another
//animation to animate the view away again. This time delay
//for 3 second before the 2nd animation.
[UIView animateWithDuration: .2
delay: 3.0
options: 0
animations:
^{
myView.center -= myViewBottom;
};
completion: nil
}
];
Try to use beginUpdates and endUpdates, here is an example:
in your header
#property NSInteger newOffset;
implementation:
- (void) colapseHeader
{
_newOffset = 50;
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 50 + _newOffset;
}
- (void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
_newOffset = 100;
[self.tableView beginUpdates];
[self.tableView endUpdates];
[self performSelector:#selector(colapseHeader) withObject:nil afterDelay:3];
}

Resources