In my table cells, there is a button that displays a drop-down menu when you click on it. The problem is, the drop-down menu exceeds the height of the cell and bleeds into the cell below.
In that case, if I click the item in the drop-down, it actually acts as I clicked the cell below.
I tried using the code below but it doesn't seem to work.
[super bringSubviewToFront:dropDown];
[super willMoveToSuperview:dropDown];
The function that shows the drop-down is defined in the custom class for the table cell:
- (IBAction)eventAction:(id)sender {
NSArray * arr = [[NSArray alloc] init];
arr = [NSArray arrayWithObjects:#"Hello 0", #"Hello 1",nil];
NSArray * arrImage = [[NSArray alloc] init];
arrImage = [NSArray arrayWithObjects:[UIImage imageNamed:#"apple.png"], [UIImage imageNamed:#"apple2.png"], nil];
if(dropDown == nil) {
CGFloat f = 100;
dropDown = [[NIDropDown alloc]showDropDown:sender :&f :arr :arrImage :#"down"];
dropDown.delegate = self;
dropDown.layer.zPosition = 1;
[super bringSubviewToFront:dropDown];
[super willMoveToSuperview:dropDown];
}else {
[dropDown hideDropDown:sender];
[self rel];
}
}
Any help is greatly appreciated!!
Thank you!!
Rather than being a case of views being on top of each other, I think it might be that the touch is being interpreted by the table cell below as well.
Try disabling user interaction in the table view when the eventAction is fired.
tableView.userInteractionEnabled = NO;
And then turn it back on when the drop down view is dismissed.
Related
I am using NIDropworn in a strip of view the problem is the drop-down table is coming over another view which I have just placed below the drop-down view.
I am unable to select and and do any operation on the drop down table .
Is there a way that I can add the drop-down in the second view.
now the dropdown is coming on the small strip of view.
For example: I am having the dropDown menu in the header of a page which is view1.and the dropdown table is coming on the body which is view2.
You may not have added the NIDropDown in your view.
- (IBAction)btn_click:(id)sender {
NSArray * arr = [[NSArray alloc] init];
arr = [NSArray arrayWithObjects:#"None",#"Name",#"Date",nil];
// NSArray * arrImage = [[NSArray alloc] init];
if(dropDown == nil) {
CGFloat f = 130;
dropDown = [[NIDropDown alloc]showDropDown:sender :&f :arr :nil :#"down"];
dropDown.delegate = self;
dropDown.userInteractionEnabled=YES;
[self.viewBelowDD addSubview:dropDown]; // may be missing this line
[self.viewBelowDD bringSubviewToFront:dropDown];
}
else {
[dropDown hideDropDown:sender];
[self rel];
}
}
Hope that helps. Let me know if this doesn't work.
So I want to highlight a specific UIView in iCarousel when I click a button within that view and I want to be able to highlight as many views as I want within the carousel. So I have a button that sets the alpha of a UIImageview within the view the problem that I'm running into is although it knows the index of the view I don't know how to call the corresponding index of the UIImageview within that view. So I setup the UIImageview within a custom nib and I have this code setting up the iCarousel's view it:
UPDATED based on #danh answer
//.h
#property (nonatomic, strong)NSMutableSet *selected;
//.m
- (void)viewDidLoad
{
self.selected = [NSMutableSet set];
}
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
//create new view if no view is available for recycling
if (view == nil)
{
view = [[[NSBundle mainBundle] loadNibNamed:#"ItemView" owner:self options:nil] lastObject];
}
int chkTag = checkImg.tag;
checkImg = (UIImageView *)[checkImg viewWithTag:chkTag];
NSNumber *indexNum = [NSNumber numberWithInt:index];
// here's where the view state gets set
checkImg.alpha = ([self.selected member:indexNum])? 1.0 : 0.0;
return view;
}
Then I have this called when the specific view is being selected:
- (void)carouselCurrentItemIndexUpdated:(iCarousel *)carousel1{
NSInteger indexInt = carousel1.currentItemIndex;
NSNumber *index = [NSNumber numberWithInt:indexInt];
if ([self.selected member:index]) {
[self.selected removeObject:index];
} else {
[self.selected addObject:index];
}
// now just reload that item, and let the viewForItemAtIndex
// take care of the selection state
[carousel reloadItemAtIndex:indexInt animated:NO];
}
Which works but only allows me to select one item at a time and check it. I want to be able to select/unselect multiple items at a time.
It works like a table view. You need is a model for selected items. This needs to outlive any given carousel view. So add a property NSMutableSet *selectedItems and initialize it with self.selected = [NSMutableSet set];
When the button is pressed, you want to add the current index to that set (does that button toggle selection? if so, then you want to add it if it's absent, or remove it if it's present).
NSInteger indexInt = carousel1.currentItemIndex;
NSNumber *index = [NSNumber numberWithInt:indexInt];
if ([self.selected member:index]) {
[self.selected removeObject:iIndex];
} else {
[self.selected addObject:index];
}
// now just reload that item, and let the viewForItemAtIndex
// take care of the selection state
[carousel reloadItemAtIndex:indexInt animated:NO];
The last step is to react to the selection state when you configure a view:
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view {
if (view == nil) {
view = [[[NSBundle mainBundle] loadNibNamed:#"ItemView" owner:self options:nil] lastObject];
}
// get the checkImg view however you do that already. if you're confused about this
// give it a tag when you create it, then find it like this:
UIImageView *checkImg = (UIImageView *)[view viewWithTag:SOME_TAG];
NSNumber *indexNum = [NSNumber numberWithInt:index];
// here's where the view state gets set
checking.alpha = ([self.selected member:indexNum])? 1.0 : 0.0;
return view;
}
EDIT - Part of the problem seems to be creating and then later getting subviews of the carousel. UIView provides a tag property that will help, but the posted code makes a couple errors. Here's how to use tags:
If you create the image view in IB, give it a tag using the properties inspector. Here, I gave a view a tag of 32.
Now SOME_TAG in my suggestion above should be 32, so...
UIImageView *checkImg = (UIImageView *)[view viewWithTag:32];
NSLog(#"%#", checkImg);
// if this doesn't log an image view, then something is wrong.
I have 6 UIButtons set up in my UIView, all in the exact same location. What I want to do, is to swipe from left to right or right to left, in order to go through the buttons.
I have the UIGestures all set up and working on the view, I am just not sure the best way to go about cycling through these UIButtons.
I was thinking that it could be simple enough to tag each UIButton and HIDE all but one, but am not sure about the best way to loop through these.
Just put them in an NSMutableArray and whatever button is at index 0 is the visible one, as they swipe you'd remove the button at index 0, set it to hidden = YES and add it to the end of the array then set the button at index 0's hidden = NO.
Assuming you're using ARC, inside your class' implementation (.m) file:
#interface MyFancyButtonClass () {
NSMutableArray *_swipeButtons;
}
inside your viewDidLoad:
_swipeButtons = [NSMutableArray arrayWithObjects:buttonOne, buttonTwo, buttonThree, buttonFour, nil];
buttonOne.hidden = NO;
buttonTwo.hidden = buttonThree.hidden = buttonFour.hidden = YES;
inside your gestureRecognizer:
UIButton *currentVisibleButton = [_swipeButtons firstObject];
UIButton *nextVisibleButton = [_swipeButtons objectAtIndex:1];
[_swipeButtons removeObject:currentVisibleButton];
[_swipeButtons addObject:currentVisibleButton];
currentVisibleButton.hidden = YES;
nextVisibleButton.hidden = NO;
Create a NSMutableArray like this:
NSMutableArray * buttons = [[NSMutableArray alloc] init];
[buttons addObject:button1];
[buttons addObject:button2];
[buttons addObject:button3];
[buttons addObject:button4];
[buttons addObject:button5];
Save this array to a property like this
self.buttons = buttons;
Store the currentButton Like this:
int currentButton = 0;
Get the current button like this:
UIButton * currentSelectedButton = buttons[currentButton];
Cycle through the buttons like this:
UIButton * currentSelectedButton = buttons[currentButton];
currentSelectedButton.hidden = YES;
currentButton++;
if (currentButton >= self.buttons.count)
currentButton = 0;
currentSelectedButton = buttons[currentButton];
currentSelectedButton.hidden = NO;
I want to add additional menu item for the menu that appears when some text is selected.
I have added the code below to viewDidLoad:
NSMutableArray *extraItems = [[NSMutableArray alloc] init];
UIMenuItem *boldItem = [[UIMenuItem alloc] initWithTitle:#"Bold"
action:#selector(bold:)];
[extraItems addObject:boldItem];
[UIMenuController sharedMenuController].menuItems = extraItems;
I also have overwritten my custom UIWebView with these methods:
- (void)bold:(id)sender {
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
if (action == #selector(bold:))
return YES;
return [super canPerformAction:action
withSender:sender];
}
So sometimes when I highlight the text the menu appeasers, but sometimes it does not. I don't know what the problem is.
Your array "extraItems" should be an NSArray, not an NSMutableArray, so your first three lines that you added to viewDidLoad should be replaced by:
UIMenuItem* extraItem = [[UIMenuItem alloc] initWithTitle:#"Bold"
action:#selector(bold:)];
NSArray* extraItems = [NSArray arrayWithObject:extraItem];
Then add this version of extraItems array to the sharedMenuController just as you did.
In my app I have a pretty large form to be filled out. The form itself is made with a table view and static cells mode. Each of the cells containing a label and a textfield. I wanted to add a toolbar above the keyboard to enable navigating between the text fields. I did that, however it is behaving very strange (at least I think).
I have no problems jumping to the next text field while jumping to the previous textfield is only possible if it is visible. If it is not visible the old textfield stays first responder, however the moment I scroll my table view and the intended text field becomes visible, it becomes the first responder (I do not click into it!). Well this is of course not the behavior that I wanted.
My question is: Is this kind of behavior normal? Could you somehow circumvent it?
If you want to see this kind of behavior yourself I have uploaded an Xcode project that illustrates the problem. You can download the zipped project here: download. The main parts of the code are explained below.
I set up a grouped table view with static cell. Each of them containing a label and a textfield. I created outlets for every textfield to gain access to them. In my viewDidLoad method I create the toolbar and its buttons, store the textfields in an array and set the controller to be the textfields delegate.
- (void)viewDidLoad
{
[super viewDidLoad];
// create the keyboard toolbar with navigation elements
self.keyboardToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 44)];
UIBarButtonItem *prevButton = [[UIBarButtonItem alloc] initWithTitle:#"Previous" style:UIBarButtonItemStyleBordered target:self action:#selector(prevClicked:)];
UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithTitle:#"Next" style:UIBarButtonItemStyleBordered target:self action:#selector(nextClicked:)];
[self.keyboardToolbar setItems:[NSArray arrayWithObjects:prevButton, nextButton, nil]];
// create the field chain
self.fields = [NSArray arrayWithObjects:self.aField, self.bField, self.cField, self.dField, self.eField, self.fField, nil];
// for scrolling and keeping track of currently active field
NSInteger max = [self.fields count];
for(NSInteger i = 0; i < max; i++) {
UITextField *curr = (UITextField *)[self.fields objectAtIndex:i];
curr.delegate = self;
}
}
The text field delegate methods store a reference of the active text field and prevent line breaks from being inserted.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
textField.inputAccessoryView = self.keyboardToolbar;
return YES;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
// set the current active textfield
self.currentField = textField;
// scroll this textfield to top
UITableViewCell *cell = (UITableViewCell *)textField.superview.superview;
[self.tableView scrollToRowAtIndexPath:[self.tableView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
self.currentField = nil;
return NO;
}
And finally there are the selectors for the toolbar buttons and the logic to get the next textfield.
- (void)moveResponderByStep:(NSInteger)step
{
// only move if a textfield is the current responder
if(![self.currentField isEditing]) {
return;
}
// where we are and where to move
NSInteger max = [self.fields count];
NSInteger moveToNumber;
for(NSInteger i = 0; i < max; i++) {
if(self.currentField == [self.fields objectAtIndex:i]) {
moveToNumber = i + step;
}
}
// stay in bounds
if(moveToNumber >= max || moveToNumber < 0) {
[self.currentField resignFirstResponder];
return;
}
// move on
UITextField *next = [self.fields objectAtIndex:moveToNumber];
[next becomeFirstResponder];
}
- (void)prevClicked:(id)sender
{
[self moveResponderByStep:-1];
}
- (void)nextClicked:(id)sender
{
[self moveResponderByStep:1];
}
Thank you!
Try checking first to see if the row is visible. Scroll the row to visible if it isn't. Then set the text field as first responder.