My app had the default MainWindow.xib with a NavigationController in it. Now I recently switched it to a xib-less main window and RootViewController (subclass of UIViewController) similar to the example provided at the bottom of HelloiPhone:
My Main.cs:
namespace MyApp {
public class Application {
static void Main(string[] args) {
UIApplication.Main(args, null, "MyApp.AppDelegate");
}
}
public class AppDelegate : UIApplicationDelegate {
UIWindow window;
// This method is invoked when the application has loaded its UI and its ready to run
public override bool FinishedLaunching(UIApplication app, NSDictionary options) {
RootViewController rootViewController = new RootViewController();
UINavigationController navigationController = new UINavigationController(rootViewController);
navigationController.LoadView();
navigationController.NavigationBar.BarStyle = UIBarStyle.Black;
window = new UIWindow(UIScreen.MainScreen.Bounds);
window.AddSubview(navigationController.View);
window.MakeKeyAndVisible();
return true;
}
// This method is required in iPhoneOS 3.0
public override void OnActivated(UIApplication app) {
}
public override void WillTerminate(UIApplication app) {
//Save data here
}
}
}
My Info.plist:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UILaunchImageFile</key>
<string>images/logo_320x480.png</string>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleBlackOpaque</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
</dict>
</plist>
On the simulator, everything seems well. At first, the launching image is displayed and finally the rootView appears after a few seconds.
However, when deploying to the device (iPod touch), the rootView won't display. Instead, the screen turns to white after the launching image. (Status bar at the top is still there)
Is there something wrong with that approach? Am I missing something?
You might find some useful info here:
differences-between-iphone-ipod-simulator-and-devices
iphone-device-vs-iphone-simulator
The white screen was not related to switching to xib-less.
The white screen was actually my rootView with white background, some images and some buttons with background images and white font color. I renamed the folder "images" to "Images" a while back and got hit by case-sensitivy on the device. No images displayed and everything else was white so I didn't see it.
If I had tested on the device before switching to xib-less, I could've directly related it to renaming the folder.
Related
We are extending our Xamarin.iOS app (by Xamarin.Forms) for CarPlay. When open the CarPlay simulator, the app is showing on the screen of CarPlay, but crashed when launching from CarPlay simulator.
Below is the Info.plist Scene configuration:
<key>UIApplicationSceneManifest</key>
<dict>
<key>UISceneConfigurations</key>
<dict>
<key>CPTemplateApplicationSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>CPTemplateApplicationScene</string>
<key>UISceneConfigurationName</key>
<string>ParkingPlus-Car</string>
<key>UISceneDelegateClassName</key>
<string>ParkingPlus.AppSceneDelegateImp</string>
</dict>
</array>
</dict>
</dict>
"ParkingPlus" is the app bundle name!
The class AppSceneDelegateImp (under the root folder of the iOS project
public class AppSceneDelegateImp : UIResponder, ICPTemplateApplicationSceneDelegate
{
private CPInterfaceController _interfaceController;
public async void DidConnect(CPTemplateApplicationScene templateApplicationScene, CPInterfaceController interfaceController)
{
_interfaceController = interfaceController;
.....
}
public void DidDisconnect(CPTemplateApplicationScene templateApplicationScene, CPInterfaceController interfaceController)
{
_interfaceController.Dispose();
_interfaceController = null;
}
}
When I override the AppDelegate.GetConfiguration as below
public override UISceneConfiguration GetConfiguration(UIApplication application, UISceneSession connectingSceneSession, UISceneConnectionOptions options)
{
...
}
When tapping the app icon on CarPlay, the method will be called. But when I inspected the connectingSceneSession, I found there are some exceptions inside the variable members.
"CPTemplateApplicationSceneSessionRoleApplication has no associated enum value on this platform".
Screenshot for connectingSceneSession inspection
If continue, then the app will throw an exception which seems advise that the SceneDelegate is not being loaded properly:
Exception
My envorinment:
Visual studio for mac Version 8.7.8
Xamarin.iOS 14.0.0
Xcode 12.0
It seems like Xamarin.ios 14 missing something when binding the iOS library. Anyone has the similar issue. Did I do anything wrong or Is there any other way I can implement the CarPlay part feature by Xcode/swift while keeping the mobile app on Xamarin.Forms/Xamarin.iOS?
Appreciate any comments or help.
With the help from Xamarin.ios team, below is the full solution to this issue:
https://github.com/xamarin/xamarin-macios/issues/9749
The AppDelegate to create the scene configuration for two cases (CarPlay and phone)
[DllImport("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")]
public extern static IntPtr IntPtr_objc_msgSend_IntPtr_IntPtr(IntPtr receiver, IntPtr selector, IntPtr arg1, IntPtr arg2);
public static UISceneConfiguration Create(string? name, NSString sessionRole)
{
global::UIKit.UIApplication.EnsureUIThread();
var nsname = NSString.CreateNative(name);
UISceneConfiguration sceneConfig;
sceneConfig = Runtime.GetNSObject<UISceneConfiguration>(IntPtr_objc_msgSend_IntPtr_IntPtr(Class.GetHandle("UISceneConfiguration"), Selector.GetHandle("configurationWithName:sessionRole:"), nsname, sessionRole.Handle));
NSString.ReleaseNative(nsname);
//Because only the CarPlay scene will be here to create a scene configuration
//We need manually assign the CarPlay scene delegate here!
sceneConfig.DelegateType = typeof(AppCarSceneDelegateImp);
return sceneConfig!;
}
[Export("application:configurationForConnectingSceneSession:options:")]
public UISceneConfiguration GetConfiguration(UIApplication application, UISceneSession connectingSceneSession, UISceneConnectionOptions options)
{
UIWindowSceneSessionRole sessionRole;
bool isCarPlaySceneSession = false;
try
{
//When the connecting scene is a CarPlay scene, an expected exception will be thrown
//Under this moment from Xamarin.iOS.
sessionRole = connectingSceneSession.Role;
}
catch (NotSupportedException ex)
{
if (!string.IsNullOrEmpty(ex.Message) &&
ex.Message.Contains("CPTemplateApplicationSceneSessionRoleApplication"))
{
isCarPlaySceneSession = true;
}
}
if (isCarPlaySceneSession && UIDevice.CurrentDevice.CheckSystemVersion(14,0))
{
return Create("Car", CarPlay.CPTemplateApplicationScene.SessionRoleApplication);
}
else
{
//If it is phone scene, we need the regular UIWindow scene
UISceneConfiguration phoneScene = new UISceneConfiguration("Phone", UIWindowSceneSessionRole.Application);
//And assign the scene delegate here.
phoneScene.DelegateType = typeof(AppWindowSceneDelegateImp);
return phoneScene;
}
}
Create a UIWindowScene delegate to handle the regular mobile scene window
public class AppWindowSceneDelegateImp : UISceneDelegate
{
public override void WillConnect(UIScene scene, UISceneSession session, UISceneConnectionOptions connectionOptions)
{
var windowScene = scene as UIWindowScene;
if (windowScene != null)
{
//Assign the Xamarin.iOS app window to this scene
UIApplication.SharedApplication.KeyWindow.WindowScene = windowScene;
UIApplication.SharedApplication.KeyWindow.MakeKeyAndVisible();
}
}
}
I've been trying to disable a javafx.scene.control.ColorPicker without dimming it in my UI. Meaning that I want it to look as enabled (enabled appearence), but just do not respond to any command, also not showing the table of colors on mouse click (actually disabled). This behaviour will be interchangeable with normal behaviour, according to the system state (i.e., sometimes color picker will behave as normal).
I've tried some options, but none seemed to work, as follows:
1. Use setEditable(boolean):
myColorPicker.setEditable(false);
This just doesn't work, the color picker remains editable.
2. Use setDisable(boolean) and setOpacity(double) together:
myColorPicker.setDisable(true);
myColorPicker.setOpacity(1.0f);
This makes the color picker actually not editable, and the resulting color picker appear a little less dimmed than just using setDisable(true), but still not the appearence of an enabled color picker.
3. Overriding onMouseClick(), onMousePressed() and onMouseReleased() with empty implementations:
myColorPicker.setOnMouseClicked(new EventHandler <MouseEvent>() {
public void handle(MouseEvent event) {
System.out.println("Mouse clicked.");
}
});
myColorPicker.setOnMousePressed(new EventHandler <MouseEvent>() {
public void handle(MouseEvent event) {
System.out.println("Mouse pressed.");
}
});
myColorPicker.setOnMouseReleased(new EventHandler <MouseEvent>() {
public void handle(MouseEvent event) {
System.out.println("Mouse released.");
}
});
The above approach printed on my console the corresponding messages, but color picker still responded to mouse click (showing the color table and allowing to pick a new color). Also tried to override setOnAction(EventHandler<ActionEvent>), but with same effect (except that no console printing when I clicked the color picker).
Here it is the excerpt of my FXML:
<VBox fx:controller="mypackage.ElementConfigWidget"
xmlns:fx="http://javafx.com/fxml" fx:id="root" styleClass="elementConfigPane">
<HBox id="elementInfo">
(...)
<ColorPicker fx:id="elementColor" styleClass="elementColor" />
</HBox>
(...)
</VBox>
Here it is my CSS exerpt:
.elementColor {
-fx-cursor: hand;
-fx-background-color: #fff;
-fx-focus-color: transparent;
-fx-faint-focus-color: transparent;
-fx-pref-width: 50.0;
}
I actually expected setEditable(boolean) to solve my problem, by keeping the element appearence and ignoring input actions. What am I missing?
Thanks a lot!
I manage to achieve it with some CSS
.Also you need to setDisable(true) and opacity to 1.0
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ColorPicker;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
ColorPicker myColorPicker = new ColorPicker();
myColorPicker.setDisable(true);
myColorPicker.setOpacity(1.0);
Scene s = new Scene(myColorPicker);
s.getStylesheets().add(this.getClass().getResource("test.css").toExternalForm());
primaryStage.setScene(s);
primaryStage.show();
}
}
And the test.css
.color-picker > .label:disabled {
-fx-opacity : 1.0;
}
I would like to create buttons like these for settings panel navigation:
Can you tell me how I can create this hover effect over the icons? The most difficult part for me is to create CSS code which looks like the the picture.
Although the above answer works. You should really do this completely in CSS using pseudo-selectors:
java:
btnsa.getStyleClass().add("myButton");
css:
.myButton {
-fx-background-color:transparent;
}
.myButton:hover {
-fx-background-color:#dae7f3;
}
You have to use MouseEntered and MouseExited events for getting hover effects over the icons.
try this its working.........
btnsa.setStyle("-fx-background-color:transparent;");
btnsa.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("JavafxSm.gif"))));
btnsa.setOnMouseEntered(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
btnsa.setStyle("-fx-background-color:#dae7f3;");
}
});
btnsa.setOnMouseExited(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
btnsa.setStyle("-fx-background-color:transparent;");
}
});
some snap shots of above code......
Instead, you can do just 1 line code in CSS, if your FXML file connected with CSS
yourButtonId:hover{-fx-background-color: #6695e2}
I want to develop a multiple scenes Java FX application. But I want to have the common menu across all scenes. I think using FXML I can create a menu in a scene. But Can I have the same menu across all the scenes even after I navigated to other screen?
If so how is it. Else let me know any alternative for it.
Yes this is possible. I'm using this mechanism in my own application.
What I do first is make an FXML with the menu bar and an AnchorPane who contains the content. This FXML is loaded when the application starts.
I use a Context class (based on the answer of Sergey in this question: Multiple FXML with Controllers, share object) which contains a method ShowContentPane(String url) method:
public void showContentPane(String sURL){
try {
getContentPane().getChildren().clear();
URL url = getClass().getResource(sURL);
//this method returns the AnchorPane pContent
AnchorPane n = (AnchorPane) FXMLLoader.load(url, ResourceBundle.getBundle("src.bundles.bundle", getLocale()));
AnchorPane.setTopAnchor(n, 0.0);
AnchorPane.setBottomAnchor(n, 0.0);
AnchorPane.setLeftAnchor(n, 0.0);
AnchorPane.setRightAnchor(n, 0.0);
getContentPane().getChildren().add(n);
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
So what basically happens is:
When the program starts, set content pane in the Context:
#Override
public void initialize(URL url, ResourceBundle rb) {
Context.getInstance().setContentPane(pContent); //pContent is the name of the AnchorPane containing the content
...
}
When a button or menuitem is chosen, I load the FXML in the content Pane:
#FXML
private void handle_FarmerListButton(ActionEvent event) {
Context.getInstance().showContentPane("/GUI/user/ListUser.fxml");
}
Hope this helps :)
I have QLPreviewController up and running but I'm using PresentModalViewController() to show the QLPreviewController directly. For reasons beyond explanation, I would like to have my own UIViewController which will create its own view and within that view I would like to use the QLPreviewController. Should be easy I thought, but the code below just does nothing. The QLPreviewControllers ViewDidAppear never gets called. (In my example below, PreviewController inherits from QLPreviewController and encapsulates delegate, preview item and source).
Can somebody explain what is wrong with the code below (besides the fact that it is pointless :-))?
Oh, yeah: in my test scenario, I present the controller below modally. It shows up but witout the preview.
public class OuterPreviewController : UIViewController
{
public OuterPreviewController (QLPreviewControllerDataSource oDataSource) : base()
{
this.oDataSource = oDataSource;
}
private PreviewController oPreviewController;
private QLPreviewControllerDataSource oDataSource;
public override void LoadView ()
{
this.View = new UIView();
this.View.Frame = new RectangleF(0, 0, 500, 500);
this.View.BackgroundColor = UIColor.Red;
}
public override void ViewDidAppear (bool animated)
{
// Code execution comes her. No errors, no issues.
base.ViewDidAppear (animated);
this.oPreviewController = new PreviewController();
this.oPreviewController.DataSource = this.oDataSource;
// Preview controller's view is added but it never shows up.
this.View.AddSubview(this.oPreviewController.View);
this.oPreviewController.View.Frame = this.View.Frame;
this.oPreviewController.View.Center = this.View.Center;
}
public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
{
return true;
}
}
Found a solution by coincidence today: all ReloadData() on the preview controller and magically it will show its contents.
This allows to add a QLPreviewController to an existing view as a subview and embed a preview. It also gets you rid of the toolbar which contains the open in menu.