I have a UITableView that I build in loadView. One of the things I do in loadView is create a UIView to act as the table header and stuff a UIImageView into it. The image view contains an image that is a stylized title, so I want to add an accessibility label for VoiceOver users. However, I can't get VoiceOver to "focus" on the image in order to read the label, and the Accessibility Inspector doesn't respond to clicking on the image in the simulator. My (abbreviated) code follows:
... in -loadView ...
// Make header view
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(...)];
UIImageView *titleImageView = [[UIImageView alloc] initWithImage:[self titleImage]];
titleImageView.accessibilityLabel = [self accessibilityLabelForTitleImage];
[headerView addSubview:titleImageView];
// Make table view
self.tableView = [[UITableView alloc] initWithFrame:CGRect(...) style:UITableViewStylePlain];
self.tableView.tableHeaderView = headerView;
... code continues ...
I've stepped through in gdb and accessibilityLabelForTitleImage returns a string. po [titleImageView accessibilityLabel] prints out the correct string, but I'm still unable to focus on the image view. Note that the views themselves appear and respond as appropriate.
Am I missing something? Is there a way to force VoiceOver to acknowledge an image view?
In Voice-Over , in order to make an element accessible :-
you have to set setIsAccessibilityElement property as true which i don't find in your code.
The other important point is that to make child elements (subviews) to be accessible , you have to seperately make them accessible while the parent should not be accessible(you have to specify this also).
Implement the UIAccessibilityContainer Protocol in your custom - cell.
It will be a big story if i go on .Please refer this Accessibility voice over by apple.
Hope this helps.
I used KIF for testing my IOS app. In my tableview, I assigned value to tableview.accesssibilityIdentifier instead of tableview.accessibilityLabel. It worked for me. Wanna give it a try?
Voice-Over sometimes can get nasty and just by setting isAccessibilityElement might not work.
In this case try setting accessibilityElements on the parent view and include the child views in the array, like this:
parentView.accessibilityElements = [childView1, childView1, childView1]
Doing it also ensures that the accessibility items are being read in the order you want.
Related
I'm wondering if anyone else has the issue that MKMapView (Or maybe it relates to many other Views?) does a strange thing where it defaults to 1000x1000 in size the first time I load a screen. When I segue to another screen, and segue back to the map screen, then it actually followed up all my constraints.
This didn't happen with Xcode7 and I wonder if someone knows there's a known bug in Xcode8 or something?
MapKitView get loaded programmatically and is added as a subview within my View that has the constraints.
MKMapView *mapkitView = [[MKMapView alloc] initWithFrame:self.aConstrainedView.frame];
[self.mapkitView setDelegate:self];
[self.mapkitView setShowsUserLocation:YES];
[self.mapkitView setRotateEnabled:NO];
[self.aConstrainedView addSubview:self.mapkitView];
Could this be related to Autoresizing issue in Xcode 8 ?
Your initialiser should use the bounds of its superview, not the frame:
MKMapView *mapkitView = [[MKMapView alloc] initWithFrame:self.aConstrainedView.bounds];
Set a breakpoint on this line and in the debugger use:
(lldb) po self.aConstrainedView.bounds
to ensure the width and height are correct. If you're adding the map view in viewDidLoad, then that's too early. You should override:
- (void)viewDidLayoutSubviews {
dispatch_once(
// Add map view here
);
}
and add your code in there, as that gets called after your subviews have all been laid out according to your constraints.
I'd like to use this same solution with my UIView to get the same result.
I have a UIView with a UIScrollView. These are embedded in a UINavigationController.
A customer adds an item to their basket and I would like to give them a confirmation message. Right now a little basket UIBarButtonItem updates a title within to show the number of items. This is fine but not every user/customer will notice this.
I don't really like the style of a UIAlertView for this situation. So I'm going to add my own UIView and style it how I want to.
I'm trying to figure out how to get the UIView to show up in the center of the window. Whether the customer is using an iPhone4 or iPhone5.
UIView code:
UIView *confirmationPopup = [[UIView alloc] initWithFrame:CGRectMake(10, 200, 300, 100)];
[confirmationPopup setBackgroundColor:[UIColor redColor]];
// confirmationPopup.center = [confirmationPopup.superview convertPoint:confirmationPopup.superview.center fromView:confirmationPopup.superview.superview];
[[[self navigationController] view] addSubview:confirmationPopup];
The popup view is centered horizontally automatically but not vertically. I've tried to play around with the line you can see I've commented out but it doesn't center the UIView in the center of the window. It appears to be centering it inside the NavBar
Would appreciate some solutions.
Don't hard-code; use auto layout. You might be helped by my custom class for this purpose, an imitation alert view substitute that you can configure however you like. It takes advantage of iOS 7 custom presentation view transitions. (Of course in iOS 8 there will be even more support for this kind of thing, i.e. UIPresentationController.)
I am developing an app which allows you to select photos and place them into different positions. The workflow is basically:
Tap an area of the screen
UIImagePickerController displays
Select a photo
Photo displays in the tapped area of the screen
I would like it so that if the user goes through this workflow for a second time, the UIImagePickerController when displayed will be showing the same album, and position within that album, that the user was last at.
I've tried saving a reference to the UIImagePickerController, as well as the UIPopoverController, so that they are created only once. However, every time I present the popover containing the UIImagePickerController, it is back at the main photos menu (eg. Camera Roll, Photo Library, My Photo Stream).
Any ideas for how to achieve what I'm after?
You can use ALAssetsLibrary . But this will cost you more effort. First time use – enumerateGroupsWithTypes:usingBlock:failureBlock: to list all album and remember user's choice. And at second time. Just use that album:ALAssetsGroup's – enumerateAssetsUsingBlock: to list all the images and videos. Apple has a few demo you can have a look PhotosByLocation MyImagePicker
keep a UIImagePickerController obj in .h class (for example imagePicker)
alloc the obj once (for example in viewDidLoad)
imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self.view addSubview:imagePicker.view];
imagePicker.view.hidden = YES;
imagePicker.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
imagePicker.view.bounds = CGRectMake(0,20,self.view.frame.size.width, self.view.frame.size.height);
In didFinishPickingMediaWithInfo
if([[info valueForKey:UIImagePickerControllerMediaType] isEqualToString:#"public.image"]){
imagePicker.view.hidden = YES;
}
When you want to show the imagePickerView just do
imagePicker.view.hidden = NO;
Just to point you to right direction. You can use asset library to show the images as a picker. You can use the apple sample code MyImagePicker. The method [[assetsLibrary] enumerateGroupsWithTypes:ALAssetsGroupAlbum usingBlock:^(ALAssetsGroup *group, BOOL *stop) can be used for photo album. Using the asset library you can check which image was selected last and then use the method,
- (void)enumerateAssetsAtIndexes:(NSIndexSet *)indexSet options:(NSEnumerationOptions)options usingBlock:(ALAssetsGroupEnumerationResultsBlock)enumerationBlock;
You can use this method next time to enumerate which image onwards you want to enumerate. This method can accept an indexSet as [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(index, count)] which should help to indicate the last selected image.
To know more about how to use asset library check this.
It should be possible to reach into the resulting UITableView and then find its content offset. You can do this by searching the subviews of the UIImagePickerController's view property for a table view.
for (UIView *view in controller.view) {
if ([view isKindOfClass:[UITableView class]]) {
contentOffset = [(UITableView *)view contentOffset];
}
}
When you represent the view controller, you will want to restore the content offset in a similar fashion.
Note, I haven't actually tested to see the view hierarchy of the UIImagePickerController. Verify its structure by printing its subviews. There is also no guarantee that the structure will stay the same, since you are diving into the private implementation (though it's important to note you are not actually using any private APIs so this is okay).
Use AlAssetsLibrary. It control the image & video capture under the application. there a demo on apple.
https://developer.apple.com/library/ios/#documentation/AssetsLibrary/Reference/ALAssetsLibrary_Class/Reference/Reference.html
look for this or
if you want to make a cutomize album for the image and video here a great example.
https://github.com/Kjuly/ALAssetsLibrary-CustomPhotoAlbum
I'm working on some drawing code. I have that portion working great.
I want to draw over an image, but I want to still be able to see the detail of the image, the black lines, etc.
What I am working on is making a transparent UIImageView that holds the image.
I'm not sure how to get this set up properly though.
Should this be added above the other UIImageView that I color on or below it?
Here's what I have so far:
- (void)viewDidLoad
{
[super viewDidLoad];
topImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 46, 320, 370)];
[topImageView setImage:[UIImage imageNamed:#"imagesmall.png"]];
topImageView.alpha = 1.0;
topImageView.layer.opacity = 1.0;
topImageView.layer.opaque = NO;
[self.view addSubview:topImageView];
[topImageView release];
}
Thoughts anyone?
Yes, you can draw views over other views. They are drawn in the order that they're added as subviews, unless you reorder them after that.
You may need to set the opaque property for some views (this is distinct from and overrides their layer opacity), and set their backgroundColor to nil. UIImageView seems to be transparent by default, as long as its image is; some other UIView subclasses are not.
So, just what is your overlay going to be? If you just need to display one image over another, what you have here seems to work already. If you need to draw some lines programmatically, you'll need to do this:
Create a subclass of UIView.
Implement its drawRect method to display the content you need.
When you add your custom view on top of the background image, make sure it is not opaque and has no backgroundColor.
A common problem here is to find that your foreground is working, but the background isn't being loaded properly. To make sure the background is there, set the alpha of the foreground view to 0.5. You won't want to do that in production, but it will allow you to verify that both views exist.
In my application, when the user clicks an infoButton, it should add another view to the screen at a specific location. I'm trying to achieve this behavior with the following method:
- (IBAction)showInfo1:(id)sender
{
UIView *myView1 = [[UIView alloc] initWithFrame:CGRectMake(25,25,50,20)];
[self.view addSubview:myView1];
}
(I declared everything in the header file of my class.)
When I run the code and press the button, nothing appears to happen (I don't see the new view).
I also noticed that XCode is displaying the following warning:
Local declaration of 'myView1' hides instance variable.
Does anyone have any ideas?
How do you know nothing changes?
It looks like myView1 doesn't actually contain anything. Try setting the background color of myView1
- (IBAction) showInfo1: (id) sender
{
UIView *myView1 = [[UIView alloc] initWithFrame:CGRectMake(25,25,50,20)];
myView1.backgroundColor = [UIColor redColor];
[self.view addSubview: myView1];
}
To open it at a specific point you need to change the parameters in CGRectMake() for example
to open it at the very top left with a width of 50 and height of 20 you would do:
CGRectMake(0, 0, 50, 20)
"Local declaration of 'myView1' hides instance variable." message appears because you have declared in your class some property with the same name (even if the type is different).
If you put UIView *myView1 in your class definition, your method would look like
- (IBAction)showInfo1:(id)sender{
myView1 = [[UIView alloc] initWithFrame:CGRectMake(25,25,50,20)];
[self.view addSubview:myView1];
}
Here comes more considerations: you must to release myView1 when you stop using it, avoid to be placed more than once, etc. but here we have the basic idea.
Finally, maybe your view is already added, but 'cause it doesn't contains anything yet, you don't notice it. Also you would like to check UIViewController to see if works better for you.