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.
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 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];
}
I am working with UICollectionView where I am displaying all the images from photo library of the phone.
When I click on any of the image, the image get flipped and and some information regarding the image is displayed.
When the user again clicks on the same image the image flips again and the original image is shown.
The problem is that whenever I scroll down through the UICollectionView the last selected image flips automatically and the information about the image gets displayed.
How to stop this problem.
Here is some code:
- (void) collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell1 = [collectionView cellForItemAtIndexPath:indexPath];
if(old_path!=NULL){
UICollectionViewCell *cell2 = [collectionView cellForItemAtIndexPath:old_path];
[UIView transitionFromView:cell2.selectedBackgroundView toView:cell2.contentView duration:0.5 options:UIViewAnimationOptionCurveLinear |UIViewAnimationOptionTransitionFlipFromLeft completion:nil];
}
if(old_path==indexPath&&flag)
{
[cell1 setSelected:NO];
[UIView transitionFromView:cell1.selectedBackgroundView toView:cell1.contentView duration:0.5 options:UIViewAnimationOptionCurveLinear |UIViewAnimationOptionTransitionFlipFromLeft completion:nil];
flag=FALSE;
}
else{
[UIView transitionFromView:cell1.contentView toView:cell1.selectedBackgroundView duration:0.5 options:UIViewAnimationOptionCurveLinear |UIViewAnimationOptionTransitionFlipFromLeft completion:nil];
flag=TRUE;
}
old_path=indexPath;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
ALAsset *asset = assets[indexPath.row];
NSLog(#"Description : %#",[asset description]);
UIImage *img=[self imageWithImage:[UIImage imageWithCGImage:[asset thumbnail]] convertToSize:CGSizeMake(150, 150)];
UIView *contents = [[UIView alloc]initWithFrame:cell.bounds];
contents.backgroundColor = [UIColor colorWithPatternImage:img];
[cell.contentView addSubview:contents];
UIView *backgroundView = [[UIView alloc]initWithFrame:cell.bounds];
backgroundView.backgroundColor = [UIColor yellowColor];
UIButton *del=[UIButton buttonWithType:UIButtonTypeRoundedRect];
del.frame= CGRectMake(backgroundView.frame.origin.x+20, backgroundView.frame.origin.y+20, 100, 40);
[del setTitle:#"Delete" forState:UIControlStateNormal];
[del addTarget:self action:#selector(delete) forControlEvents:UIControlEventTouchUpInside];
[backgroundView addSubview:del];
UIButton *cancel=[UIButton buttonWithType:UIButtonTypeRoundedRect];
cancel.frame= CGRectMake(backgroundView.frame.origin.x+20, backgroundView.frame.origin.y+80, 100, 45);
[cancel setTitle:#"Cancel" forState:UIControlStateNormal];
[cancel addTarget:self action:#selector(cancel) forControlEvents:UIControlEventTouchUpInside];
[backgroundView addSubview:cancel];
cell.selectedBackgroundView = backgroundView;
[cell bringSubviewToFront:cell.selectedBackgroundView];
return cell;
}
Here, old_path contains the index of the last selected image.
The main problem is probably with the UIView transition methods:
[UIView transitionFromView:cell1.selectedBackgroundView toView:cell1.contentView duration:0.5 options:UIViewAnimationOptionCurveLinear |UIViewAnimationOptionTransitionFlipFromLeft completion:nil];
UICollectionViewCell's contentView and selectedBackgroundView shouldn't be messed with like this, because the cell manages their layout. This code will remove the content view entirely and replace it with the background view, which is expected to be behind the content view when selected, and removed from the view hierarchy when not selected.
The proper way to accomplish what you're doing (showing / hiding the image in response to a tap) would be perform the transition between the image view itself and another subview on the content view.
There could also be something in your resizing code that's flipping the image, but it's hard to say without the code for imageWithImage:convertToSize:. It would probably be more efficient to get rid of that method, and do something like this:
UIImageView *imageView = [[UIImageView alloc] initWithFrame:cell.bounds];
imageView.contentsMode = UIViewContentModeScaleAspectFill;
imageView.clipsToBounds = YES;
imageView.image = [UIImage imageWithCGImage:[asset thumbnail]];
[cell.contentsView addSubview:imageView];
A couple of other observations:
Collection view cells are reused, which means that your implementation collectionView:cellForItemAtIndexPath: could end up adding a whole pile of image views to a cell that has been dequeued several times. A better solution would be to subclass UICollectionViewCell and add the custom views in its init method.
The code old_path==indexPath does not actually test for equality between the two index paths, just if the two variables have the same address in memory. Use [oldPath isEqual:indexPath] instead.
You cannot do custom animations on background views without subclassing and handling explicitly. Because collection view automatically brings the selectedBackgroundView to top if selectedBackgroundView is not same as backgroundView. Adding apple documentation for reference.
// The background view is a subview behind all other views.
// If selectedBackgroundView is different than backgroundView, it will be placed above the background view and animated in on selection.
https://developer.apple.com/library/iOs/documentation/UIKit/Reference/UICollectionViewCell_class/Reference/Reference.html
So I'm having issues with the buttons for the filters in my photo app. I'm not exactly sure why, but they've suddenly stopped working. The selector is not being called when they're tapped, but I have no idea why. They were working just fine a few days ago, but for some reason they're not now. I've checked the UIView subviews array, verified that it's right on top. I need a way to see if, for some reason, the touches are not making it to the button. I'm not sure how to do this.
I wish I had more information to give, but this is all I've got. I hope someone has some suggestions because I'm at wit's end with it.
Thanks in advance!
Button Creation Method:
-(void)createFilterButtonsForThumbnail:(UIImage *)thumbnail
{
UIView *filtersContainer = self.filterContainer;
CGRect buttonFrame = CGRectMake(kFilterFrameThickness, kFilterFrameThickness,
thumbnail.size.width, thumbnail.size.height);
CGFloat frameWidth = thumbnail.size.width+(2*kFilterFrameThickness);
CGFloat frameHeight = kFilterPickerHeight;
UIEdgeInsets backgroundInsets = UIEdgeInsetsMake(0, kFilterFrameThickness, 0, kFilterFrameThickness);
UIImage *buttonBackgroundImage = [[UIImage imageNamed:#"FilmReel"] resizableImageWithCapInsets:backgroundInsets];
for (int i = 0;i<(self.filterPaths.count+kFilterNonLookups+1);i++){
UIImageView *buttonBackground = [[UIImageView alloc] initWithFrame:CGRectMake(kFilterSidePadding+(i*(frameWidth+kFilterSidePadding)),
0,
frameWidth,
frameHeight)];
[buttonBackground setImage:buttonBackgroundImage];
UIButton *thumbnailButton = [[UIButton alloc] initWithFrame:buttonFrame];
UIImage *filteredThumbnail = [self applyFilterAtIndex:i ToImage:thumbnail];
[thumbnailButton setImage:filteredThumbnail forState:UIControlStateNormal];
[thumbnailButton addTarget:self action:#selector(filterSelected:) forControlEvents:UIControlEventTouchUpInside];
[thumbnailButton setTag:i];
[buttonBackground addSubview:thumbnailButton];
[filtersContainer addSubview:buttonBackground];
if ((i > (kFilterProMinimumIndex)) && ([self isProVersion]) == NO){
UIImageView *proTag = [[UIImageView alloc] initWithImage:nil];
CGRect proFrame = CGRectMake(buttonFrame.origin.x,
buttonFrame.origin.y + buttonFrame.size.height - kFilterProIconHeight-kFilterFrameThickness,
kFilterProIconWidth,
kFilterProIconHeight);
[proTag setBackgroundColor:[UIColor orangeColor]];
[proTag setFrame:proFrame];
[thumbnailButton addSubview:proTag];
[self.filterProTags addObject:proTag];
}
}
}
Selector Method:
-(void)filterSelected:(UIButton *)button
{
NSLog(#"Pressed button for index %i",button.tag);
int buttonTag = button.tag;
if ((buttonTag < kFilterProMinimumIndex+1) || ([self isProVersion] == YES)){
[self.imageView setImage:[self applyFilterAtIndex:buttonTag ToImage:self.workingImage]];
}
else {
[self processProPurchaseAfterAlert];
}
}
I see a couple issues in this, but I'm not sure which ones are causing it to break. First, you should instantiate your button using buttonWithType: on UIButton:
UIButton *thumbnailButton = [UIButton buttonWithType:UIButtonTypeCustom];
[thumbnailButton setFrame:buttonFrame]
The reason for this is UIButton is a class cluster, and you should let the OS give you the correct button.
Secondly, you're adding the Button as a Subview of an UIImageView, which by default, has userInteractionEnabled set to NO.
This property is inherited from the UIView parent class. This class
changes the default value of this property to NO.
You should have the button be one large button, with the background of the button be the image you want it to be.
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.