UIButton subview in UICollectionViewCell not changing control state - ios

I have a UICollectionView where each UICollectionViewCell has a UIButton as a subview. The UIButtons respond to taps no problem (their targets get fired), but the button itself does not change to the selected state (no change in look and feel of the button). I have a hunch it's because of the UICollectionViewCell not properly forwarding its touch events to the button, but I'm not sure. Even if that's so, how do I set things up so that the button's state changes properly in this scenario?

The UIScrollview (and thus UICollectionView too) has a property called delaysContentTouches, by default it is set to YES, change this to NO and your button should highlight like it is supposed to.

If i may suggest an alternative, the UICollectionView has an awesome delegate method called
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { }
which could handle the click to that cell... if you are looking for specific events to happen like seeing an image change to the state of the button, you could hard code that in... when they press the button do one thing, when they release the button do another thing....
according to the documentation as well
UIControlStateSelected
Selected state of a control. For many controls, this state has no effect on behavior or appearance. But other subclasses (for example, the UISegmentedControl class) may have different appearance depending on their selected state. You can retrieve and set this value through the selected property.
in laymens terms.. for a UIButton the "Selected State" does nothing...
if the the button is suppose to dim when it's clicked and it's not doing that, then you may have to do that programmatically if, but i'm not exactly sure what you are trying to do...
the dimming feature is with in the highlighted state
UIControlStateHighlighted
Highlighted state of a control. A control enters this state when a touch enters and exits during tracking and when there is a touch up event. You can retrieve and set this value through the highlighted property.
in laymens terms, you touch the button it's highlighted
to see if the button is changing states properly you can do something like this
[button addTarget:self action:#selector(functionToCall:) forControlEvents:UIControlEventAllTouchEvents];
NSLog(#"Selected: %i", button.selected);
NSLog(#"Highlighted: %i", button.highlighted);
NSLog(#"Normal State or not: %i", button.state);
the "functionToCall will be called when any type of touch even happens to the button and with in that function you could have those 3 NSLogs which will print to your console the different UIControlState values, this will show that the button is working properly and show that it may be a UIViewCollection error, if it's the UICollectionView... then you will have to programmatically dim the button :3
hope this helps !

Related

iOS - change view (UICollectionViewCell) to disabled status

I have a UICollectionView and I want some of my cells to be disabled. That means I want the cell to look a bit greyer (to have a disabled feeling), and I want the user to not be able to click on the cell.
I know I can use the alpha parameter and set it to something like 0.7, but this gets disabled while moving the cells around, and also it doesn't look grey enough. So I'm looking for another option to do it.
For controlling the tapping on a cell, I know I can use collectionView:didSelectItemAtIndexPath: and check for the indexPath. But I was wondering if there's another option for disabling a cell, like there is for disabling a UIButton: myButton.enabled = NO.
You can always set userInteractionEnabled to NO for the UICollectionViewCell and any taps inside it will be ignored.
Your problem with the alpha sound like you need to do some more work in prepareForReuse, or implement prepareForReuse in your custom cell class if you have not already done so.

Combine UISwitch and UITableViewCell for VoiceOver interaction

In Calendar, when you create a new event, if you tap on the All Day cell with VoiceOver enabled, Siri says "All Day switch button on/off, double tap to change setting". And indeed double tapping will toggle the switch. Also, it's not possible to tap on just the toggle switch itself - you have to interact with the cell itself to toggle the switch, the switch itself is not an accessible element.
In my app I have the exact same setup with a label and a switch. But when I tap the cell with VoiceOver enabled it only reads the label so the blind user has no idea there's a toggle switch in that cell. If they tap the switch itself then they can interact with it, so it's the opposite of the setup in the Calendar app.
How can I obtain the same behavior that Apple implemented? I need some way to combine the switch into the cell so VoiceOver reads both upon highlighting the cell, then when they double tap it should toggle the switch, and I'm not sure how that setup can be accomplished. Thanks!
To implement the desired behavior, instead of placing the UISwitch in the contentView of the cell, add it as the accessoryView programmatically. Then the cell and switch will behave exactly as expected when using VoiceOver, exactly as it does in Calendar.
You should be able to set a custom accessibility description on the cell using
cell.accessibilityLabel = #"Double tap to toggle setting";
You can set up custom gestures for when VoiceOver is running according to this answer:
https://stackoverflow.com/a/12337128/567511
But here you would not need custom gestures, instead your didSelectRowAtIndexPath would flip the switch only when UIAccessibilityIsVoiceOverRunning is true.
I would like to elaborate on the answer of Joey, and clarify how a solution to this question can be achieved in code.
In the tableView:cellForRowAtIndexPath:, create a custom UISwitch view and append it to the accessoryView of the cell. This could look something like the following.
UISwitch *switchView = [[UISwitch alloc] initWithFrame:CGRectZero];
[switchView setOn:NO];
[switchView addTarget:self action:#selector(selector:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = switchView;
return cell;
The cell will now behave like any native iOS switch known from e.g. Settings or Calendar. Double tapping on the cell with VoiceOver enabled, will now toggle the UISwitch (on/off), and VoiceOver will automatically notify the user about the state of the switch, together with an accessibility hint.

Accessibility for UINavigationController and UINavigationItem

I'm improving the accessibilty of my iOS project and am using an UINavigationController.
My UINavigationItem has two buttons, the left one is "Cancel".
By default, the cancel buttons gets selected when showing the view.
So the first thing a user hears is "Cancel".
What I really want is that the title should be selected and spoken, and the
cancel button should not be selected.
Questions:
Is this how it should be, and what could be the reason for this?
Has anyone successfully unselected the button and instead selected the title?
Thanks,
Claes
From Apple's UIAccessibility Guide:
UIAccessibilityLayoutChangedNotification - Posted by an application when the layout of a screen changes, such as when an element appears or disappears. This notification includes a parameter, which is either an NSString object that VoiceOver speaks or an accessibility element that VoiceOver moves to.
So you can do something like this:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification,title);
}
You should replace "title" in the above code with the actual Accessibility element you want to be selected and spoken.
You can also use UIAccessibilityScreenChanged instead of UIAccessibilityLayoutChanged "when a new view appears that comprises a major portion of the screen".

Creating a custom toggle with UIButton in Interface Builder

Is this possible? It seems shoddy for it not to be.
I'm trying to create a toggle button (not a UISwitch) in IB. For example a mute button, when muted would have some indication that sound is disabled, when you hit it, that indicator disappears (but still the same underlying graphic), and toggles between these states each time it is pressed.
This functionality can be achieved using the selected property, however you can't change the Selected AND Highlighted property in IB like you can in code, so whenever the button is pressed, no matter the state, the highlighted image is the same, which looks terrible and glitchy.
Is there a way to fix this with just IB, or do I have to make a custom class to avoid manually loading in all these buttons?
Have you thought about subclassing UIButton to add in the things you need?

ios navigation buttons

I'm doing a custom nav in ios for the first time. I have six buttons laid out in a row. When I tap the button, I want the image to change. However, the button is not togglable. The only way a button can be unselected is if another button is touched. Only one button can be active at any given time.
My idea:
use UIButtons
change UIButton image on touch
keep track of the active button inside the navigation class
when an inactive button is touched, make the currently active button inactive and turn the touched button to active
I want the end product to work like a custom TabBarController, but without switching layouts. I just want to edit the content in the current ViewController.
Is there a better way to do this?
You could just use the UISegmentedControl, which has that functionality already. If you need to significantly customise the look and feel though, your UIButton solution sounds fine.
I setup the UIButtons in the Interface Builder like so:
Default with unselected background image
Disabled with selected background image
On touch, a button is self.enabled = NO which makes the UIButtons look change. However, the button goes dim, so I also implemented self. adjustsImageWhenDisabled = NO.
This way a button can't be re-selected once it's "active".

Resources