How to present UIView from UITableViewCell - ios

In my app I have a UITableViewCell with a button in it.
- (void)buttonPressed:(id)sender {
UIView *test = [[UIView alloc] initWithFrame:CGRectMake(self.frame.origin.y+5, self.frame.origin.x+53, 200, 200)];
test.backgroundColor = [UIColor redColor];
test.layer.cornerRadius = 15.0f;
test.layer.masksToBounds = YES;
[self addSubview:test];
}
However, this red view is presented behind the section headers. What's the best way to add it to the view from inside the UITableViewCell in a proper way?

Get the cell you want to add it to, and then use
[cell.contentView addSubview: test];
You can get the cell from the button's frame.origin by converting the point to the table view's coordinate system and using the UITableView method indexPathForRowAtPoint. That code might looks like this:
- (NSIndexPath *) indexPathForView: (UIView*) view;
{
CGPoint viewCenter = CGPointMake(
CGRectGetMidX(view.bounds),
CGRectGetMidY(view.bounds)
);
viewCenter = [self.tableView convertPoint: viewCenter fromView: view];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: viewCenter];
return indexPath;
}
Or better yet, as an extension on UITableView:
#implementation UITableView (indexPathForCellContainingView)
- (NSIndexPath *) indexPathForCellContainingView: (UIView *) view;
{
//get the view's center point (which will be in it's parent view's coordinate system
//And convert it to the table view's coorindate system
CGPoint viewCenter = [self convertPoint: view.center fromView: view.superview];
//Ask the table view which cell's index path contains that point.
return [self indexPathForRowAtPoint: viewCenter];
}
#end

You can try this:
- (void)buttonPressed:(id)sender {
UIView *test = [[UIView alloc] initWithFrame:CGRectMake(5, 53, 200, 200)];
test.backgroundColor = [UIColor redColor];
test.layer.cornerRadius = 15.0f;
test.layer.masksToBounds = YES;
[self.contentView addSubview:test];
}

Related

Scrollview should start from where I left it last time

I have a scrollview(timesScrollView) which is added as a subview on a view(dropDownView).The view is hidden until a particular button is pressed, when that button is pressed view will appear.
(IBAction)how_many_times_btn_click:(id)sender{
if(howMany==false){
for(UIView *view in dropDownView.subviews)
{
[view removeFromSuperview];
}
howMany=true;
duration=false;
how_many_times_btn.backgroundColor=[UIColor colorWithRed:130/255.0f green:189/255.0f blue:31/255.0f alpha:1.0f];
durationBtn.backgroundColor=[UIColor colorWithRed:62/255.0f green:67/255.0f blue:79/255.0f alpha:1.0f];
startBtn.backgroundColor=[UIColor colorWithRed:62/255.0f green:67/255.0f blue:79/255.0f alpha:1.0f];
dropDownView.hidden=NO;
dropDownView.frame=CGRectMake(0, 0, self.view.frame.size.width,70);
dropDownView.backgroundColor=[UIColor colorWithRed:37/255.0f green:42/255.0f blue:54/255.0f alpha:1.0f];
//dropDownView.backgroundColor=[UIColor whiteColor];
targetLbl=[[UILabel alloc]init];
targetLbl.frame=CGRectMake(0, 30, dropDownView.frame.size.width,30);
targetLbl.text=#"TARGET";
targetLbl.textColor=[UIColor whiteColor];
targetLbl.font=[UIFont boldSystemFontOfSize:22];
targetLbl.textAlignment=NSTextAlignmentCenter;
how_many_Lbl=[[UILabel alloc]init];
how_many_Lbl.frame=CGRectMake(0, targetLbl.frame.origin.y+targetLbl.frame.size.height, dropDownView.frame.size.width, 20);
how_many_Lbl.textAlignment=NSTextAlignmentCenter;
how_many_Lbl.text=#"HOW MANY TIMES WILL YOU DO IT?";
how_many_Lbl.textColor=[UIColor colorWithRed:65/255.0f green:71/255.0f blue:80/255.0f alpha:1.0f];
how_many_Lbl.font=[UIFont systemFontOfSize:10.0f];
hideViewBtn=[UIButton buttonWithType:UIButtonTypeCustom];
hideViewBtn.frame=CGRectMake(dropDownView.frame.size.width-30,20,20,20);
[hideViewBtn setImage:[UIImage imageNamed:#"Close Icon [ x ]"] forState:UIControlStateNormal];
[hideViewBtn addTarget:self action:#selector(hideView) forControlEvents:UIControlEventTouchUpInside];
//hideViewBtn.backgroundColor=[UIColor whiteColor];
self.timesScroll=[[LTInfiniteScrollView alloc] initWithFrame:CGRectMake(0, how_many_Lbl.frame.origin.y+how_many_Lbl.frame.size.height+16, dropDownView.frame.size.width, 102)];
//self.timesScroll.backgroundColor=[UIColor whiteColor];
self.timesScroll.verticalScroll=NO;
self.timesScroll.dataSource=self;
self.timesScroll.maxScrollDistance=5;
self.timesScroll.contentInset=UIEdgeInsetsMake(0, self.timesScroll.frame.size.width/2-31, 0,self.timesScroll.frame.size.width/2-31 );
self.timesScroll.userInteractionEnabled=YES;
self.timesScroll.exclusiveTouch=YES;
dropDownView.frame=CGRectMake(0, 0, self.view.frame.size.width,_timesScroll.frame.origin.y+_timesScroll.frame.size.height+20);
[self viewWillAppear:YES];
[dropDownView addSubview:targetLbl];
[dropDownView addSubview:how_many_Lbl];
[dropDownView addSubview:hideViewBtn];
[dropDownView addSubview:_timesScroll];
}
else
{
[self hideView];
}
}
The method above is what I am using to create view.
Now my problem is that when that particular button(how_many_times_btn) is pressed again all views are first removed then added as you can see and scrollview starts from initial position but I want it show from where I left it last time how_many_times_btn was clicked.
Hope you can understand What I am trying to say....if not I am happy to elaborate furthur.
you can get the last position by delegate methods
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
nslog(#"%f %f",scrollView.contentOffset.x,scrollView.contentOffset.y);
}
and store the x and y value and set
scrollView.contentOffset = CGPointMake(x,y);
You can save contentOffsetto one variable of CGPoint. And use this variable 's value later to scroll the UIScrollview.
Something like below line of code :
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
contentOffset = scrollView.contentOffset;
}
When button pressed write below line of code:
self.timesScroll .contentOffset = contentOffset;
I'm using LTInfiniteScrollview in which there is a method 'reloadDataWithInitialIndex'
-(void)reloadDataWithInitialIndex:(NSInteger)initialIndex
{
for (UIView *view in self.scrollView.subviews) {
[view removeFromSuperview];
}
self.views = [NSMutableDictionary dictionary];
self.visibleViewCount = [self.dataSource numberOfVisibleViews];
self.totalViewCount = [self.dataSource numberOfViews];
[self updateSize];
_currentIndex = initialIndex;
self.scrollView.contentOffset = [self contentOffsetForIndex:_currentIndex];
[self reArrangeViews];
[self updateProgress];}
This method is called in 'viewWillAppear'
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.viewSize = CGRectGetWidth(self.view.frame) / Number_of_visibleViews;
self.timesScroll.delegate=self;
[self.timesScroll reloadDataWithInitialIndex:howIndex];}
I just passed previous index value here.

iOS - Facebook POP: slide tableview cell to bottom right corner

Maybe you can help me with a problem.
I'm using the new Facebook POP animation framework in an iOS (7) app.
I have a tableview with a "+ button" in each cell. I want that if a user clicks on a button in the cell, that the cell (a copy of that cell) slides to the bottom right corner (in the last tabbar item) from alpha 1 to 0. Like a "add to cart" button. So the user knows that the row is added to the cart.
Does anyone know how I can accomplish that with the Facebook POP framework? Or can you point me in the right direction?
I think it's not so difficult, but I can't figure it out.
Many thanks in advance!
Assuming you refer to a UITableView inside a UIViewController which is assigned as a tab of a UITabBarController, first you duplicate the selected cell into a UIView and then you perform basic POP animation as follows:
#import <math.h>
#import "POPAnimation.h"
#import "POPBasicAnimation.h"
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UIView *view = [self duplicateCell:cell
ContentOffset:tableView.contentOffset
Row:indexPath.row];
[self.view addSubview:view];
NSUInteger numberOfTabs = 3;
CGFloat tabWidth = self.view.frame.size.width / numberOfTabs;
[self fadeOutView:view WhileMoveTo:CGRectMake(self.view.frame.size.width - tabWidth,
tableView.frame.size.height,
tabWidth,
view.frame.size.height)];
}
- (UIView*)duplicateCell:(UITableViewCell*)cell ContentOffset:(CGPoint)offset Row:(NSInteger)row
{
CGFloat cellHeight = cell.frame.size.height;
CGFloat topVisibleCellRow = (int)(offset.y / cellHeight) ;
CGFloat delta = fmodf(offset.y, cellHeight);
CGRect frame = cell.frame;
frame.origin.y = (row - topVisibleCellRow)*cellHeight - delta;
UIView *view = [[UIView alloc] initWithFrame:frame];
view.backgroundColor = [UIColor yellowColor];
UILabel *label = [[UILabel alloc] initWithFrame:cell.textLabel.frame];
label.textColor = [UIColor blackColor];
label.text = cell.textLabel.text;
label.contentMode = UIViewContentModeScaleAspectFit;
[view addSubview:label];
return view;
}
- (void)fadeOutView:(UIView*)view WhileMoveTo:(CGRect)rect
{
[view pop_removeAllAnimations];
POPBasicAnimation *animFrame = [POPBasicAnimation animationWithPropertyNamed:kPOPViewFrame];
POPBasicAnimation *animAlpha = [POPBasicAnimation animationWithPropertyNamed:kPOPViewAlpha];
CGFloat fDuration = 1.5f;
animFrame.toValue = [NSValue valueWithCGRect:rect];
animFrame.duration = fDuration;
animAlpha.toValue = #(0.0);
animAlpha.duration = fDuration;
[view pop_addAnimation:animFrame forKey:#"animateFrame"];
[view pop_addAnimation:animAlpha forKey:#"animateAlpha"];
}
This example is based on a basic UITableViewCell but you can adapt the cell duplication to any custom cell scheme.

UICollectionView full screen zoom on UICollectionViewCell

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.

Control parent tableview using ViewWithTag from the subclass of the table header view

I have a UIView subclass of a table's header view, is it possible to get the table view from my header view subclass using viewWithTag:? I tried below methods but still get nothing:
my method 1:
UIView *tv = (UIView *)[self.superview viewWithTag:11];
my method 2:
UITableView *tv = (UITableView *)[self.superview viewWithTag:11];
Thanks.
The best solution is to walk the view's superview hierarchy until you get to the table view. This approach will work regardless of the underlying table view structure.
UIView *view = self.superview;
UITableView *tv = nil;
while (view) {
if ([view isKindOfClass:[UITableView class]]) {
tv = (UITableView *)view;
break;
}
view = view.superview;
}
if (tv) {
// found the table view. Do something with it
}
Create your UITableView:
TableHeaderView *v = [[TableHeaderView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
_tableView.tableHeaderView = v;
// I think you miss this line
_tableView.tag = 101;
_tableView.backgroundColor = [UIColor redColor];
NSLog(#"%#",_tableView.backgroundColor);
// value: UIDeviceRGBColorSpace 1 0 0 1
In your TableHeaderView:
- (id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
// just example to get super class
[self performSelector:#selector(doSomething) withObject:nil afterDelay:5];
}
return self;
}
- (void) doSomething
{
UITableView *tb = (UITableView*) [self.superview viewWithTag:101];
NSLog(#"%#",tb.backgroundColor);
// value: after:UIDeviceRGBColorSpace 1 0 0 1
}

UITableViewController always display search bar

In iOS 5, is there a way to never hide the search bar in a UITableViewController?
I wouldn't recommend a UITableViewController for that then, a UIViewController with a UITableVIew and UISearchBar on top of it and not on the header would do the job. In a more personal opinion, I wouldn't recommend UITableViewController for anything, I find it too much strict for what it really offers. If for some reason I am using a UITableViewControllerand the customer asks me to add a new element to the screen, I am basically screwed.
I know it's an old question, but I found out a solution for this, which works with the classic UITableViewController and UTSearchDisplayController.
I created a container view for the searchBar 1st then put the searchbar inside it. The container must not clip to bounds. After this you can change the position of the searchbar relative to the container. One problem with this that this way the searchbar not handle user interactions. So we need to use our own container which get the events below its real frame.
Our container class:
#interface _SearchContainerView : UIView
#end
#implementation _SearchContainerView
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
if (self.subviews.count > 0) {
UISearchBar *searchBar = (UISearchBar *) self.subviews[0];
CGRect f = searchBar.frame;
f = CGRectMake(0, 0, f.size.width, f.origin.y + f.size.height);
if (CGRectContainsPoint(f, point)) return YES;
}
return [super pointInside:point withEvent:event];
}
#end
If you create the searchBar programmatically you can set the this up with a following like code:
- (void)setSearchEnabled:(BOOL)searchEnabled {
if (searchBar == nil && searchEnabled) {
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.tableView.bounds.size.width, 44)];
searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar
contentsController:self];
searchBar.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin
| UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
searchDisplayController.delegate = self;
searchDisplayController.searchResultsDataSource = self;
searchContainer = [[_SearchContainerView alloc] initWithFrame:searchBar.frame];
[container addSubview:searchBar];
container.clipsToBounds = NO;
self.tableView.tableHeaderView = container;
} else {
[searchBar removeFromSuperview];
self.tableView.tableHeaderView = nil;
searchBar = nil;
searchDisplayController = nil;
searchContainer = nil;
}
}
Then you can change the position based on the tableView's scroll position:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (searchBar == nil || searchDisplayController.isActive) return;
CGRect b = self.tableView.bounds;
// Position the searchbar to the top of the tableview
searchBar.frame = CGRectMake(0, b.origin.y, b.size.width, 44);
}
And the last part is to restore everything after searching:
- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller {
// Restore header alpha
searchContainer.alpha = 1.0;
// Place the searchbar back to the tableview
[searchBar removeFromSuperview];
[searchContainer addSubview:searchBar];
// Refresh position and redraw
CGPoint co = self.tableView.contentOffset;
[self.tableView setContentOffset:CGPointZero animated:NO];
[self.tableView setContentOffset:co animated:NO];
}

Resources