I have a UIButton that scrolls my UICollectionView to the right. The button is added to the superview of my UICollectionView soo it floats on top of the cells.
But I can only let the UIAction take place once. How do I replicate the action or refresh the button so that I can use it again.
Here is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(910, 345 , 100, 100);
button.backgroundColor = [UIColor purpleColor];
[self.collectionView.superview addSubview:button];
[button addTarget:self action:#selector(changeContentOffset:) forControlEvents:UIControlEventTouchUpInside];
}
- (IBAction)changeContentOffset:(id)sender {
[self.collectionView setContentOffset:CGPointMake(910, -65) animated:YES];
}
You can add the button to self.view
or
In your - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
method you can simply add the button to cell content view [cell.contentView addSubview: button];
If you set a breakpoint in the line inside the IBAction, did you stop only once ? According to your question, you want to scroll right each time you click on that button, but your method doesn't do so.
The method set the contentOffset of your UICollectionViewthe first time you tap on the button, but for the other times, since the UICollectionViewis already shifted, you cannot see any change. Try replacing your method with :
- (IBAction)changeContentOffset:(id)sender {
CGPoint offset = self.collectionView;
offset.x += 910;
offset.y -= 65;
[self.collectionView setContentOffset:offset animated:YES];
}
You have to change this method to depend of the collectionView actual position...
self.collectionView.paginateEnabled = YES;
- (IBAction)changeContentOffset:(id)sender {
float x = cellWidth + self.collectionView.contentOffset.x;
[self.collectionView setContentOffset:CGPointMake(910, x) animated:YES];
}
Related
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.
I'm trying to design a UITableViewController such that when the user hits the "Search" button on the navigation bar, the table view drops down and a UIView drops down from the navigation bar. Then, when the user taps anywhere outside of the UIView, the UIView should retract and the table view should return to its original position.
Currently, I have the following method that is the selector for the "Search" button. Note - self.searchBar is a custom UIView subclass.
Is there a cleaner/better way to accomplish this? Also I'm not sure how to get rid of the view after the user taps out of the search menu... I'm guessing I should call, [self.searchBar removeFromSuperview]; but not sure in which delegate method to put that line.
Thanks!
- (void)_showSearchMenu
{
CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height * .25);
frame.origin.y = CGRectGetMaxY(self.navigationController.navigationBar.frame) - frame.size.height;
self.searchBar.frame = frame;
[self.navigationController.navigationBar.superview insertSubview:self.searchBar belowSubview:self.navigationController.navigationBar];
[UIView animateWithDuration:0.5 animations:^{
CGRect frame = self.searchBar.frame;
frame.origin.y = CGRectGetMaxY(self.navigationController.navigationBar.frame);
self.searchBar.frame = frame;
self.tableView.contentOffset = CGPointMake(0, -250);
}];
}
To be more clear, I'm trying to achieve something similar to the effect seen in the HotelTonight app here (the second screen shows what happens when you hit the top right bar button)
This is I think the best approach for that, use these delegates:
(CGFloat) tableView:(UITableView *)tableView
heightForHeaderInSection:(NSInteger)section (UIView *)
tableView:(UITableView *)tableView
viewForHeaderInSection:(NSInteger)section
How:
Create a BOOL isOpen with a default value of NO
When you click the Search Button, implement this:
(void) searchButtonTouch:(id)sender {
isOpen = (isOpen) ? YES : NO;
isOpen = !isOpen;
[self.urTableView reloadData];
}
Now in your delegates:
(CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return (isOpen) ? 170.0f : 0.0f;
}
(UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
CGFloat height = [self tableView:tableView heightForHeaderInSection:section];
UIView *vw = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, height)];
vw.backgroundColor = [UIColor yellowColor];
// add other controls here in your UIView
// or
// just add a UIView at top of your UITableView
// then add other controls to it (if ur using storyboard)
return vw;
}
Add Tapgesture on superview
In TapGesture Action check in if is searchBar view visible
If Visible hide DropDown view by setting new frame with height zero
You can Add Tap Gesture Programmatically or from Interface Builder , You can use its delegate method "shouldReceiveTouch" or any other custom action.
Gesture Implementation
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewFlowLayout *myLayout=[[UICollectionViewFlowLayout alloc]init];
myLayout.scrollDirection=UICollectionViewScrollDirectionHorizontal;
[self.collectionView setCollectionViewLayout:myLayout animated:YES];
UIImageView *recipeImageView=[[UIImageView alloc]initWithFrame:CGRectMake(35, 100, 250, 250)];
recipeImageView.layer.borderColor = [UIColor redColor].CGColor;
recipeImageView.layer.borderWidth = 8.0;
[self.view addSubview:recipeImageView];
NSString *selectedRecipeImageFileName = [self.getName objectAtIndex:indexPath.row];
UIImage *selectedRecipeImage = [UIImage imageNamed:selectedRecipeImageFileName];
recipeImageView.image = selectedRecipeImage;
}
I'm using a collection view. First, I press on any image, then it will show a UIImageView on the view. If I press on another image, then again that image will appear. At this point it works properly. After that, I want to have it so if I press on a blank space then the image view hides. Please give me some ideas.
Add this to your tap gesture:
[recipeImageView removeFromSuperview];
But your image view must be accessible to any function. So you can just make a function and then call it whenever you want.
UPDATE
Sorry for delayed response. Try this:
in your .h file:
first in #interface... add <UIGestureRecognizerDelegate>
and after #interface:
#property UIImageView *recipeImageView;
in your .m files viewDidLoad:
UIGestureRecognizer *taps = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(removeImageView)];
taps.cancelsTouchesInView = NO;
taps.delegate = self;
[self.view addGestureRecognizer:taps];
and somewhere in your .m file:
-(void)removeImageView
{
[_recipeImageView removeFromSuperview];
}
Keep a pointer to that UIImageView and call removeFromSuperview on it.
Use the tap gesture on your main view to remove the UIImageView from superView.
//inside viewDidLoad initilise tap gesture
tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(removeImageView:)];
tapRecognizer.numberOfTapsRequired = 1;
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewFlowLayout *myLayout=[[UICollectionViewFlowLayout alloc]init];
myLayout.scrollDirection=UICollectionViewScrollDirectionHorizontal;
[self.collectionView setCollectionViewLayout:myLayout animated:YES];
UIImageView *recipeImageView=[[UIImageView alloc]initWithFrame:CGRectMake(35, 100, 250, 250)];
recipeImageView.layer.borderColor = [UIColor redColor].CGColor;
recipeImageView.layer.borderWidth = 8.0;
// tap gesture was initialised globally.
[self.view addGestureRecognizer:tapGesture];
[self.view addSubview:recipeImageView];
NSString *selectedRecipeImageFileName = [self.getName objectAtIndex:indexPath.row];
UIImage *selectedRecipeImage = [UIImage imageNamed:selectedRecipeImageFileName];
recipeImageView.image = selectedRecipeImage;
}
Now inside the removeImageView:
- (void)removeImageView:(UITapGestureRecognizer*)sender {
UIView *view = sender.view;
//Now here check the views on which user is taping and match if user is taping on desired view where you want remove the images from superView. and also remove the tap gesture from view.
}
So my app has an editable and sortable UITableView in its left hamburger basement:
To make sure the table cells were skinny enough to show both the delete button and the sorting drag handle on edit, I created a custom UITableViewCell to handle the editing of the table cells:
Everything works fine on edit, but when I tap done, instead of hiding the delete button hangs around:
The code for this, inside of BookmarkTableViewCell.m, is:
- (void)setEditing:(BOOL)editing animated:(BOOL)animate
{
[super setEditing:editing animated:animate];
if (editing) {
for (UIView * view in self.subviews) {
if([[[view class] description] isEqualToString:#"UITableViewCellReorderControl"])
{
UIView *movedReorderControl = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetMaxX(view.frame), CGRectGetMaxY(view.frame))];
[movedReorderControl addSubview:view];
[self addSubview:movedReorderControl];
CGRect newFrame = movedReorderControl.frame;
newFrame.origin.x = -35;
movedReorderControl.frame = newFrame;
}
}
UIImageView *deleteBtn = [[UIImageView alloc]initWithFrame:CGRectMake(10, 10, 24, 24)];
[deleteBtn setImage:[UIImage imageNamed:#"icon_delete.png"]];
[self addSubview:deleteBtn];
}
}
Let me know if you need anymore details. Any insight into fixing this would be great. Thanks!
It looks like you're adding the deleteBtn, but you aren't removing it. if editing is false you should locate the deleteBtn cell and remove it from it's superview so it goes away.
My application has splitview and it's activated only in landscape mode.
In masterview i have tableview and in the last section i have a custom button.
The problem is that the button width stays in potrait instead of using device orientation.
I've tried to play with setAutoresizingMask on button and view but that doesn't work either.
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger) sectionNum {
if (sectionNum == 4) {
CGRect frameSize;
if (UIInterfaceOrientationIsLandscape([[UIDevice currentDevice] orientation])) {
frameSize = CGRectMake(45.0, 0.0, 600.0, 44.0);
} else {
frameSize = CGRectMake(45.0, 0.0, 680.0, 44.0);
}
UIView *btnView = [[[UIView alloc] initWithFrame:frameSize] autorelease];
// button
UIButton* btnFind = [UIButton buttonWithType:UIButtonTypeCustom];
[btnFind setBackgroundImage:[[UIImage imageNamed:#"buttonblue.png"] stretchableImageWithLeftCapWidth:14.0 topCapHeight:0.0] forState:UIControlStateNormal];
[btnFind setBackgroundImage:[[UIImage imageNamed:#"buttonred.png"] stretchableImageWithLeftCapWidth:14.0 topCapHeight:0.0] forState:UIControlStateHighlighted];
btnFind.frame = frameSize;
btnFind.tag = 1;
[btnFind setTitle:#"Find" forState:UIControlStateNormal];
[btnFind addTarget:self action:#selector(doSearchDoc:) forControlEvents:UIControlEventTouchUpInside];
//[btnFind setAutoresizingMask:UIViewAutoresizingFlexibleRightMargin];
//[btnView setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
[btnView addSubview:btnFind];
return btnView;
}
return nil;
}
Can someone please let me know how to resolve this.
Thanks.
I've had other issues that the header was not refreshed when rotating the device, ie. the method above was not invoked in my situatio, you could check if this is the case also for you.
The solution I adopted was to invoke reloadData in the rotating method :
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
// This solves an issue that the header doesn't show when roating device (ok on simulator)
NSIndexPath* ipselected = [self.tableView indexPathForSelectedRow];
[self.tableView reloadData];
[self.tableView selectRowAtIndexPath:ipselected animated:false scrollPosition:UITableViewScrollPositionMiddle];
}
Of course it is usable if you can afford a full reload when rotating the device but itis typically a time when the user will better accept a 0.5s delay as he/she is busy with moving the device.
lternatively you could keep an ivar to your button and change its frame in the above method.