Set voiceover's focus on a specific table cell in uitableview (UIAccessibility) - iphone

I have a UITableView that I have scroll to the bottom as soon as the user adds another element/table cell to it. For the screen this works fine, because the user can see the cell they just added at the bottom of the table. But when running my app using VoiceOver, the first UITableCell to get focused and read is the top cell that's visible on the screen.
I want to set it so that the cell that gets focused and then read as soon as this UITableView appears is the very last cell in the table. How do I do this? It seems like it would be very simple but I can't figure it out.
Here's what I tried so far (in cellForRowAtIndexPath):
if (cellJustAdded && indexPath.row == [array count]-1) {
cell.accessibilityElementIsFocused = YES; //obviously this does not work
}
but I don't think you can use accessibilityElementIsFocused like that.

When you want VoiceOver to select a certain element you can post an accessibility notification using UIAccessibilityPostNotification( ... );.
Depending on if it's a major (complete screen) change or a minor (layout only) change you should post either
UIAccessibilityScreenChangedNotification (complete change)
UIAccessibilityLayoutChangedNotification (small change)
In both cases the optional argument is the element that VoiceOver should move to.
So after having added the new cell to your table view you would call
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification,
yourNewCellThatShouldHaveFocus);

Related

Display UITableView's section title when index is touched

I'm writing a dictionary app to study iOS and I've implemented a UITableView with the alphabet as section titles and an index of all the letters on the right side. It works perfectly, but is it possible for me to display the selected index in a box at the center of the screen? I'm looking at the UITableViewDelegate reference but can't see any methods I might override. Help?
You'd have to manually create a UIView that you put above the UITableView which then shows the letter or whatever you want to present. Make sure not to add it to the table view itself as it's a UIScrollView subclass and your view would be affected by its contentOffset.
When the user presses one index or moves his finger above it, this callback gets called:
-tableView:sectionForSectionIndexTitle:title atIndex:
Use it to change your view's contents and make it visible and set a timer for it to fade out again.
You have to create custom view that display when you click on the cell and in that view you can add Label to show the alphabet which you have selected.
And yes also if you want to display it on center of your screen than give its X and Y coordinates value according to it.hope it helps...

Group table view with multiple text fields

I have a group table view with 10 sections, each section has one cell, and each cell has a text field inside.
When user tap on a text field I scroll its parent cell to bottom, so that it will be exactly above the keyboard.
Every text field has a "Next" return key, so when user tap it the next text field (in the cell below) should be first responder.
The problem is:
Suppose user tap on a text field of cell at index 5, this will make the keyboard pop up and the tableview will scroll so this cell will be right above the keyboard.
Now user press the next button..
What I want to happen is to make the text field of cell at index 6 become the first responder.
But how do I get this text field??
If I try to get the cell with cellForRowAtIndexPath I'll get nil, because the cell is invisible..
Two solutions come to mind:
1) you don't have many cells, so don't recycle them, create them when you startup and put them in an array where you can easily get them, Then, when the tablview asks for cells, you pull them out of your array.
When you want to go to next, you simultaneously tell the tableview to scroll to such and such a location or cell, and you pull the cell out of the array, add it to your view with some offscreen frame so it cannot be seen, and make the textField the first responder (to keep the keyboard up). when the tableView asks for the cell, you MAY need to reset the frame, or both reset the frame and remove it from the view. If you find you need to do this you MAY need to make it the first responder again soon (dispatch a block to the main queue so that the text field never resigns first responder.
2) Similarly, when you want to make a cell's textField the first responder, and its contained in the visible cells, then you can just scroll and make it the first responder. If its not in the visibleCells, create a cell, add it to the view as above, do the first responder stuff as above, and when you are asked for THAT cell's index, supply that cell, possibly resetting the frame.
I've used offscreen textFields to play tricks with the keyboard (to keep it up, to get it up, etc - so I know that works). What's less certain to me are the tricks with the textField being in the view or not.
This makes me think of a 3rd way. You put a UITextField offscreen in the view. When you want to switch, and the cell is not yet visible (that is, created), you tell the offscreen textField to be firstReponder, then track the tableView scrolling, and when it ends the textField you WANT s first responder is now visible, so you can transfer (ie set) firstResponder on it, keeping the keyboard up.
I do not know how you create your rows but you need to consider, that UITableView recycles the cells. That means that the text field could be theoretically the same as before, just the content changes.
So all you need to do is make sure you know the textfield that is positioned right above the keyboard. I would not be surprised if this will be created when the view enters and never actually changes.
Again, the table recycles the cells and their content holders only filling in the corresponding data for the row as you provide it.
If you post your code that creates and recycles the cells I could be more specific.

image is reverting to original when scrolling uitableview

I have a button inside each cell. When it's pressed, the image is changed (basically a checkbox) to denote a selection. When you scroll to the bottom ... then scroll back up to the top. The image is reverted to the original image.
This question is pretty similar to this:
Preserve Cell Image After Scrolling UITableView
And others. But, I can't seem to find a good answer. I understand that's it's reverting back to how the uitableview is setup when the cell goes off the screen. But, how do I save the changed image to the uitableview so when it scrolls it doesn't revert to the original?
Thanks in advance! =)
It's changing back because cells are reused. When your cell is going off the screen it is taken out of the view and put back into the reuse pool. Then you're getting it out of the queue again in cellForRowAtIndexPath and setting it back up as the default.
The question you linked to is exactly what you should follow. You should store the state of your cell in your view controller and then when you set it up again in cellForRowAtIndexPath you should load that state and set up the cell appropriately.
One simple way for your method would be to have an NSArray which you set up to be the same size as the number of rows in your table and then in that just store an NSNumber for each row which contains a boolean value on or off for your selection state. When the user toggles, toggle the value in the array and then in cellForRowAtIndexPath read that value and set it up appropriately.
I'm assuming the checkbox in your table view cell is changing state to a selected state because a user selected it. You shouldn't use UI elements to maintain the state of your app. That is, when the user taps the checkbox, you should use that event to somehow reflect that state change in a data object in your app. Then, when that cell needs to be displayed again, you configure it with the state you previously saved. This allows for things like cell reuse, and view unloading and is all-around a good habit.

Trying to make a Custom UITableViewCell with a UITextField becomeFirstResponder when Editing

I have a UITableViewController with custom UITableViewCells that contain a UITextField. When switching the table view into edit mode, I add a new cell to the bottom of the table and would like to make this cell becomeFirstResponder. My tableView:cellForRowAtIndexPath: method checks for this bottom cell, so I just added the line:
[cell.theTextField becomeFirstResponder];
Which I believed should work. However, when the table view is first displayed, it does not seem to be working. BUT if I select the cell (making it the first responder), then go out of edit mode (causing a resignFirstResponder within my code), I can then go back into edit mode and magically it becomes the first responder as I would expect!
Note that even if I end editing mode with a different cell selected (they all have text fields) and go out of edit mode, then back in, it still works, as long as at some point I had made the last cell becomeFirstResponder (by selecting it).
So, my guess is that when it first becomes the first responder, there is something getting set either in the table view or some place else that wasn't originally set, and from then on it makes this work.
Anyone have any ideas as to what may be going on here?
The first becomeFirstResponder call fails because the cell doesn't have a superview yet. The table view adds the cell as its subview after you return it from tableView:cellForRowAtIndexPath:. I suggest you make this call somewhere else. If you already have a custom UITableViewCell subclass, you could implement didMoveToWindow: and call [self becomeFirstResponder] there.

How to use first responder to keep only one cell selected at the maximum in a view with multiple table views?

I have a scrollview which has several table views as sub views...
say that I have selected a cell in one of the sub views. Now when I select a cell from another view, the cell I selected previously should not be highlighted.
How do I do this? I know I can do this using the first responder, but I am not sure how to do it.
Would anyone be able to help me out in this?
Thanks
From the apple interface guidlines:
Always provide feedback when users select a list item. Users expect a table row to highlight briefly when they tap a selectable item in it. After tapping, users expect an immediate action to occur: Either a new view appears or the row displays a checkmark to indicate that the item has been selected or enabled.
In rare cases, a row might remain highlighted when secondary details or controls related to the row item are displayed in the same screen. However, this is not encouraged because it is difficult to display simultaneously a list of choices, a selected item, and related details or controls without creating an uncomfortably crowded layout.
I don't think apple will approve an app that leaves a row highlighted (I had an app reject for that very reason). You should perform an action and then immediately unhighlight it. In some rare cases you can leave it highlighted while showing a related view.
However, if you store the current cell you have selected, you can call -deselectRowAtIndexPath:animated: on the tableview to deselect a row.