I have a UIActionSheet that works just fine on the iPhone simulator. It is presented when the user touches a UIButton.
Using the iPad, I believe UIActionSheets are wrapped into a UIPopupController.
When I call the same code using the iPad simulator, I get a thin "line" displayed, which looks like a UIPopupController (you can see the small arrow that usually points to a control). None of the content can be seen.
What is the correct way to use a UIActionSheet using the iPad with MonoTouch? Here is a bit of sample code I have been testing with - creating the UIActionSheet:
var actionSheet = new UIActionSheet () { Style = UIActionSheetStyle.BlackTranslucent };
actionSheet.Frame = actionSheetFrame;
actionSheet.Clicked += (s, e) => { Console.WriteLine ("Clicked on item {0}", e.ButtonIndex); };
actionSheet.AddSubview (doneButton);
Then, I am showing the actionsheet by calling the following from a button:
btnSay.TouchUpInside += (sender, e) => {
actionSheet.ShowFrom(tmpBtn.Frame, tmpView, false);
};
I get something like the attached screenshot when using the iPad simulator.
For reference, here is what the UIActionSheet looks like when using the iPhone simulator.
Note: The project is a universal single-view MonoTouch c# project.
Any pointers or help would be much appreciated!
I faced this same problem with a recent app I released to the app store.
When you show a UIActionSheet on iPad, iOS wraps the UIActionSheet in a UIPopoverView.
I used the following code to detect whether this is an iPad, and if it is, adjust the frame of the popover view:
const int CHROMEWIDTHLEFT = 9;
const int CHROMEWIDTHRIGHT = 8;
const int MARGIN = 50;
UIActionSheet _actionSheet;
...
if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad) {
var popover = _actionSheet.Superview.Superview;
if (popover != null)
{
var x = _actionSheet.Frame.X + MARGIN;
var y = (UIScreen.MainScreen.ApplicationFrame.Height - _actionSheet.Frame.Height) / 2;
var width = _actionSheet.Frame.Width - (MARGIN * 2);
var height = _actionSheet.Frame.Height;
popover.Frame = new RectangleF (x, y, width, height);
_actionSheet.Frame = new RectangleF (x, y, width - (CHROMEWIDTHLEFT + CHROMEWIDTHRIGHT), height - (CHROMEWIDTHLEFT + CHROMEWIDTHRIGHT));
}
}
The example is based upon the Xamarin ActionSheet Date Picker here
I have put these up as a Gist (Normal and DatePicker)
Related
I have tried creating a game in unity and build it on ios on any apple devices there were no problem except on iphone x. Screenshot is below.enter image description here. It was covered by the iphone x notch and then when when the character is on the left or the right side it was cut it half.Is there any other solution or a plugin we can use to solve the issue ?. Is there a unity settins or xcode settings to that ? .Thank You
About the iPhone X notch, you can use this:
Screen.safeArea
It is a convenient way to determine the screen actual "Safe Area". Read more about it in this thread.
About the character cutting in half, this is probably something you need to take care of manually based on your game logic. By getting the Screen.width - you should be able to either adjust the Camera (zoom out) or limit the character movement in a way that it will not get past the screen edge.
For the iPhone X and other notched phones you can use the generic Screen.safeArea provided by Unity 2017.2.1+. Attach the script below to a full screen UI panel (Anchor 0,0 to 1,1; Pivot 0.5,0.5) and it will shape itself to the screen safe.
Also recommended to have your Canvas set to "Scale With Screen Size" and "Match (Width-Height)" = 0.5.
public class SafeArea : MonoBehaviour
{
RectTransform Panel;
Rect LastSafeArea = new Rect (0, 0, 0, 0);
void Awake ()
{
Panel = GetComponent<RectTransform> ();
Refresh ();
}
void Update ()
{
Refresh ();
}
void Refresh ()
{
Rect safeArea = GetSafeArea ();
if (safeArea != LastSafeArea)
ApplySafeArea (safeArea);
}
Rect GetSafeArea ()
{
return Screen.safeArea;
}
void ApplySafeArea (Rect r)
{
LastSafeArea = r;
Vector2 anchorMin = r.position;
Vector2 anchorMax = r.position + r.size;
anchorMin.x /= Screen.width;
anchorMin.y /= Screen.height;
anchorMax.x /= Screen.width;
anchorMax.y /= Screen.height;
Panel.anchorMin = anchorMin;
Panel.anchorMax = anchorMax;
}
}
For a more in depth breakdown, I've written a detailed article with screenshots here: https://connect.unity.com/p/updating-your-gui-for-the-iphone-x-and-other-notched-devices. Hope it helps!
Sorry for the late answer but I have adjusted the camera's viewport rectangle for iOS devices and it works correctly. Check if it works for your camera as well.
I have tried safeArea and other script based solutions which do not seem to work.
#if UNITY_IPHONE
mainCamera.rect = new Rect(0.06f, 0.06f, 0.88f, 1);
#endif
Prior to iOS 11, I was using this code inside a custom renderer for the TabPage to conditionally hide the TabBar in my app:
private void ToggleTabs(object sender, bool hideTabs)
{
TabBar.Hidden = hideTabs;
TabBar.Frame = TabBar.Hidden
? new CGRect(TabBar.Frame.X, TabBar.Frame.Y, TabBar.Frame.Width, 0)
: new CGRect(TabBar.Frame.X, TabBar.Frame.Y, TabBar.Frame.Width, tabBarHeight);
}
where tabBarHeight is calculated when the TabBar is constructed (it should always be 49 according to the docs, but I hate magic numbers).
The problem that I'm now running into is that even though I'm collapsing the frame, there is still a white rectangle left where the tab bar used to be. I have only noticed this behavior on devices running iOS 11 deployed from XCode 9.
I found some information about SafeAreaInsets that I thought may have been causing the problem, but 0 is always returned unless I'm running on an iPhone X, so that seems to have been a bust.
It looks like the iOS 11 SDK may be to blame, but I can't figure out the work around.
This worked for me:
TabBar.Hidden = tabBarHidden;
// The solution to the space left behind the invisible tab bar
if (tabBarHidden)
{
View.Subviews[1].Frame = new CoreGraphics.CGRect(View.Subviews[1].Frame.X, View.Subviews[1].Frame.Y,
View.Subviews[1].Frame.Width, 0);
View.Subviews[0].Frame = new CoreGraphics.CGRect(View.Subviews[0].Frame.X, View.Subviews[0].Frame.Y,
View.Subviews[0].Frame.Width, View.Subviews[0].Frame.Height + 49);
}
else
{
View.Subviews[1].Frame = new CoreGraphics.CGRect(View.Subviews[1].Frame.X, View.Subviews[1].Frame.Y,
View.Subviews[1].Frame.Width, 49);
View.Subviews[0].Frame = new CoreGraphics.CGRect(View.Subviews[0].Frame.X, View.Subviews[0].Frame.Y,
View.Subviews[0].Frame.Width, View.Subviews[0].Frame.Height - 49);
}
Had to add a little tweak for when the phone gets rotated, the views broke again, so this code also gets called when the rotation happens. The little wiggle of the view height seems to sort it all out... Very Hacky but 3-4 hrs later, I accepted the hack and moved on!
if (RootTabPage._fullScreen)
{
View.Subviews[1].Frame = new CoreGraphics.CGRect(View.Subviews[1].Frame.X, View.Subviews[1].Frame.Y,
View.Subviews[1].Frame.Width, 0);
if( View.Frame.Height == View.Subviews[0].Frame.Height )
View.Subviews[0].Frame = new CoreGraphics.CGRect(View.Subviews[0].Frame.X, View.Subviews[0].Frame.Y,
View.Subviews[0].Frame.Width, View.Frame.Height + 2 );
else
View.Subviews[0].Frame = new CoreGraphics.CGRect(View.Subviews[0].Frame.X, View.Subviews[0].Frame.Y,
View.Subviews[0].Frame.Width, View.Frame.Height + 3 );
}
else
{
View.Subviews[1].Frame = new CoreGraphics.CGRect(View.Subviews[1].Frame.X, View.Subviews[1].Frame.Y,
View.Subviews[1].Frame.Width, th);
View.Subviews[0].Frame = new CoreGraphics.CGRect(View.Subviews[0].Frame.X, View.Subviews[0].Frame.Y,
View.Subviews[0].Frame.Width, View.Frame.Height );
}
I am trying to open the Control Center using appium and the following code:
int halfWidth = driver.manage().window().getSize().width / 2;
int screenHeight = driver.manage().window().getSize().height;
driver.swipe(halfWidth, screenHeight-5, halfWidth, screenHeight-300, 500); // driver is instance of IOSDriver
Instead of opening control centre the app simply draws on the screen upwards from the bottom (using coordinates input). Anyone know how to open Control Center using appium and swipe (or any other way)?
Thanks, Charlie
We can do this. I tried in Appium 1.4.13 and I am able to change settings.
I used below code to change the settings in my iPadAir2.
int height = driver.findElementByClassName("UIAWindow").getSize().getHeight();
int width = driver.findElementByClassName("UIAWindow").getSize().getWidth();
driver.swipe(width-100, height, width-100, height-200, 500);
driver.findElementByAccessibilityId("Wi-Fi").click();
Appium 1.6.5, You can use swipe method, bellow my Python code:
window_size = self.driver.get_window_size() # this returns dictionary
el = self.driver.find_element(*self.configuration.CommonScreen.WEB_VIEW)
action = TouchAction(self.driver)
start_x = window_size["width"] * 0.5
start_y = window_size["height"]
end_x = window_size["width"] * 0.5
end_y = window_size["height"] * 0.5
action.press(el, start_x, start_y).wait(100).move_to(el, end_x, end_y).release().perform()
I am able to toggle the Wifi OFF or turn Airplane mode ON using Appium 1.6.4-beta for iOS
Swipe up from the bottom of the screen
Click continue link
Click the Wifi or Airplane button
Swipe down from middle of screen
But this doesn't appear to be doing anything in the simulator. I have to actually turn off my computers internet connection to disable the internet on the simulator.
#iOSFindBy(xpath = "//XCUIElementTypeSwitch[#name='Wi-Fi']")
private MobileElement WIFI_MODE_BUTTON;
public void disableWifi() {
openToolBarMenu();
//if wifi is on/true then turn it off
if (WIFI_MODE_BUTTON.getAttribute("value") == "true" ) {
Autoscope.tap(WIFI_MODE_BUTTON);
}
closeToolBarMenu();
}
#iOSFindBy(xpath = "//XCUIElementTypeButton[#name='Continue']")
private MobileElement CONTINUE_BUTTON; //continue button on control center
public void openToolBarMenu() {
Autoscope.scrollFromBottomOfScreen();
if (Autoscope.isElementDisplayed(CONTINUE_BUTTON)) {
Autoscope.tap(CONTINUE_BUTTON);
}
}
static public void scrollFromBottomOfScreen() {
TouchAction touchAction = new TouchAction(autoscopeDriver);
int xStartPoint = Math.round(pixelWidth() / 2);
int yStartPoint = pixelHeight();
int yEndPoint = 0 - yStartPoint;
touchAction.press(xStartPoint, yStartPoint).moveTo(0, yEndPoint).release().perform();
}
This code will help in bringing up the Control center, while you are in your app, you can perform all the operations which are available in the Control Center
new TouchAction(DriverConfig.getInstance().getDriver()).press(point(250, 735)).waitAction(waitOptions(Duration.ofSeconds(3))).moveTo(point(250, -460)).release()
.perform();
C#: iOS 13.x
//Opening control center
var size = Driver.Manage().Window.Size;
var height = size.Height;
var width = size.Width;
var touchAction = new TouchAction(Driver);
touchAction.Press(width - 100, height).Wait(1000).MoveTo(width - 100, height - 200).Release().Perform();
//Clicking the WiFi button
Driver.FindElementByAccessibilityId("wifi-button").Click();
//Checking if WiFi enabled or not
var myElement = Driver.FindElementByAccessibilityId("wifi-button");
var result = myElement.GetAttribute("label");
if(!result.Contains("Wi-Fi, Not Connected") && !result.Equals("Wi-Fi"))
{
// WiFi connected
}
else
{
// WiFi Not connected
}
The idea is to simulate the swipe action you use to open Control Center on the corresponding iOS device. My device is iPhone 11 so it is swipe from the top right(to the right of the notch) down. My code is to swipe from position(x,y) (80% width, 0) to (80% width, 50% height)
Dimension size = getScreenSize();
int x = (size.getWidth() / 5) * 4;
int startY = 0;
int endY = size.getHeight() / 2;
new TouchAction(driver).press(PointOption.point(x, startY))
.waitAction(WaitOptions.waitOptions(Duration.ofSeconds(1)))
.moveTo(PointOption.point(x, endY))
.release().perform();
Ok so after a fair amount of investigation it seems to me that this is not possible. If you really need this functionality then I think a tool like eggplant might be appropriate.
I'm trying to present a UIActivityViewController from an OpenGL view (using libGDX/RoboVM) but am having mixed results.
It works fine on iOS 7 and on iOS 8 iPad, but on iOS 8 iPhone it simply pauses the application without anything happening. Nothing of note in the debug logs, except that the completion block never fires. This is the code:
UIActivityViewController controller = new UIActivityViewController(activityItems, null);
List<String> excludedTypes = new ArrayList<String>();
excludedTypes.add("UIActivityTypePrint");
excludedTypes.add("UIActivityTypeAssignToContact");
excludedTypes.add("UIActivityTypeAddToReadingList");
excludedTypes.add("UIActivityTypeAirDrop");
excludedTypes.add("UIActivityTypeCopyToPasteboard");
controller.setExcludedActivityTypes(excludedTypes);
IOSApplication iosApplication = (IOSApplication)Gdx.app;
// for iPad (https://groups.google.com/forum/#!topic/robovm/fiGDVf6AAsc)
int majorOsVersion = Integer.parseInt(System.getProperty("os.version").substring(0, System.getProperty("os.version").indexOf('.')));
if (majorOsVersion >= 8)
{
UIView sourceView = iosApplication.getUIViewController().getView();
if (width > 0 && height > 0)
{
UIView subView = new UIView(new CGRect(left, top, width, height));
sourceView.addSubview(subView);
sourceView = subView;
}
UIActivityViewControllerExtensions.getPopoverPresentationController(controller).setSourceView(sourceView);
}
iosApplication.getUIViewController().presentViewController(controller, true, null);
I have verified that the method is being called in the "main" thread (hopefully on libGDX that's the same main thread as in a CocoaTouch app)
NullPointerException here:
UIActivityViewControllerExtensions.getPopoverPresentationController(controller).setSourceView(sourceView);
getPopoverPresentationController() returns null on iPhones, which is not a problem in Objective-C land.
I'm creating an app with Monotouch 5 and I'm having a problem with creating a datepicker with the mode UIDatePickerMode.DateAndTime on iOS 4.3 or lower when running my app in an iPad Simulator. The DatePicker is always broken, although the dimensions I set for it's frame and the surrounding view are perfectly fine.
This is how it looks like on an iPad Simulator with iOS 4.3:
http://screencast.com/t/isIRcUcKCF5
and this is how it looks on an iPad Simulator with iOS 5.0:
http://screencast.com/t/UxPTpR0Btzb
This problem does not occur on iPhone Simulators or real devices. I know it also does not occur on real iPad devices with iOS 5, but I could not test 4.3 or lower because I have no such device.
The source code for creating the date picker is as follows:
public override void Selected (MonoTouch.Dialog.DialogViewController dvc, UITableView tableView, NSIndexPath path)
{
var vc = new MyViewController (this) {
Autorotate = dvc.Autorotate
};
datePicker = CreatePicker ();
datePicker.Frame = PickerFrameWithSize (datePicker.SizeThatFits (SizeF.Empty));
//vc.View encompasses the entire, screen so there is plenty of space available for the date picker
vc.View.BackgroundColor = UIColor.Black;
vc.View.AddSubview (datePicker);
dvc.ActivateController (vc);
}
public virtual UIDatePicker CreatePicker ()
{
var picker = new UIDatePicker (RectangleF.Empty){
AutoresizingMask = UIViewAutoresizing.FlexibleWidth,
Mode = UIDatePickerMode.DateAndTime,
Date = DateValue,
};
return picker;
}
static RectangleF PickerFrameWithSize (SizeF size)
{
var screenRect = UIScreen.MainScreen.ApplicationFrame;
float fY = 0, fX = 0;
switch (UIApplication.SharedApplication.StatusBarOrientation){
case UIInterfaceOrientation.LandscapeLeft:
case UIInterfaceOrientation.LandscapeRight:
fX = (screenRect.Height - size.Width) /2;
fY = (screenRect.Width - size.Height) / 2 -17;
break;
case UIInterfaceOrientation.Portrait:
case UIInterfaceOrientation.PortraitUpsideDown:
fX = (screenRect.Width - size.Width) / 2;
fY = (screenRect.Height - size.Height) / 2 - 25;
break;
}
// calculated values:
// fx: 224
// fy: 369
// size.Width: 320
// size.Height: 320
return new RectangleF (fX, fY, size.Width, size.Height);
}
When I am using a datepicker with the modes UIDatePickerMode.Date or UIDatePickerMode.Time, the problem does not occur.
The problem looks just like blank UIDatePicker on iPad in mode UIDatePickerModeDateAndTime, but the fix described there does not work in my case for some weird reason.
Any hints on how to work around this bug would be greatly appreciated.
Thanks,
Adrian
I still don't have a clue how to make the code above work, but I managed to work around this iOS bug by using a UIPopupView for displaying the calendar instead.