I have a view where I am showing image and image name in a grid view. As shown in the image.
Now for the same I am taking one UIButton with image as background and UILabel and positioning it accordingly on the screen. Now when I press on the UIButton, it shows the UIActionSheet with option to delete, view and cancel. Now problem comes here. When I press Delete for only one record, the record gets deleted, but if more that one records are there, then gives issues in deleting that it shows the deleted record.
To Add UIButton and UILabel:
-(void)showImageFrame
{
int FrameWidth = 190;
int Frameheight = 196;
int FrameX;
int FrameY;
int lblWidth = 190;
int lblHeight = 40;
int lblX,lblY;
settButton = [UIButton buttonWithType:UIButtonTypeCustom];
[settButton setImage:[UIImage imageNamed:#"Picture frame.png"] forState:UIControlStateNormal];
[settButton addTarget:self action:#selector(pressSelectedImage:) forControlEvents:UIControlEventTouchDown];
btnInnerImg = [UIButton buttonWithType:UIButtonTypeCustom];
[btnInnerImg addTarget:self action:#selector(pressSelectedImage:) forControlEvents:UIControlEventTouchDown];
lblImgName = [[UILabel alloc]init];
lblImgName.font = [UIFont boldSystemFontOfSize:30];
lblImgName.textAlignment = UITextAlignmentCenter;
lblImgName.textColor = [UIColor whiteColor];
lblImgName.backgroundColor = [UIColor clearColor];
for(int i = 0;i<cnt1;i++)
{
[settButton setTag:i];
img = [[appDelegate.DataArray objectAtIndex:i]valueForKey:#"ProfileImage"];
[btnInnerImg setImage:img forState:UIControlStateNormal];
[btnInnerImg setTag:i];
lblImgName.text = [[appDelegate.DataArray objectAtIndex:i]valueForKey:#"strNameImg"];
[lblImgName setTag:i];
if(i==0)
{
FrameX = 35;FrameY = 119;btnX = 49;btnY=134;lblX = 35;lblY=337;
}
if(i==1)
{
FrameX = 289;FrameY = 119;btnX = 303;btnY=134;lblX = 289;lblY=337;
}
if(i==2)
{
FrameX = 545;FrameY = 119;lblX = 545;lblY=337;btnX = 558;btnY=134;
}
if(i==3)
{
FrameX = 802;FrameY = 119;lblX = 802;lblY=337;btnX = 816;btnY=134;
}
if(i==4)
{
FrameX = 35;FrameY = 411;lblX = 35;lblY=629;btnX = 49;btnY=426;
}
if(i==5)
{
FrameX = 289;FrameY = 411;lblX = 289;lblY=629;btnX = 303;btnY=426;
}
if(i==6)
{
FrameX = 545;FrameY = 411;lblX = 545;lblY=629;btnX = 558;btnY=426;
}
if(i==7)
{
FrameX = 802;FrameY = 411;lblX = 802;lblY=629;btnX = 816;btnY=426;
}
[settButton setFrame:CGRectMake(FrameX,FrameY,FrameWidth,Frameheight)];
[lblImgName setFrame:CGRectMake(lblX,lblY,lblWidth,lblHeight)];
[btnInnerImg setFrame:CGRectMake(btnX,btnY,btnWidth,btnHeight)];
[newButtonArray addObject:settButton];
[self.view addSubview: settButton];
[self.view addSubview: lblImgName];
[self.view addSubview: btnInnerImg];
}
}
To remove the UIButton and UILabel:
-(void)removeImageFrame
{
[settButton removeFromSuperview];
[btnInnerImg removeFromSuperview];
[lblImgName removeFromSuperview];
settButton = nil;
btnInnerImg = nil;
lblImgName = nil;
}
I don't want to use UITableviewCell for the grid view. Also what I am doing is that on deleting 1 record, I am removing all the records and reload them again as per record counter. I know I am doing some mistake in removeImageFrame method, but not able to find it. How can I remove the single UIButton with different Tags?
It would be nice to see a bit more context (the action method and how you get from pressing the button to deleting the button), but here is some advice:
Remove all objects from your button array at the start of showImageFrame
Create new buttons (with locally declared variables, not an ivar) inside the loop.
Don't use a tag of 0, that is the default tag that all views have
When a button is tapped, try to pass this as an argument to the removeImageFrame method - that's what sender is for.
You could also look at background images and foreground images for a single button instead of having what appears to be one button for the frame and one for a picture
(unrelated to your problem) try to think of a better way to display a grid than hard coding coordinates. What it the device is rotated?
Related
while presenting the search controller i am setting the showScopeBar property to hide or show the scope bar
- (void)willPresentSearchController:(UISearchController *)searchController {
// do something before the search controller is presented
NSMutableArray *scopeArray = #[#"All"].mutableCopy;
UISearchBar *searchBar =_searchController.searchBar;
if (![labelDepartmentSelection.text isEqualToString:#"Department"]) {
[scopeArray addObject:#"Department"];
}
if (![labelJobSelection.text isEqualToString:#"Job"]) {
[scopeArray addObject:#"Job"];
}
searchBar.scopeButtonTitles = scopeArray;
searchBar.showsScopeBar = scopeArray.count>1;
[searchBar layoutIfNeeded];
NSArray *subviews = searchBar.subviews;
if([[UIDevice currentDevice].systemVersion floatValue]>=7.0) {
//Get search bar with scope bar to reappear after search keyboard is dismissed
UIView *scopeBar = [subviews.firstObject subviews].firstObject;
[scopeBar setHidden:NO];
CGRect frame = scopeBar.frame;
frame.origin.y = frame.origin.y = 64.0;
scopeBar.frame = frame;
}
[searchBar layoutSubviews];
[searchBar sizeToFit];
[serviceOptionTableView setContentInset:UIEdgeInsetsMake(scopeArray.count>1?44:0, 0, 0, 0)];
serviceOptionTableView.tableHeaderView = searchController.searchBar;
}
and when i simply hide and show the scope bar base on the scope titles i want it giet distorted
here is the case for this
- (void)willPresentSearchController:(UISearchController *)searchController {
// do something before the search controller is presented
NSMutableArray *scopeArray = #\[#"All"\].mutableCopy;
UISearchBar *searchBar =_searchController.searchBar;
if (!\[labelDepartmentSelection.text isEqualToString:#"Department"\]) {
\[scopeArray addObject:#"Department"\];
}
if (!\[labelJobSelection.text isEqualToString:#"Job"\]) {
\[scopeArray addObject:#"Job"\];
}
searchBar.scopeButtonTitles = scopeArray;
searchBar.showsScopeBar = scopeArray.count>1;
\[serviceOptionTableView setContentInset:UIEdgeInsetsMake(scopeArray.count>1?44:0, 0, 0, 0)\];
}
this is the image of case 2
The issue should fix itself if you remove the line:
searchBar.showsScopeBar = scopeArray.count>1;
Setting the showScopeBar property has a weird effect for some reason. Removing it allows the default animation behaviour without any issues.
Ive seen this effect in 2 apps and I REALLY want to find how to do it.
The animation is in a UIBarButtonItem, and is only to the image. The image is a + symbol, and it rotates to a X.
If you want to see the effect you have to start a conversation with someone and next to the text input theres the + button for images and emoji's. Or heres a video of the effect in another app, after he taps the bar button you see it rotate to a X, http://www.youtube.com/watch?v=S8JW7euuNMo.
I have found out how to do the effect but only on a UIImageView, I have to turn off all the autoresizing and the view mode has to be centered, then apply the rotation transform to it. I have tried many ways of trying to have it work in a bar item and so far the best way is adding a image view instance, then setting it up and setting the view mode centered and autoresizing off and then using that image view for a custom bar item view. But when i do this, the effect works except while its doing it, the image will go off to the side a little bit instead of staying where it already is. Ive tried getting the center before the animation and set it during the animation but that doesnt do anything.
So the answer for this is you have to make a instance of the Image view, then set it up with no resizing and view mode is centered. Then add the image view to a UIButton with custom type, and then use the button as the custom view for the bar item.
- (IBAction)animate {
[UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
imageView.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(45));
} completion:^(BOOL finished) {
imageView.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(0));
if ([imageView.image isEqual:[UIImage imageNamed:#"Add.png"]]) {
imageView.image = [UIImage imageNamed:#"Close.png"];
}
else imageView.image = [UIImage imageNamed:#"Add.png"];
}];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Add.png"]];
imageView.autoresizingMask = UIViewAutoresizingNone;
imageView.contentMode = UIViewContentModeCenter;
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 0, 40, 40);
[button addSubview:imageView];
[button addTarget:self action:#selector(animate) forControlEvents:UIControlEventTouchUpInside];
imageView.center = button.center;
barItem = [[UIBarButtonItem alloc] initWithCustomView:button];
navItem.rightBarButtonItem = barItem;
}
Recently had to do the same thing in Swift. I created a tutorial that includes starter and final projects, and goes step-by-step with some tips sprinkled in. The code looks like this:
#IBOutlet weak var rightBarButton: UIBarButtonItem! {
didSet {
let icon = UIImage(named: "star")
let iconSize = CGRect(origin: CGPointZero, size: icon!.size)
let iconButton = UIButton(frame: iconSize)
iconButton.setBackgroundImage(icon, forState: .Normal)
rightBarButton.customView = iconButton
rightBarButton.customView!.transform = CGAffineTransformMakeScale(0, 0)
UIView.animateWithDuration(1.0,
delay: 0.5,
usingSpringWithDamping: 0.5,
initialSpringVelocity: 10,
options: .CurveLinear,
animations: {
self.rightBarButton.customView!.transform = CGAffineTransformIdentity
},
completion: nil
)
iconButton.addTarget(self, action: "tappedRightButton", forControlEvents: .TouchUpInside)
}
}
func tappedRightButton(){
rightBarButton.customView!.transform = CGAffineTransformMakeRotation(CGFloat(M_PI * 6/5))
UIView.animateWithDuration(1.0) {
self.rightBarButton.customView!.transform = CGAffineTransformIdentity
}
}
I wanted to keep the expanded tapping size that the native UIBarButtonItem view provides (such as -initWithBarButtonSystemItem:target:action: versus -initWithCustomView:).
Here's a basic implementation of my code.
- (void)setup {
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(navigationBarRightAction)];
}
- (void)navigationBarRightAction {
UIView *itemView = [self.navigationItem.rightBarButtonItem performSelector:#selector(view)];
UIImageView *imageView = [itemView.subviews firstObject];
if (self.shouldRotate) {
imageView.contentMode = UIViewContentModeCenter;
imageView.autoresizingMask = UIViewAutoresizingNone;
imageView.clipsToBounds = NO;
imageView.transform = CGAffineTransformMakeRotation(M_PI_4);
} else {
imageView.transform = CGAffineTransformIdentity;
}
}
You don't have to use a button as a custom view, it works in fact with less code using a UIImageView and adding a UITapGestureRecognizer.
I hope my solution below helps someone b/c I struggled with this for a long time until I got the bar button item to receive taps and get it to work with all the features I wanted. In my case, I made an "alert bell" bar button item that jingles when there are notifications, and then segues to a new tableview controller when tapped.
This was my solution (Swift 5):
#IBOutlet weak var notifyBell: UIBarButtonItem!
func updateNumNotesAndAnimateBell(_ numNotes: Int) {
guard let image = UIImage(named: "alertBellFill_\(numNotes)") else { return }
let imageView = UIImageView(image: image)
notifyBell.customView = imageView
notifyBell.customView?.contentMode = .center
let tap = UITapGestureRecognizer(target: self, action: #selector(notifyBellPressed))
notifyBell.customView?.addGestureRecognizer(tap)
let scaleTransformA = CGAffineTransform(scaleX: 0.8, y: 0.8)
let rotateTransformA = CGAffineTransform(rotationAngle: 0.0)
let hybridTransformA = scaleTransformA.concatenating(rotateTransformA)
let rotateTransformB = CGAffineTransform(rotationAngle: -1*CGFloat.pi*20.0/180.0)
let hybridTransformB = scaleTransformA.concatenating(rotateTransformB)
notifyBell.customView?.transform = hybridTransformA
UIView.animate(withDuration: 3,
delay: 1,
usingSpringWithDamping: 0.1,
initialSpringVelocity: 10,
options: [.allowUserInteraction, .curveEaseInOut],
animations: {
self.notifyBell.customView?.transform = numNotes > 0 ? hybridTransformB : scaleTransformA
},
completion: nil
)
}
#objc func notifyBellPressed(_ sender: UIBarButtonItem) {
performSegue(withIdentifier: "goToNotificationsTVC", sender: self)
}
Key discoveries for me were that:
-- .allowUserInteraction must be included in the animate options, otherwise the UIBarButtonItem won't be active until the animation completes.
-- You will likely have to declare YourBarButtonItem.customView?.contentMode = .center when using CGAffineTransform(rotationAngle: ) or else it will distort your image when it tries to rotate.
-- The code above includes a scale animation and rotate animation that is different depending on how many notifications I have. With zero notifications, the image is an empty bell, else, it displays the number of notifications in the bell image. I probably could've done this with an updating label, but I had already gone the route of making separate PNGs for each so this worked nicely.
So I have an app that behaves like a photo gallery and I'm implementing the ability for the user to delete the images. Here is the setup: I have 9 UIImageViews, imageView, imageView2, etc. I also have an "Edit" button, and a tapGesture action method. I dragged a Tap Gesture Recognizer over onto my view in IB, and attached it to each one of the UIImageViews. I also attached the tapGesture action method to each of the UIImageViews. Ideally, I would like the method to only become active when the "Edit" button is pressed. When the user taps Edit, then taps on the picture they want to delete, I would like a UIAlertView to appear, asking if they are sure they want to delete it. Here is the code I'm using:
- (IBAction)editButtonPressed:(id)sender {
editButton.hidden = YES;
backToGalleryButton.hidden = NO;
tapToDeleteLabel.hidden = NO;
}
- (IBAction)tapGesture:(UITapGestureRecognizer*)gesture
{
UIAlertView *deleteAlertView = [[UIAlertView alloc] initWithTitle:#"Delete"
message:#"Are you sure you want to delete this photo?"
delegate:self
cancelButtonTitle:#"No"
otherButtonTitles:#"Yes", nil];
[deleteAlertView show];
if (buttonIndex != [alertView cancelButtonIndex]) {
UIImageView *view = [self.UIImageView];
if (view) {
[self.array removeObject:view];
}
CGPoint tapLocation = [gesture locationInView: self.view];
for (UIImageView *imageView in self.view.subviews) {
if (CGRectContainsPoint(self.UIImageView.frame, tapLocation)) {
((UIImageView *)[self.view]).image =nil;
}
}
[self.user setObject:self.array forKey:#"images"];
}
}
This code is obviously riddled with errors:
"Use of undeclared identifier button index" on this line: if (buttonIndex != [alertView cancelButtonIndex])
"Property UIImageView not found on object of type PhotoViewController" on this line UIImageView *view = [self.UIImageView];
And "Expected identifier" on this line ((UIImageView *)[self.view]).image =nil;
I'm very new to programming, and I'm surprised that I even made it this far. So, I'm just trying to figure out how I need to edit my code so that the errors go away, and that it can be used whenever one of the 9 image views is tapped, and also so that this method only fires when the Edit button is pushed first. I was using tags earlier, and it worked great, but I save the images via NSData, so I can't use tags anymore. Any help is much appreciated, thanks!
First, you don't want to attach the tap gesture to the image views. Also, if you are going to have more than 9 images, you may want a scroll view, or handle scrolling separately. First, remove that gesture recognizer and all its connections.
Next, determine what type of view you will use as your gallery canvas. A simple View, or a ScrollView, or whatever... it doesn't really matter right now, just to get it working. You want to ctrl-drag that view into your interface definition, so it drops an IBOutlet for the view (that way you can reference it in code).
You will place your ImageViews onto the view I just mentioned.
You can have an internal flag for the gesture recognizer, but it also has a property that use can enable/disable it whenever you want. Thus, you can have it active/inactive fairly easily.
All you want to do is drop a single tap-gesture-recognizer onto your controller, and connect it to the implementation section of the controller. It will generate a stub for handling the recognizer. It will interpret taps "generally" for the controller, and call your code whenever a tap is made on the view.
Some more code...
Creates a frame for the "new" image in the scroll view.
- (CGRect)frameForData:(MyData*)data atIndex:(NSUInteger)idx
{
CGPoint topLeft;
int row = idx / 4;
int col = idx % 4;
topLeft.x = (col+1)*HORIZ_SPACING + THUMBNAIL_WIDTH * (col);
topLeft.y = (row+1)*VERT_SPACING + THUMBNAIL_HEIGHT * (row);
return CGRectMake(topLeft.x, topLeft.y, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT);
}
Creates an image view for each piece of metadata, and a small border.
- (UIImageView*)createImageViewFor:(MetaData*)metadata
{
UIImageView *imageView = [[UIImageView alloc] initWithImage:metadata.lastImage];
imageView.frame = CGRectMake(0, 0, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT);;
imageView.layer.borderColor = [[UIColor blackColor] CGColor];
imageView.layer.borderWidth = 2.0;
imageView.userInteractionEnabled = YES;
return imageView;
}
This is where the views are created and added to the parent...
imageView = [self createImageViewFor:metadata];
//[data.imageView sizeToFit];
// Make sure the scrollView contentSize represents the data
CGRect lastFrame = [self frameForData:data atIndex:self.data.count-1];
CGFloat newHeight = lastFrame.origin.y + lastFrame.size.height;
if (self.bookshelfScrollView.contentSize.height < newHeight) {
CGSize newSize = self.bookshelfScrollView.contentSize;
newSize.height = newHeight;
self.bookshelfScrollView.contentSize = newSize;
}
[self.bookshelfScrollView addSubview:data.imageView];
So, you just create each frame, add them to the view, and the only thing you have to do is enable user interaction on them, because otherwise the scroll view does not allow the gesture through.
OK... Looking at the code you posted... since you didn't say what was wrong with it... hard to say... The below is your code... My comments are, well, Comments...
- (IBAction)editButtonPressed:(id)sender {
editButton.hidden = YES;
backToGalleryButton.hidden = NO;
tapToDeleteLabel.hidden = NO;
}
- (IBAction)tapGesture:(UITapGestureRecognizer*)gesture
{
// I don't think I'd do this here, but it shouldn't cause "problems."
UIAlertView *deleteAlertView = [[UIAlertView alloc] initWithTitle:#"Delete"
message:#"Are you sure you want to delete this photo?"
delegate:self
cancelButtonTitle:#"No"
otherButtonTitles:#"Yes", nil];
[deleteAlertView show];
// In your controller, you have the main view, which is the view
// on which you added your UIViews. You need that view. Add it as an IBOutlet
// You should know how to do that... ctrl-drag to the class INTERFACE source.
// Assuming you name it "galleryView"
// Take the tap location from the gesture, and make sure it is in the
// coordinate space of the view. Loop through all the imageViews and
// find the one that contains the point where the finger was taped.
// Then, "remove" that one from its superview...
CGPoint tapLocation = [gesture locationInView: self.galleryView];
for (UIImageView *imageView in self.galleryView.subviews) {
if (CGRectContainsPoint(imageView.frame, tapLocation)) {
[imageView removeFromSuperview];
}
}
}
Personally, in my little photo gallery, I bypassed all of the gesture recognizer stuff by replacing the UIImageView controls with UIButton controls, setting the image property for the button like you would for the UIImageView. It looks identical, but then you get the functionality of tapping on a thumbnail for free, with no gestures needed at all.
So, my view just has a UIScrollView, which which I programmatically add my images as buttons with the image set for the button control, e.g.:
- (void)loadImages
{
listOfImages = [ImageData newArrayOfImagesForGallery:nil];
// some variables to control where I put my thumbnails (which happen to be 76 x 76px)
int const imageWidth = 76;
int const imageHeight = imageWidth;
NSInteger imagesPerRow;
NSInteger imagePadding;
NSInteger cellWidth;
NSInteger cellHeight;
// some variables to keep track of where I am as I load in my images
int row = 0;
int column = 0;
int index = 0;
// add images to navigation bar
for (ImageData *item in listOfImages)
{
// figure out what row and column I'm on
imagesPerRow = self.view.frame.size.width / (imageWidth + 2);
imagePadding = (self.view.frame.size.width - imageWidth*imagesPerRow) / (imagesPerRow + 1);
cellWidth = imageWidth + imagePadding;
cellHeight = imageHeight + imagePadding;
// this is how I happen to grab my UIImage ... this will vary by implementation
UIImage *thumb = [item imageThumbnail];
// assuming I found it...
if (thumb)
{
// create my button and put my thumbnail image in it
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(column * cellWidth + imagePadding,
row * cellHeight + imagePadding,
imageWidth,
imageHeight);
[button setImage:thumb forState:UIControlStateNormal];
[button addTarget:self
action:#selector(buttonClicked:)
forControlEvents:UIControlEventTouchUpInside];
button.tag = index++;
[[button imageView] setContentMode:UIViewContentModeScaleAspectFit];
// add it to my view
[scrollView addSubview:button];
// increment my column (and if necessary row) counters, making my scrollview larger if I need to)
if (++column == imagesPerRow)
{
column = 0;
row++;
[scrollView setContentSize:CGSizeMake(self.view.frame.size.width, (row+1) * cellHeight + imagePadding)];
}
}
}
}
// I also have this in case the user changes orientation, so I'll move my images around if I need to
- (void)rearrangeImages
{
if (!listOfImages)
{
[self loadImages];
return;
}
// a few varibles to keep track of where I am
int const imageWidth = 76;
int const imagesPerRow = self.view.frame.size.width / (imageWidth + 2);
int const imageHeight = imageWidth;
int const imagePadding = (self.view.frame.size.width - imageWidth*imagesPerRow) / (imagesPerRow + 1);
int const cellWidth = imageWidth + imagePadding;
int const cellHeight = imageHeight + imagePadding;
NSArray *buttons = [[NSArray alloc] initWithArray:[scrollView subviews]];
int row;
int column;
int index;
CGRect newFrame;
// iterate through the buttons
for (UIView *button in buttons)
{
index = [button tag];
if ([button isKindOfClass:[UIButton class]] && index < [listOfImages count])
{
// figure out where the button should go
row = floor(index / imagesPerRow);
column = index % imagesPerRow;
newFrame = CGRectMake(column * cellWidth + imagePadding,
row * cellHeight + imagePadding,
imageWidth,
imageHeight);
// if we need to move it, then animation the moving
if (button.frame.origin.x != newFrame.origin.x || button.frame.origin.y != newFrame.origin.y)
{
[UIView animateWithDuration:0.33 animations:^{
[button setFrame:newFrame];
}];
}
}
}
NSInteger numberOfRows = floor(([listOfImages count] - 1) / imagesPerRow) + 1;
[scrollView setContentSize:CGSizeMake(self.view.frame.size.width, numberOfRows * cellHeight + imagePadding)];
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[self rearrangeImages];
}
Hopefully this gives you an idea of how you can programmatically add a UIButton to act as an image in a gallery. I've tried to edit this on the fly, so I apologize in advance if I introduced any errors in the process, but it should give you a sense of what you could conceivably do ... I removed my code to do this in a separate GCD queue (which I do because I have close to 100 images, and doing this on the main queue is too slow.)
Anyway, you can then create your buttonClicked method to do your display of your UIAlertView.
- (void)buttonClicked:(UIButton *)sender
{
if (inEditMode)
{
// create your UIAlterView using [sender tag] to know which image you tapped on
}
}
Finally, you have two buttons on your UIAlertView, but you don't seem to check to see what button the user clicked on. Your view controller should be a UIAlterViewDelegate, in which you have defined your alertView:clickedButtonAtIndex which will do your actual edit steps.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
// ok, will do what I need to do with whatever the user tapped in my alertview
}
The easiest thing I can think of off the top of my head is to have the gesture disabled by default, and then have the gesture enabled once the edit button is hit. This way, the picture will only respond to the tap gesture recognizer if it is in "Edit" mode.
I'm adding a custom clear button (UIButton) to a UITextField as the rightView, however I've found there's some weird behaviour on the viewMode. It doesn't seem to display as the normal clear button does, despite the view mode being set. Example code below:
UITextField *f = [[[UITextField alloc] init] autorelease];
f.frame = CGRectMake(0, 0, 300, 44);
f.backgroundColor = [UIColor clearColor];
f.textColor = [UIColor whiteColor];
f.clearButtonMode = UITextFieldViewModeNever;
UIImage *image = [UIImage imageNamed:#"Image.png"];
UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom];
b.frame = CGRectMake(0, 0, image.size.width, image.size.height);
[b setImage:image forState:UIControlStateNormal];
f.rightView = b;
f.rightViewMode = UITextFieldViewModeWhileEditing;
The button displays correctly in the following states:
Shows while focused and no text
Shows while focused and typing
Hides when no focus
However, if the textfield already has content, and you switch focus to it the clear button does not show. To get it to show again you must delete all text, and switch focus back and forth.
I haven't found anyone else with this problem, so have been scratching my head on this one for a while. Any light shedding very much appreciated.
This fixes the bug :
- (BOOL)becomeFirstResponder
{
BOOL ret = YES ;
ret = [super becomeFirstResponder] ;
if( ret && ( _setupClearButtonMode == UITextFieldViewModeWhileEditing ) )
self.rightViewMode = UITextFieldViewModeAlways ;
return ret ;
}
- (BOOL)resignFirstResponder
{
BOOL ret = YES ;
ret = [super resignFirstResponder] ;
if( ret && ( _setupClearButtonMode == UITextFieldViewModeWhileEditing ) )
self.rightViewMode = UITextFieldViewModeWhileEditing ;
return ret ;
}
In your subclass of UITextField
with the var _setupClearButtonMode set on init.
I recently ran into the same problem and ended up setting right view mode to UITextFieldViewModeAlways and manually showing/hiding that button when it's needed (made proxy delegate which monitored text field state, set button's visibility and passed messages to actual delegate).
Simple code for solve this problem
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
textField.rightViewMode=UITextFieldViewModeAlways;
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
textField.rightViewMode=UITextFieldViewModeNever;
return YES;
}
I am creating some buttons and putting them inside a UIScrollView like this:
int i = 0;
while (i != numberOfButtons ) {
int updatetY = 160*i;
CGRect buttonFrame = CGRectMake(updatetY, 0, 160, 60);
UIButton *button = [[UIButton alloc] initWithFrame:buttonFrame];
UIImage *buttonImage = [UIImage imageNamed:#"bg.png"];
[button setBackgroundImage:buttonImage forState:UIControlStateNormal];
[button setTitle:[buttonsArray objectAtIndex:i] forState:UIControlStateNormal];
[button addTarget:self action:#selector(MYPROBLEM) forControlEvents:UIControlEventTouchUpInside];
[menuScrollView addSubview:button];
i++;
}
Now I need to build a method to capture which button is being touched, and run a specific bunch of code (see (MYPROBLEM).
Anybody knows what I can do to "trace" which button is being touched and then run a specific function?
something like:
-(void) buttonfunction
{
case ...
doThis
case...
doThat
}
thanks in advance.
You need to use the tag property of the uibutton control. It's a numeric id for the button. You can set a tag on the button based on the i variable in your loop, for instance:
button.tag=i;
Then in your button's action message, you would simply add the id of the button as a parameter and check its tag like so:
-(void) buttonFunction:(id)sender {
switch (sender.tag)
{
//code goes here
}
}
Hope this helps.