I am attempting to add Maps to my Xamarin forms application. When I open the app, it errors with the following:
Plugin.Geolocator.Abstractions.GeolocationException has been thrown
A geolocation error occurred: Unauthorized
The first time, a popup appears when I run the app to ask if I can access location, and I accepted. The popup no longer appears when I run the app, it just errors. The ItemsPage is the first screen I am directed, where the app crashes. I have included my .plist file. I was following this guide from Xamarin.
Main.cs (iOS)
public class Application
{
// This is the main entry point of the application.
static void Main(string[] args)
{
// if you want to use a different Application Delegate class from "AppDelegate"
// you can specify it here.
UIApplication.Main(args, null, "AppDelegate"); // error thrown here
}
}
ItemsPage.xaml
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
x:Class="Divco.ItemsPage"
Title="{Binding Title}"
x:Name="BrowseItemsPage">
<ContentPage.ToolbarItems>
<ToolbarItem Text="Logout" Command="{Binding LogoutCommand}"/>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout>
<!--<maps:Map WidthRequest="320" HeightRequest="300"
x:Name="MyMap"
IsShowingUser="false"
MapType="Street"/>-->
<ListView x:Name="ItemsListView" ItemsSource="{Binding Items}" VerticalOptions="FillAndExpand" HasUnevenRows="true" RefreshCommand="{Binding LoadItemsCommand}" IsPullToRefreshEnabled="true" IsRefreshing="{Binding IsBusy, Mode=OneWay}" CachingStrategy="RecycleElement" ItemSelected="OnItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="10">
<Label Text="{Binding id}" LineBreakMode="NoWrap" Style="{DynamicResource ListItemTextStyle}" FontSize="16" />
<Label Text="{Binding description}" LineBreakMode="NoWrap" Style="{DynamicResource ListItemDetailTextStyle}" FontSize="13" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
AppDelegate.cs
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
Xamarin.FormsMaps.Init();
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
}
Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDisplayName</key>
<string>{Hidden}</string>
<key>CFBundleName</key>
<string>{Hidden}</string>
<key>CFBundleIdentifier</key>
<string>{Hidden}</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>MinimumOSVersion</key>
<string>8.0</string>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>XSAppIconAssets</key>
<string>Assets.xcassets/AppIcon.appiconset</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>MKDirectionsRequest</string>
<key>LSItemContentTypes</key>
<array>
<string>com.apple.maps.directionsrequest</string>
</array>
</dict>
</array>
<key>MKDirectionsApplicationSupportedModes</key>
<array>
<string>MKDirectionsModeCar</string>
</array>
<key>UIBackgroundModes</key>
<array>
<string>location</string>
<string>fetch</string>
<string>remote-notification</string>
</array>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs access always to location.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access location when open.</string>
</dict>
</plist>
Eventually, I would like to comment out the maps portions in the xaml to show the current location of the user.
NSLocationAlwaysAndWhenInUseUsageDescription is also needed in info.plist after iOS 11 for requesting always Authorization.
Detail Refer to Requesting Always Authorization
Related
My parent view is a Motion Layout. In it I have a ViewPager which has 2 pages. Each page has a vertical recycler view.
My desired effect is for a textView, which is a child of this motion layout, to change its color on page swipe (and to do it smoothly).
PROBLEM: Nothing happens on swipe. Just a regular ViewPager swipe
Here is my transition:
<Transition
app:constraintSetEnd="#id/end"
app:constraintSetStart="#id/start">
<OnSwipe
app:dragDirection="dragLeft"
app:touchAnchorSide="right"
app:touchAnchorId="#id/news_viewPager"/>
</Transition>
I've set a listener on the Motion Layout motionlayout.addTransitionListener() and I'm debugging in its four methods (such as onTransitionChange()) to see if the animation is set off, but it doesn't even starts.
I've tried adding touchRegionId, disableScroll & disablePostScroll but I'm out of ideas.
Could someone please explain to me why it is not working, and a solution to it (or at least an alternative)? Thank you.
Just in case, here's my full scene xml:
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ConstraintSet android:id="#+id/start">
<Constraint android:id="#id/new_videos_title">
<CustomAttribute
app:attributeName="textColor"
app:customColorValue="#color/navBarOn" />
</Constraint>
<Constraint android:id="#id/news_viewPager" />
<Constraint android:id="#id/new_articles_title">
<CustomAttribute
app:attributeName="textColor"
app:customColorValue="#color/navBarOff" />
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="#+id/end">
<Constraint android:id="#id/news_viewPager" />
<Constraint android:id="#id/new_videos_title">
<CustomAttribute
app:attributeName="textColor"
app:customColorValue="#color/navBarOff" />
</Constraint>
<Constraint android:id="#id/new_articles_title">
<CustomAttribute
app:attributeName="textColor"
app:customColorValue="#color/navBarOn" />
</Constraint>
</ConstraintSet>
<Transition
app:constraintSetEnd="#id/end"
app:constraintSetStart="#id/start">
<OnSwipe
app:dragDirection="dragLeft"
app:touchAnchorSide="right"
app:touchAnchorId="#id/news_viewPager"/>
</Transition>
I currently have a user control
<?xml version="1.0" encoding="utf-8" ?>
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Mobile.Control.MultiSelect">
<ListView ItemsSource="{Binding ListSource}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<ContentView Padding="10">
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Name}" HorizontalOptions="Center" TextColor="White" />
</StackLayout>
</ContentView>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
In the code behind I have
public partial class MultiSelect : StackLayout
{
public MultiSelect()
{
InitializeComponent();
BindingContext = this;
}
public static readonly BindableProperty ListSourceProperty =
BindableProperty.Create<MultiSelect, ObservableCollection<ListItem>>(p => p.ListSource, new ObservableCollection<ListItem>());
public ObservableCollection<ListItem> ListSource
{
get { return (ObservableCollection<ListItem>)GetValue(ListSourceProperty); }
set { SetValue(ListSourceProperty, value); }
}
}
In my XAML page I then have
<control:MultiSelect x:Name="MyMultiSelect" />
The question is, how do I bind something in the BindingContext of the XAML
page to the user control.
In the code behind of the XAML page I have
MyMultiSelect.ListSource = BindingContext.MyList;
and this works well. However I don't want anything in the code behind of my XAML page as it goes against the nice clean MVVM pattern I have going on, where my code behind is otherwise nice, clean and empty.
In XAML I have tried
and quite a few other variants but can't get anything to work.
Try this:
public static readonly BindableProperty ListSourceProperty =
BindableProperty.Create<MultiSelect, ObservableCollection<ListItem>>(p => p.ListSource, new ObservableCollection<ListItem>(), BindingMode.Default, null, (bindable, oldVal,newVal)=>{ (bindable as MultiSelect).LisstSource = newVal;});
I'm extending javafx.stage.Popup to display a popup message. The entire app works fine on Windows and Ubuntu but on Mac Popups go behind the current stage when the app is full screen. I've tried using z-index,.toFront(), setting owner window and everything. But the popups just never showup! Same problem is with javafx.stage.FileChooser. Since the app must be fullscreen all the time, what is the solution?
EDIT: In another page,the textfield has cursor blinking in fullscreen but does not receive typed keys! And this happens ONLY in full screen! If I lose fullscreen, the textfield recieves typed keys. Quite annoying :( Please suggest if I should file a bug or something
I've figured out workaround for popup but problem persists for DirectoryChooser/FileChooser.
This is the class that extends Popup:
public class PopupDisplay extends Popup
{
String Title=new String("Information");
String Prompt=new String("Prompt Text");
#FXML
private AnchorPane anchorMain;
#FXML
private Label lblTitle=new Label();
#FXML
private Font x1;
#FXML
private Label lblPrompt=new Label();
#FXML
private Button btnOk;
#FXML
private GridPane gridMain;
#FXML
private HBox hboxTitle;
static PopupDisplay instance;
private ColorDxDesktop application;
public void show(Stage stage, String titleKey,String promptKey, Locale enLocale)
{
AnchorPane root;
FXMLLoader loader=new FXMLLoader();
ResourceBundle rb;
Prompt=promptKey;
Title=titleKey;
try
{
loader.setLocation(getClass().getResource("/com/sc/colordx/resources/"));
rb=ResourceBundle.getBundle("com.sc.colordx.resources.lang.Popup",application.getLocale());
loader.setResources(rb);
PopupController.prompt=Prompt;
PopupController.title=Title;
root = (AnchorPane)loader.load(getClass().getResource("/com/sc/colordx/presentation/Popup.fxml").openStream());
getScene().setRoot(root);
PopupController popupController=loader.getController();
Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds();
root.setPrefWidth(application.getStage().getWidth());
root.setPrefHeight(application.getStage().getHeight());
Node n=root.getChildren().get(0);
n.setLayoutX(screenBounds.getWidth()/2.5);
n.setLayoutY((screenBounds.getHeight()/2.5));
//root.toFront();
show(stage);
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
public static PopupDisplay getInstance()
{
return instance;
}
#FXML
private void hide(MouseEvent event)
{
this.hide();
}
public void showInProgress()
{
PopupController.showInProgress();
}
And this is the FXML for Popup:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane id="AnchorPane" fx:id="anchorMain" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="768.0" prefWidth="1024.0" styleClass="mainFxmlClass" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="com.sc.colordx.controller.PopupController">
<children>
<GridPane id="GridPane" fx:id="gridMain" alignment="CENTER" layoutX="309.0" layoutY="330.0" minWidth="400.0" style="-fx-background-color:black;" styleClass="visibleWindow, gridpane, gridpane-boder" vgap="20.0">
<children>
<Label fx:id="lblPrompt" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefWidth="271.0" text="%keyPrompt" textFill="WHITE" textOverrun="CLIP" wrapText="true" GridPane.columnIndex="0" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="CENTER">
<font>
<Font name="System Bold" size="14.0" fx:id="x1" />
</font>
<GridPane.margin>
<Insets bottom="6.0" left="6.0" right="6.0" top="6.0" />
</GridPane.margin>
</Label>
<HBox id="HBox" fx:id="hboxButtons" alignment="CENTER" spacing="7.0" style="" styleClass="hbox" GridPane.columnIndex="0" GridPane.hgrow="ALWAYS" GridPane.rowIndex="2" GridPane.vgrow="ALWAYS">
<children>
<Button fx:id="btnOk" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onMouseClicked="#exitOkay" text="%keyYes" HBox.hgrow="ALWAYS" />
<Button id="btnOk" fx:id="btnCancel" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onMouseClicked="#hide" text="%keyNo" HBox.hgrow="ALWAYS" />
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
<stylesheets>
<URL value="#../resources/css/Popup.css" />
</stylesheets>
</HBox>
<ProgressIndicator fx:id="progress" cache="true" cacheHint="QUALITY" progress="0.0" visible="false" GridPane.columnIndex="0" GridPane.rowIndex="1">
<GridPane.margin>
<Insets left="300.0" />
</GridPane.margin>
</ProgressIndicator>
</children>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
</columnConstraints>
<padding>
<Insets />
</padding>
<rowConstraints>
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints>
</GridPane>
</children>
<stylesheets>
<URL value="#../resources/css/Popup.css" />
</stylesheets>
</AnchorPane>
The same thing I was getting with Popup while running JavaFx application in MAC so what I did was created new Stage (dummy/invisible with height and width = 0) with initStyle(StageStyle.UTILITY); and bind my popup with that. Everytime I need to display popup I use dummyStage.show(); and popup.toFront(); so it will cause a trick to handle my problem in mac.
today's question is about embedding a map view into a JavaFX application. I basically followed the instructions on StackOverFlow - embedding google map in JavaFX and Embed OpenLayers with OpenStreetMap, so everything like the *.html file is in place. But there, people are adding the WebView to main Scene. For me, I would like to add the WebView to a SplitPane. ThereFore I prepared the application.fxml file as followed:
<SplitPane id="SplitPane" dividerPositions="0.5" orientation="HORIZONTAL" prefHeight="260.0" prefWidth="850.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<TableView id="tableView1" fx:id="table" prefHeight="263.0" prefWidth="433.0">
<columns>
<TableColumn text="one" /><TableColumn text="two" /><TableColumn text="three" />
</columns>
</TableView>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<Region fx:id="webViewRegion" prefHeight="200.0" prefWidth="200.0" />
</children>
</AnchorPane>
</items>
</SplitPane>
The FXML file is loaded by the FXMLLoader when the application is started. In the application controller I get the Region as followed:
#FXML
private Region webViewRegion;
class MyMapView extends Region {
HBox toolbar;
WebView webview = new WebView();
WebEngine webEngine = webview.getEngine();
public MyMapView() {
final URL urlGoogleMaps = getClass().getResource("openstreetmap.html");
webEngine.load(urlGoogleMaps.toExternalForm());
getChildren().add(webview);
}
}
private void load_webView() {
webViewRegion = new MyMapView();
}
For me, now I do not exactly know how to populate the Region with the Webview in a correct way or if there is any better approach?
I am building a application in JavaFx 2.0 and would like to, when the application is deployed, to have it show up on the center of the window of a browser. I have looked for this topic in google and yahoo and found nothing. Any help is greatly appreciated.
Look at the source code for the JavaFX Ensemble example. The Ensemble application is configured to run to fill a browser window, no matter the size of the window. The way it is done is by configuration in the JavaScript which launches the app as well as via css styling of the div the application is embedded in.
Here is an extract of the relevant parts of the html.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JavaFX 2.0 - Ensemble</title>
<SCRIPT src="http://java.com/js/dtjava.js"></SCRIPT>
<script>
function javafxEmbed_ensemble() {
dtjava.embed(
{
id : 'ensemble',
url : 'Ensemble.jnlp',
placeholder : 'javafx-app-placeholder',
width : '100%',
height : '100%',
jnlp_content : '...'
},
{
javafx : '2.0+'
},
{}
);
}
dtjava.addOnloadCallback(javafxEmbed_ensemble);
</script>
<style>
html, body, #javafx-app-placeholder, #ensemble-app {
margin: 0;
overflow: hidden;
padding: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body><div id='javafx-app-placeholder'></div></body>
</html>
If you need something other than 100% coverage, you can the 100% tags to, say 75%, and adjust the css styling to get centering in the page with the margins you want.
The current Java packaging tools (e.g. the javafxpackager utility), do not allow specification of percentange widths. I've created a feature request for this in the javafx jira - you can create an account there to view the request. If you use those tools to generate your deployment html, then you might have to modify the deployment html by hand or by a post-processing ant script, as can be seen in the build.xml for the Ensemble sample application.
You can use combination of HBox and VBox panels in your FXML. Hier is my tested code:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="panel1" xmlns:fx="http://javafx.com/fxml" fx:controller="app.MainController">
<HBox alignment="CENTER" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<VBox alignment="CENTER">
<Pane fx:id="panel2"></Pane> <!-- YOUR CENTERED CONTENT HERE! -->
</VBox>
</HBox>
</AnchorPane>
The 'panel1' will stretch in the browser area. So the HBox and VBox will also. Because they have 'center' attributes for their childeren, the 'panel2' will be centered.
Use this FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="500.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml">
<children>
<HBox id="HBox" alignment="CENTER" spacing="5.0" AnchorPane.bottomAnchor="213.0" AnchorPane.leftAnchor="168.0" AnchorPane.rightAnchor="168.0" AnchorPane.topAnchor="214.0">
<children>
<GridPane id="gridPane1" alignment="CENTER" hgap="2.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" vgap="2.0">
<children>
<Label id="label1" alignment="CENTER_RIGHT" contentDisplay="RIGHT" text="Username" GridPane.columnIndex="0" GridPane.rowIndex="0" />
<Label id="label2" alignment="CENTER_RIGHT" text="Password" GridPane.columnIndex="0" GridPane.rowIndex="1" />
<TextField id="textField1" fx:id="userid" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="0" />
<PasswordField id="passwordField1" fx:id="password" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<Button id="button1" alignment="CENTER_RIGHT" text="Signin" GridPane.columnIndex="1" GridPane.halignment="RIGHT" GridPane.rowIndex="2" />
</children>
<columnConstraints>
<ColumnConstraints halignment="CENTER" hgrow="NEVER" maxWidth="-Infinity" minWidth="-Infinity" percentWidth="0.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
</columnConstraints>
<padding>
<Insets bottom="2.0" left="4.0" right="4.0" top="2.0" />
</padding>
<rowConstraints>
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints>
</GridPane>
</children>
</HBox>
</children>
</AnchorPane>
Might solve your problem
Try to use a StackPane as container. It will center all nodes it includes.
Torsten