Theoretically the following code should animate the table view cell of the screen to the right and bring in a dark "view" in it's place.
CGPoint location = [gesture locationInView:tableView];
NSIndexPath *swipedIndexPath = [tableView indexPathForRowAtPoint:location];
UITableViewCell *swipedCell = [tableView cellForRowAtIndexPath:swipedIndexPath];
//code to create view
UIView *sideView;
sideView.backgroundColor = [UIColor lightGrayColor];
//set the side view frame to the same as the cell
sideView.frame = swipedCell.frame;
//add it to the tableview
[tableView addSubview:sideView];
[UIView animateWithDuration:1
animations:^{
sideView.frame = CGRectMake(0, swipedCell.frame.origin.y, swipedCell.frame.size.width, swipedCell.frame.size.height);
// While simultaneously moving the cell's frame offscreen
// The net effect is that the side swipe view is pushing the cell offscreen
swipedCell.frame = CGRectMake(swipedCell.frame.size.width, swipedCell.frame.origin.y, swipedCell.frame.size.width, swipedCell.frame.size.height); //move cell off
}];
However, only the cell moves off the screen. No gray view comes in it's place.
Is there a step I am missing? What is wrong with this code?
Video of example here
The big error is that you're not initializing sideView to anything.
Try UIView* sideview = [[UIView alloc] initWithFrame:swipedCell.frame];
It doesn't sound like a good idea to add a view in place of a cell just like that. You'd have to deal with scrolling, table view editing, and other stuff that the UITableView takes care of for you. So instead, try adding the sideView as a subview of swipedCell.contentView and then doing this animation instead:
[UIView animateWithDuration:1 animations:^{
sideView.frame = CGRectMake(0, swipedCell.frame.origin.y, swipedCell.frame.size.width, swipedCell.frame.size.height);
//This moves all the subviews except for the sideView off the screen
for (UIView *subview in swipedCell.contentView.subviews)
if (![subview isEqual:sideView])
subview.frame = CGRectOffset(subview.frame, swipedCell.frame.size.width, 0.0);
}];
Hope this helps!
Related
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).
How can you zoom in on a UICollectionViewCell so that it will be displayed full screen? I have extended UICollectionViewFlowLayout and in my view controller when a cell is tapped I'm doing this:
CGPoint pointInCollectionView = [gesture locationInView:self.collectionView];
NSIndexPath *selectedIndexPath = [self.collectionView indexPathForItemAtPoint:pointInCollectionView];
UICollectionViewCell *selectedCell = [self.collectionView cellForItemAtIndexPath:selectedIndexPath];
NSLog(#"Selected cell %#", selectedIndexPath);
Not really sure where to go from here. Should the UICollectionView be responsible of showing the zoomed in cell? Or should I create a new view controller that displays the content of the cell (an image) in full screen?
I took the solution here and modified it slightly to work with a collection view instead. I also added a transparent gray background to hide the original view a bit (assuming the image doesn't take up the entire frame).
#implementation CollectionViewController
{
UIImageView *fullScreenImageView;
UIImageView *originalImageView;
}
...
// in whatever method you're using to detect the cell selection
CGPoint pointInCollectionView = [gesture locationInView:self.collectionView];
NSIndexPath *selectedIndexPath = [self.collectionView indexPathForItemAtPoint:pointInCollectionView];
UICollectionViewCell *selectedCell = [self.collectionView cellForItemAtIndexPath:selectedIndexPath];
originalImageView = [selectedCell imageView]; // or whatever cell element holds your image that you want to zoom
fullScreenImageView = [[UIImageView alloc] init];
[fullScreenImageView setContentMode:UIViewContentModeScaleAspectFit];
fullScreenImageView.image = [originalImageView image];
// ***********************************************************************************
// You can either use this to zoom in from the center of your cell
CGRect tempPoint = CGRectMake(originalImageView.center.x, originalImageView.center.y, 0, 0);
// OR, if you want to zoom from the tapped point...
CGRect tempPoint = CGRectMake(pointInCollectionView.x, pointInCollectionView.y, 0, 0);
// ***********************************************************************************
CGRect startingPoint = [self.view convertRect:tempPoint fromView:[self.collectionView cellForItemAtIndexPath:selectedIndexPath]];
[fullScreenImageView setFrame:startingPoint];
[fullScreenImageView setBackgroundColor:[[UIColor lightGrayColor] colorWithAlphaComponent:0.9f]];
[self.view addSubview:fullScreenImageView];
[UIView animateWithDuration:0.4
animations:^{
[fullScreenImageView setFrame:CGRectMake(0,
0,
self.view.bounds.size.width,
self.view.bounds.size.height)];
}];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(fullScreenImageViewTapped:)];
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
[fullScreenImageView addGestureRecognizer:singleTap];
[fullScreenImageView setUserInteractionEnabled:YES];
...
- (void)fullScreenImageViewTapped:(UIGestureRecognizer *)gestureRecognizer {
CGRect point=[self.view convertRect:originalImageView.bounds fromView:originalImageView];
gestureRecognizer.view.backgroundColor=[UIColor clearColor];
[UIView animateWithDuration:0.5
animations:^{
[(UIImageView *)gestureRecognizer.view setFrame:point];
}];
[self performSelector:#selector(animationDone:) withObject:[gestureRecognizer view] afterDelay:0.4];
}
-(void)animationDone:(UIView *)view
{
[fullScreenImageView removeFromSuperview];
fullScreenImageView = nil;
}
You can simply use another layout (similar to the one you already have) wherein the item size is larger, and then do setCollectionViewLayout:animated:completion: on the collectionView.
You don't need a new view controller. Your datasource remains the same. You can even use the same cell Class, just make sure that it knows when to layout things for a larger cell content size, and when not to.
I'm quite sure that's how Facebook does it in Paper, as there is no reloading of the content, i.e. [collectionView reloadData] never seems to be called (would have caused flickering and resetting of the scroll offset, etc). This seems to be the most straight forward possible solution.
CGPoint pointInCollectionView = [gesture locationInView:self.collectionView];
NSIndexPath *selectedIndexPath = [self.collectionView indexPathForItemAtPoint:pointInCollectionView];
UICollectionViewCell *selectedCell = [self.collectionView cellForItemAtIndexPath:selectedIndexPath];
NSLog(#"Selected cell %#", selectedIndexPath);
__weak typeof(self) weakSelf = self;
[self.collectionView setCollectionViewLayout:newLayout animated:YES completion:^{
[weakSelf.collectionView scrollToItemAtIndexPath:selectedIndexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
}];
You can use MWPhotoBrowser, which is suitable for your problem. It supports Grid with Tap to Zoom functionality. you can get it from here
Grid
In order to properly show the grid of thumbnails, you must ensure the property enableGrid is set to YES, and implement the following delegate method:
(id <MWPhoto>)photoBrowser:(MWPhotoBrowser *)photoBrowser thumbPhotoAtIndex:(NSUInteger)index;
The photo browser can also start on the grid by enabling the startOnGrid property.
I've been trying to use this tutorial to make the reorder button cover the entire cell. It works great until the cell disappears from the view. Once you go back to the cell, the reorder button has shifted over quite a bit.
In this picture, the red represents the reorder button.
Here's the code used in the tutorial.
- (void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
// Grip customization code goes in here...
for(UIView* view in cell.subviews)
{
if([[[view class] description] isEqualToString:#"UITableViewCellReorderControl"])
{
UIView* resizedGripView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetMaxX(view.frame), CGRectGetMaxY(view.frame))];
[resizedGripView addSubview:view];
[cell addSubview:resizedGripView];
[resizedGripView release];
CGSize sizeDifference = CGSizeMake(resizedGripView.frame.size.width - view.frame.size.width, resizedGripView.frame.size.height - view.frame.size.height);
CGSize transformRatio = CGSizeMake(resizedGripView.frame.size.width / view.frame.size.width, resizedGripView.frame.size.height / view.frame.size.height);
// Original transform
CGAffineTransform transform = CGAffineTransformIdentity;
// Scale custom view so grip will fill entire cell
transform = CGAffineTransformScale(transform, transformRatio.width, transformRatio.height);
// Move custom view so the grip's top left aligns with the cell's top left
transform = CGAffineTransformTranslate(transform, -sizeDifference.width / 2.0, -sizeDifference.height / 2.0);
[resizedGripView setTransform:transform];
for(UIImageView* cellGrip in view.subviews)
{
if([cellGrip isKindOfClass:[UIImageView class]])
[cellGrip setImage:nil];
}
}
}
}
How do I keep the reorder control from moving to the left? I've tried to translate the transform again, but that just makes it so the reorder control is completely off the screen. What's wrong with the code that makes it move to the left and how do I fix it?
I figured out how to do it! I had to add a property to the viewController that stored the initial frame of the resizedGripView. It turns out that every time the method was being called (every time the cell appeared again), the reorder button was being moved from it's current position, so I had to store it's initial position.
UIView* resizedGripView = [[UIView alloc] init];
if (!initialFrame.size.height)
[resizedGripView setFrame: CGRectMake(0, 0, CGRectGetMaxX(view.frame), CGRectGetMaxY(view.frame))];
else
[resizedGripView setFrame: initialFrame];
if (!initialFrame.size.height)
[self setInitialFrame: resizedGripView.frame];
I have a screen which contains several subviews. On the user's interaction, I want to add another subview, change the positions of the other subviews, and make them disappear at the same time. My code is:
[self.view addSubview:imageView];
[UIView animateWithDuration:0.3
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
for (UIView *currentItemView in self.currentItemViews) {
currentItemView.center = someCenter;
currentItemView.alpha = 0;
}
} completion:^(BOOL finished) {
}];
Before I added the code with the new subview everything worked fine, but now the only thing is animated is the setting of alpha. The subviews don't move.
Any idea why and how to solve this?
Thanks in advance!
EDIT:
The code for creating the currentItemViews array:
self.currentItemViews = [[NSMutableArray alloc] initWithCapacity:6];
for (Item *item in arrayOfItems) {
ItemView *itemView = [[NSBundle mainBundle] loadNibNamed:#"ItemView" owner:self options:nil].lastObject;
itemView.item = item;
[self.currentItemViews addObject:itemView];
[self.view addSubview:itemView];
}
The ViewController I'm in, is a childViewController to another one, so it's view is added as subview too. Could that be the problem?
Please help. Trying to get animation of frame position working inside a UITableViewCell, specifically I'm trying to move the default UILabel (cell.textLabel). However, no matter what technique I use, I can't get any view inside the cell to move. The animation of colour and alpha works as outlined by the code below.
Cheers in advance for help.
Andy
Here is the code I am using:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0 && indexPath.row == 0) {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
CGRect textLabelFrame = cell.textLabel.frame;
textLabelFrame.origin.x = -textLabelFrame.size.width;
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationCurveEaseOut
animations:^{
cell.textLabel.frame = textLabelFrame; // THIS DOESN'T WORK - HELP!
cell.imageView.frame = CGRectOffset(cell.imageView.frame,0,0); // EVEN TRYING TO MOVE IMAGEVIEW DOESN'T WORK
cell.textLabel.alpha = 0; // This animates
cell.imageView.backgroundColor = [UIColor redColor]; // This animates
}
completion:^(BOOL finished){
NSLog(#"Done!");
}];
}
}
I don't think it's possible to reposition the default label or image view in a standard cell. If you want to do that, you should add your own subviews to the cell's contentView, and do your animations with those.