I would like to make popover view visible whenever user switches from landscape view to portrait view in UIsplitView of iPad. Although user can make it visible by clicking on bar button but I want this to be automated for portrait mode.
Inside " -(BOOL) shouldAutorotateToInterfaceOrientation" method, check for the device orientation.If it is portrait, then Present the popover as you do for making it visible when user clicks bar button.
All the best.
UISplitViewController sends messages to his delegate (UISplitViewControllerDelegate). You can implement this delegate methods to show the popover. You can do something like this in your "detail controller" code:
#pragma mark -
#pragma mark UISplitViewControllerDelegate implementation
- (void)splitViewController:(UISplitViewController*)svc
willHideViewController:(UIViewController *)aViewController
withBarButtonItem:(UIBarButtonItem*)barButtonItem
forPopoverController:(UIPopoverController*)pc
{
[barButtonItem setTitle:#"Your 'popover button' title"];
self.navigationItem.leftBarButtonItem = barButtonItem;
}
- (void)splitViewController:(UISplitViewController*)svc
willShowViewController:(UIViewController *)aViewController
invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
self.navigationItem.leftBarButtonItem = nil;
}
The accepted answer (using shouldAutorotateToInterfaceOrientation) doesn't work for me. It either has rotation artifacts (in the 4.2 and 5.0 iPad simulators) or only shows at startup and never again in subsequent rotations (the 4.3 simulator). What I did instead was to create a little helper function:
- (void)showPopoverInPortrait {
if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortrait) {
[self.masterPopoverController presentPopoverFromBarButtonItem:self.navigationItem.leftBarButtonItem
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
}
and call this within - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation and - (void)viewDidLoad to also handle on startup.
Related
I have to detect screen touches in VR mode, as that's what the button on a Cardboard produces. (I have other code to detect controller buttons.)
This code:
// mobile and Cardboard controls
AFRAME.scenes[0].addEventListener('touchstart', function(evt) {
// console.log('scene touchstart:', evt);
if (evt.target.classList.contains('a-enter-vr-button')) {
return;
}
if (!state.isFlying) {
AFRAME.scenes[0].emit('launch', evt);
} else {
AFRAME.scenes[0].emit('hover', evt);
}
});
fires when the screen is tapped, in Android Firefox in normal and VR mode (but VR mode is polyfilled). In Android Chrome, it fires in normal mode, but not VR mode (which appears to be native).
The same behavior occurs when I listen for mousedown, or add the listener to window, for either touchstart or mousedown.
So, what event on what element should I listen for, in native VR mode?
Add the event listener to the window or to the canvas (AFRAME.scenes[0].canvas).
window.addEventListener('click', function () { // ... } or
window.addEventListener('touchstart', ...)
VR Mode in Chrome had a virtual controller. My eventual solution was to write a component that detected both screen taps and controller buttons:
https://www.npmjs.com/package/aframe-button-controls
Some questions to the Force Touch Menu:
Now when I perform a Force Touch and press one of my menu Items, the whole InterfaceController, where my Menu is implemented is loading new.
Is this avoidable?
I've implemented a menu with 4 menuItems for my InterfaceController.
With one of this menuItems, I want to enable/disable the haptic Feedback of my Buttons.
My button methods are like this:
- (IBAction) but1Pressed {
[[WKInterfaceDevice currentDevice] playHaptic:WKHapticType.Click];
// Do something
}
How can I disable the TapticEngine, if the user disables it ind the ForceTouchMenu?
No, as by today that's not possible.
If I understand you properly, you need a BOOL which defines whether the app should perform haptic feedback when a button in your interface controller is being pressed.
To realise that, implement the following:
BOOL shouldGiveTapticFeedback = YES
Then you need a method to change this BOOL when the corresponding menu item is being pressed:
- (IBAction) tapticFeedbackChangeButtonPressed {
//change BOOL value
shouldGiveTapticFeedback = !shouldGiveTapticFeedback
}
Finally, you need to check whether the taptic feedback should be played, when a button in your interface controller is being pressed:
- (IBAction) interfaceButtonPressed {
if(shouldGiveTapticFeedback) {
//play sound
[[WKInterfaceDevice currentDevice] playHaptic:WKHapticType.Click];
}
}
No, that's not possible either.
in my app i call a UIView and that UIView is like a settings screen in my app and i have buttons in the UIView and my question is how do i add actions to the buttons iv added to the UIViews subview? thanks,
Assuming you're writing code in a view controller for your settings UIView, the UIView is properly bound to the view property of your controller, and you have referenced one of the buttons with a variable button, here is what you would write:
- (void)viewDidLoad {
[super viewDidLoad];
[button addTarget:self
action:#selector(buttonPressed)
forControlEvents:UIControlEventTouchUpInside];
}
- (void)buttonPressed
{
// do things here in response to the button being pressed
}
Another way to write that method is passing in a pointer to the button which was actually pressed, like so:
- (void)viewDidLoad {
[super viewDidLoad];
[button addTarget:self
action:#selector(buttonPressed:) // note the extra colon here
forControlEvents:UIControlEventTouchUpInside];
}
- (void)buttonPressed:(id)sender
{
UIButton *buttonWhichWasPressed = (UIButton *)sender;
// now you can do things like hide the button, change its text, etc.
}
Rather than calling addTarget:action:forControlEvents:, though, in Interface Builder (you should be doing this) after defining the buttonPressed or buttonPressed: method above, in the .xib file with the button go to the second tab in the Inspector after clicking on the Button (it should say Button Connections), and click-drag the Touch Up Inside event to File's Owner, and select "buttonPressed" from the list.
I have created a split view application that begins with a modal view splash page. The problem is that the modal view always launches in portrait mode, even if the ipad is in landscape. If I rotate the ipad a couple of times, it rotates appropriately. I have set UIInterfaceOrientation in my Info.plist, but it doesn't have any impace.
in didFinishLaunchingWithOptions, I am using the following code
...
[self.window addSubview:splitViewController.view];
SplashViewController *modalView = [[SplashViewController alloc] intiWithNibName:nil bundle:nil];
modalView.modalPresentationStyle = UIModalPresentationFullScreen;
[splitViewController presentModalViewController:modalView animated:YES];
...
Any suggestions on how I can ensure the modal view launches in landscape?
I think this is the better way to do it:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation==UIInterfaceOrientationLandscapeRight) {
return YES;
}
return NO;
}
I had a similar problem when using Matt Gemmell's MGSplitViewController. In my case, by trying to open a modal view controller in FormSheet mode from inside the detail view controller (that is the "right" pane in the UISplitViewController standard), my modal view was forcing interface rotation to portrait.
I found the solution by overriding the modal view controller -> shouldAutorotateToInterfaceOrientation: and letting him returning a NO:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
return NO;
}
In this way when the modal is going to be presented, for some reason the OS tries to force it to portrait. By answering NO the view is no more rotated and everything works fine.
In the file from which you launch the modal view, you will want to change/override the following function. You can simply copy and paste the following code and you should be able to launch the modal view in portrait landscape mode:
- (BOOL)shouldAutoRotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
Good luck.
EDIT: I said portrait mode instead of what I meant: landscape mode.
I have a tab bar application that contains navigation views in 2 of its tabs. I would like 1 view in the 1 navigation controller to allow landscape view but because of the nav bar in tab bar limitation I now have to allow landscape views for every single view in my app to make the tilt messages get passed to my app which I don't want.
I thought perhaps, on the views which shouldn't go to landscape, that there might be ways to either:
prevent the view change e.g. calling setOrientation:UIDeviceOrientationPortrait whenever the device goes landscape
or
giving the illusion that the view doesn't change e.g. presenting a modal portrait view over the rotated view
Anybody have any ideas or experience that they care to share? What is the best approach here? (I don't want to now have to design a landscape view for every view just to so that I can display a portrait & landscape view for 1 view)
I had to deal with the same problem recently and my solution is as follows:
within the UIViewController of the View that you want to be able to rotate add a Notification Handler for the UIDeviceOrientationDidChangeNotification
-(void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didRotateFromInterfaceOrientation)
name:#"UIDeviceOrientationDidChangeNotification" object:nil];
}
then of course you need to implement your didRotateFromInterfaceOrientation Method.
within that Method you can get the current orientation using
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
what I did next was evaluation the view i want to display, based on the orientation
switch (orientation) {
case UIDeviceOrientationLandscapeLeft:
NSLog(#"UIDeviceOrientationLandscapeLeft");
[self presentModalViewController:LandscapeView animated:YES];
break;
case UIDeviceOrientationLandscapeRight:
NSLog(#"UIDeviceOrientationLandscapeRight");
[self presentModalViewController:LandscapeView animated:YES];
break;
case UIDeviceOrientationPortraitUpsideDown:
NSLog(#"UIDeviceOrientationPortraitUpsideDown");
[LandScapeview dismissModalViewControllerAnimated:YES];
break;
case UIDeviceOrientationPortrait:
NSLog(#"UIDeviceOrientationPortrait");
[LandscapeView dismissModalViewControllerAnimated:YES];
break;
case UIDeviceOrientationFaceUp:
NSLog(#"UIDeviceOrientationFaceUp");
break;
case UIDeviceOrientationFaceDown:
NSLog(#"UIDeviceOrientationFaceDown");
break;
default:
break;
}
}
I hope i could help a bit.