How can you reorder the way VoiceOver reads UIAccessibilityElements? - objective-c

There are 2 answers on SO concerning this, but neither seem to work any longer.
I have a custom UITableViewCell. There are various labels laid out on this cell. VoiceOver for Accessibility reads things Left to Right, Top to Bottom.
This is an issue for the layout of my cell. I need things to be read in a specific order.
However, I don't seem to be able to change the order in which VoiceOver reads things by default.
I've tried self.accessibilityElements = #[self.view5, self.view1, self.view9] for example, but this does not change order.

You can set the cell's accessibility label with the string that you create combining all cell's subviews, for example if you have lbl1, lbl2, lbl3, btn1:
NSString *cellAccessibilityString = [NSString stringWithFormat:#"%#,%#,%#,%#", _lbl3.text, _lbl2.text, _btn1.text, _lbl1.text];
[self setAccessibilityLabel:cellAccessibilityString];
Where "self" is the cell.

No, Voice over doesnt work like that. You cannot change the order of the accessibility elements. YOu can only skip some elements which are in the stack.
Let's say you have views 1 to 9 in a vertical layout
and you do this:
self.accessibilityElements = #[self.view5, self.view1, self.view9]
IT doesnt mean that accessibility will read view 5 first, and then view 1 and then view 9.
YOu should give the order like:
self.accessibilityElements = #[self.view1, self.view5, self.view9]
So that the voice over only reads them in the order 1,5,9, and it skips the remianing!!!!
Again the voice over reads in the order left to right and from top to bottom!!!
Think it like this: USe self.accessibilityElements only if you want to add/skip the accessibility for the elements in your view, but not for the accessibility order!!!

Related

NSTableRowView "Empty Rows"

I've overridden NSTableRowView, which so far is working a treat. The problem I'm facing is drawing the separator for the empty rows.
drawSeparatorInRect:dirtyRect
only seems to override the rows that have content, all the rest seems to be filled with system colours.
At the moment I have:
-(void)drawSeparatorInRect:(NSRect)dirtyRect
{
NSRect sepRect = self.bounds;
sepRect.origin.y = NSMaxY(sepRect) - 1;
sepRect.size.height = 1;
sepRect = NSIntersectionRect(sepRect, dirtyRect);
if (!NSIsEmptyRect(sepRect))
{
[[NSColor gridColor] set];
NSRectFill(sepRect);
}
}
Which, as I said works well. I originally picked this up from some apple sample.
When I change the separator color to "red", you can see what happens:
The bottom-half of the last populate row is filled, but none of the others there after are.
Has anyone got an idea what I'm missing?
Cheers,
A
There are only row views for rows which have content. Therefore, a custom row view can not affect the drawing of separators for rows past the end of your table's content.
To customize the drawing of those separators, you need to override -[NSTableView drawGridInClipRect:]. You compute the position of the separator for where rows past the end of the content would be and draw the same way as your custom row view does.
This is explained, with example code, in the video for WWDC 2011 Session 120 – View Based NSTableView Basic to Advanced. It's also demonstrated in Apple's HoverTableDemo sample project.

looping a sprite vertically objective C sprite builder

Note: for this I am using a program called spritebuilder, which allows me to create a game with less code than would normally be needed. If you know a solution that's just all code, then by all means feel free to share it :)
Also, for this question, I followed a tutorial at this link: Build Your Own Flappy Bird Clone. Just scroll down to the part that says: "Loop the Ground"
So here's my problem. Im currently working on a game, and I created a camera which scrolls vertically long with the character sprite i created, however i need a certain image to loop. When the image leaves the bottom part of the screen I would like it to loop around to the top of the screen, infinitely. For this i created two identical images (in this case its the bark of a tree). One will be on screen, while the other will be offscreen, so as the first image leaves the screen, the second will replace it (seamlessly). I created two objects for the images, and assigned them the name _ground1, and _ground2, and I also created an NSArray in which to store them in. (Please refer to the link above if it is somewhat confusing)
Here is the code that I have:
CCNode *_ground1;
CCNode *_ground2;
NSArray *_grounds;
for (CCNode *ground in _grounds) {
// get the world position of the ground
CGPoint groundWorldPosition = [_physicsNode convertToWorldSpace:ground.position];
// get the screen position of the ground
CGPoint groundScreenPosition = [self convertToNodeSpace:groundWorldPosition];
// if the left corner is one complete width off the screen, move it to the right
if (groundScreenPosition.y <(-1 * ground.contentSize.height)) {
ground.position = ccp(ground.position.x , ground.position.y + 2 * ground.contentSize.height);
}
For some reason when I try this, it doesnt seem to work. what happens is that, the camera will travel vertically as it is meant to do, but the images do not loop. Once the two images leave the bottom of the screen, no new images replace them.
i also done this project as above tutorials. it work fine but you have some mistake to set variable in spritebuilder. in your above code replce code as and try it. you only put less than may be it issue.
if (groundScreenPosition.y <=(-1 * ground.contentSize.height)) {
ground.position = ccp(ground.position.x , ground.position.y + 2 * ground.contentSize.height);
}
You are using CCNode objects as _ground1and _ground2.
CCNode objects usually do not have a contentSize, they will return 0 unless you explicitly set them inSpriteBuilder`.
Make sure that you are using CCSprite objects in SpriteBuilder and in your code.
Also, as a friendly hint you should also consider refactoring (renaming) your sprites with more meaningful names for your use case like _treeBark1 and treeBark2 for example.

Two NSTextFields with interdependent widths in autolayout

I’m trying to put together what seems to be a simple case of two NSTextFields with dynamic width and fixed spacing in between. I cannot figure out an effective way to do so though.
I’m looking to get something like this:
The blue boxes are the NSTextFields. When more text is entered into one, it should grow and thus make the other one shrink, maintaining the lead space, trailing space and the spacing in between the fields. The first one should take the priority if both of the fields have too much text. Each field will also clearly have a maximum and a minimum possible width it can reach.
How would I go around handling this, preferably utilising IB autolayout as much as possible?
It seems to me that all of constraints you mentioned directly translate into interface builder --
First view has width >= something.
First view has width <= something
Same for Second view.
Space between views is fixed.
Second view wants to be as small as possible (have its width at 0) but this has lower lower priority than the previous constraints and lower priority than inner content size constraints.
The code I had to add to my view controller, after applying the constraints as per the ilya’s answer:
In controlTextDidChange (_controlWidthConstraint refers to the fixed width constraint of the input; it’s probably 0 by default for the second input):
// Get the new width that fits
float oldWidth = textControl.frame.size.width;
[input sizeToFit];
float controlWidth = textControl.frame.size.width;
// Don’t let the sizeToFit method modify the frame though
NSRect controlRect = textControl.frame;
controlRect.size.width = oldWidth;
textControl.frame = controlRect;
_controlWidthConstraint.constant = controlWidth;
The key lies in invalidating the intrinsicContentSize for the text field when text is input.
You can check a sample project here, to get you on the right track.

auto adjusting the positions and height width of UILabel in iOS

I have designed my help page for my application,it contains some FAQs..so I have used UILabels for question and answer,I have adjusted,x,y,width and height exactly in the xib,leaving a gap between a question and answer and answer and next question.so totally I have some 10 question and answers,I have put them inside a scroll view.
But now, suppose the text changes dynamically, how can I adjust the positions and width and height,is a problem which I am not able to figure out, by using the below code,it adjusts the height and width of a particular label,if the text increases
NSString * test=#" It may come as a rude shock, but Facebook users should not feel surprised if tomorrow they come across their photos existing in the web world despite having deleted them personally long ago.";
m_testLabel.text = test;
m_testLabel.numberOfLines = 0; //will wrap text in new line
[m_testLabel sizeToFit];
but then, my next label will clash with it..is their any way so that all the labels get adjusted according if the width of any label increases or decreases?
Hope you all have understood my question..
Did you look into the below function, pass the font you have used and the size to which u want to constraint the label into.
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size

Cursor position in a UITextView

I am looking for a non private way to find the position of the Cursor or Caret (blinking bar) in a UITextView preferably as a CGPoint.
There may be a question like this already but it does not provide a definitive way for doing it.
And,
I do not mean the NSRange of the selected area.
Just got it in another thread:
Requires iOS 3.2 or later.
CGPoint cursorPosition = [textview caretRectForPosition:textview.selectedTextRange.start].origin;
Remember to check that selectedTextRange is not nil before calling this method. You should also use selectedTextRange.empty to check that it is the cursor position and not the beginning of a text range. So:
if (textview.selectedTextRange.empty) {
// get cursor position and do stuff ...
}
Pixel-Position of Cursor in UITextView
SWIFT 2.1 version:
let cursorPosition = infoTextView.caretRectForPosition( (infoTextView.selectedTextRange?.start)! ).origin
print("cursorPosition:\(cursorPosition)")
There is no such way. Full stop.
The only thing you could do to come close is to in parallel lay out the text using CoreText, there calcualte the text position from a point and apply that on the UITextView. This, however, works with non-0 selections only. In addition CoreText has a different text layout engine, that e.g. supports kerning, which UITextView doesn't. This may result in deviations of the rendered and laid out text and thus give sub-optimal results.
There is absolutely no way to position the caret. This task is even very though if you do use private API. It's just one of the many "just don't" in iOS.
Swift 4 version:
// lets be safe, thus if-let
if let selectedTextRange = textView.selectedTextRange {
let caretPositionRect = textView.caretRect(for: selectedTextRange.start)
let caretOrigin = caretPositionRect.origin
print(">>>>> position rect: \(caretPositionRect), origin: \(caretOrigin)")
}
We simply use textView.selectedTextRange to get selected text range and than textView.caretRect(for:) to get CGRect defining position of the caret.