Android Widget using Xamarin Forms? - xamarin.android

I already have an app created in Xamarin Forms that works in Android and iOS.
Now, I want to create an Android Widget.
Can I use existing Xamarin Forms pages and create an Android Widget out of it?
If so, is there a sample for the same.
I am unable to find much help for it. Even on Xamarin Forms Forums.

I'm creating a toast message on the top of page my when i receive a push notification messages like this, so u can create widgets like this (or pages i suppose).Hope that helps u.
var pw = new Android.Widget.PopupWindow(Xamarin.Forms.Forms.Context); //create a window
var layout = new Android.Widget.RelativeLayout(Xamarin.Forms.Forms.Context);
pw.ContentView = layout; //create your layout holder
pw.Width = 100; //set window sizes
pw.Height = 100;
pw.WindowLayoutType = WindowManagerTypes.Toast; //window type (there are some other types too, just investigate :)
var tv = new Android.Widget.TextView(Xamarin.Forms.Forms.Context); //create a text and add to your layout holder
tv.Text = "Hello";
layout.AddView(tv);
pw.ShowAtLocation(layout, GravityFlags.Top, 0, 0); //show your window
You can dismiss the window via pw.Dissmiss() but i'm using a timerbecause it is a toast
var timer = new System.Timers.Timer();
timer.Interval = 5000; //5 seconds
timer.Elapsed += (sender, e) =>
{
timer.Stop();
Device.BeginInvokeOnMainThread(() =>
{
pw.Dismiss();
});
};
timer.Start();
You can inflate a predefined xaml too i think but you have to google a little :)

Related

Electron app across 2 displays?

Can an electron app run one window across 2 monitors? I'm not able to drag the edge across to the other monitor. is this possible?
I know I can do this to access the second screen.
const electron = require('electron')
const {app, BrowserWindow} = require('electron')
let win
app.on('ready', () => {
let displays = electron.screen.getAllDisplays()
let externalDisplay = displays.find((display) => {
return display.bounds.x !== 0 || display.bounds.y !== 0
})
if (externalDisplay) {
win = new BrowserWindow({
x: externalDisplay.bounds.x + 50,
y: externalDisplay.bounds.y + 50
})
win.loadURL('https://github.com')
}
})
however, I dont want 2 windows just one across 2 displays.
You can drag the electron window like any other window.
If you want to set the window size, you either do it when a BrowserWindow is created or via BrowserWindow.setSize() to modify the size see BrowserWindow docs
That was real problem, that it was impossible to set via BrowserWindow.setSize() values gather than height and width of first screen, to open window stretched on few screens
But finally I have found, the solution is
BrowserWindow.setMinimumSize(W, H);
that allows to set width, like 10`000px, for few monitors, and it will be applied unlike setSize

Horizontally centering a popup window in Vaadin

I have added a popup window to my main UI as follows:
Window component = new Window();
UI.getCurrent().addWindow(component);
Now, I want my popup to be centered horizontally and e.g. 40 pixels from the top of the screen. As far as I can see Vaadin has 4 methods for positioning my window.
component.center()
component.setPosition(x, y)
component.setPositionX(x)
component.setPositionY(y)
None of these are really what I want. I was hoping at first that setPositionY might help me. This does allow me to get the right distance from the top, but the x-position is now set to 0, where I wanted it to be centered.
The setPosition might have helped if I was able to calculate what the x-position should be, but this would require me to know the width of the component in pixels, but component.getWidth just tells me 100%.
Next I tried to use CSS styling on the component, writing and explicit css rule and adding it to the component with addStyleName. It seems though that Vaadin overrides whatever I wrote in my css with its own defaults...
Any ideas how to get my Window component positioned correctly?
I used the methods getBrowserWindowWidth() and getBrowserWindowHeight() from the com.vaadin.server.Page class for this.
I centered my "log" window horizontally in the lower part of the browser window with
myWindow.setHeight("30%");
myWindow.setWidth("96%");
myWindow.setPosition(
(int) (Page.getCurrent().getBrowserWindowWidth() * 0.02),
(int) (Page.getCurrent().getBrowserWindowHeight() * 0.65)
);
Solution 1: Use SizeReporter
Indeed, setPositionY() will reset the window's centered property to false. As the width of your pop-up and that of your browser window are not know before they appear on the screen, the only way I know to get those values is to use the SizeReporter add-on. Its use is quite straightforward:
public class MyUI extends UI {
private Window popUp;
private SizeReporter popUpSizeReporter;
private SizeReporter windowSizeReporter;
#Override
protected void init(VaadinRequest request) {
Button button = new Button("Content button");
VerticalLayout layout = new VerticalLayout(button);
layout.setMargin(true);
popUp = new Window("Pop-up", layout);
popUp.setPositionY(40);
addWindow(popUp);
popUpSizeReporter = new SizeReporter(popUp);
popUpSizeReporter.addResizeListenerOnce(this::centerPopUp);
windowSizeReporter = new SizeReporter(this);
windowSizeReporter.addResizeListenerOnce(this::centerPopUp);
}
private void centerPopUp(ComponentResizeEvent event) {
int popUpWidth = popUpSizeReporter.getWidth();
int windowWidth = windowSizeReporter.getWidth();
if (popUpWidth == -1 || windowWidth == -1) {
return;
}
popUp.setPositionX((windowWidth - popUpWidth) / 2);
}
}
This piece of code will be okay as long as you don't resize the pop-up. If you do, it will not be automatically recentered. If you replace addResizeListenerOnce() by addResizeListener() then it will automatically recenter the pop-up but you'll get some "UI glitches" as the add-on sends resize events almost continually while you're resizing your pop-up...
You could try to do it using CSS, but I personally avoid CSS as much as I can with Vaadin :).
You'll need to recompile the widgetset after you've added the add-on as a dependency.
Solution 2: Use com.vaadin.ui.JavaScript
I won't vouch for the portability of this solution but I guess it will work on most modern browsers.
public class MyUI extends UI {
private Window popUp;
#Override
protected void init(VaadinRequest request) {
Button button = new Button("Content button");
VerticalLayout layout = new VerticalLayout(button);
layout.setMargin(true);
popUp = new Window("Pop-up", layout);
popUp.setPositionY(40);
popUp.addStyleName("window-center");
addWindow(popUp);
// Add a JS function that can be called from the client.
JavaScript.getCurrent().addFunction("centerWindow", args -> {
popUp.setPositionX((int) ((args.getNumber(1) - args.getNumber(0)) / 2));
});
// Execute the function now. In real code you might want to execute the function just after the window is displayed, probably in your enter() method.
JavaScript.getCurrent().execute("centerWindow(document.getElementsByClassName('window-center')[0].offsetWidth, window.innerWidth)");
}
}

Resize WebView defined in Xamarin.Forms Core library on screen rotate event

I have web page defined in the core library as view to fill whole screen:
Content = new WebView
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
Source = "https://google.com",
};
Unfortunately on screen rotate it's not resized (please see below):
How can I make sure that screen is resized on screen rotation.
If it's iOS, then make a custom WebView renderer (http://developer.xamarin.com/guides/cross-platform/xamarin-forms/custom-renderer/):
protected override void OnElementChanged (VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
AutoresizingMask = UIViewAutoresizing.FlexibleDimensions;
ScalesPageToFit = true;
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
NativeView.Bounds = UIKit.UIScreen.MainScreen.Bounds;
}
Please try this solution, it works in iOS 8.4, but not iOS 7.
Xamarin Forms: How to resize the Webview after rotation in iOS
You need to be working with webview using Xamarin.forms.
Working with WebView in Xamarin.Forms
xamarin-forms-samples/WorkingWithWebview Has examples for each platform.
This link on Handling Rotation gives you all the details you need for android. The other answer has covered iOS.
Responding To Orientation Changes In Xamarin Forms another great link
Customizing Controls for Each Platform using these premise you can manage the screen rotation for each platform separately within the one app.
Handling Runtime Changes shows how to manage screen rotation. You need to scroll down the page.
A good link on managing windows phone, The two ways to handle orientation in your Windows 8.1 app.
Another useful link Fix IE 10 on Windows Phone 8 Viewport.
This is an interesting link on Managing screen orientation from mozilla. It is experimental, but interesting.
I implemented the custom renderer and added the line "webView.AutoresizingMask = UIViewAutoresizing.FlexibleDimensions;" but it doesn't work for me. Then, I solved this with a not so elegant solution (reloading the WebView component when the device orientation changes).
In my xaml:
<StackLayout Padding="0" >
<WebView x:Name="viewJupyter" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" />
</StackLayout>
And my code behind class:
public partial class ServiceChart : ContentPage
{
private int _rotateView;
public ServiceChart(string title, string url)
{
Title = title;
InitializeComponent();
var urlPage = new UrlWebViewSource
{
Url = url
};
viewJupyter.Source = urlPage;
if (Device.OS == TargetPlatform.iOS)
{
SizeChanged += (sender, arg) =>
{
if (_rotateView != 0)
{
var lalala = viewJupyter;
InitializeComponent();
viewJupyter.Source = (lalala.Source as UrlWebViewSource).Url;
}
_rotateView++;
};
}
}
}

FlyoutNavigation - Views using NSLayoutConstraints Fail to Properly Draw View on First Use

Cross-posted here and on github, https://github.com/Clancey/FlyoutNavigation/issues/29.
I have an odd behavior I'm trying to track down, and I'm not sure if it is FlyoutNavigation or something else I'm doing. Maybe someone can take a quick look who understands things a bit better than I do.
Example Project - https://github.com/benhysell/FlyoutNavigationWithNSLayoutConstraintsError
Goal - Use https://gist.github.com/praeclarum/5175100, A C# syntax for NSLayoutConstraints, described in this blog post, http://praeclarum.org/post/45690317491/easy-layout-a-dsl-for-nslayoutconstraint, with FlyoutNavigation.
Issue - On the first use of a view that incorporates NSLayoutConstraints the view doesn't respect the constraints or background color, both odd. On subsequent 'selections' of the view from the menu of FlyoutNavigation the view will properly draw.
Setup - Working in Xamarin Beta Channel against iPhone Simulator 6.1 and the latest released Xcode.
Steps to Reproduce
1. The easiest way to show this is to open the sample project that comes with FlytoutNavigation and modify this project using the steps below. I included in this post a link to the example project I modified to show the error.
Add the gist, https://gist.github.com/praeclarum/5175100, to a new class, call it layout.
Add a new UIViewController and the following to ViewDidLoad(), note this was modified from the Xamarin 'Hello World' sample app one can create in VS2012
public override void ViewDidLoad()
{
base.ViewDidLoad();
View.Frame = UIScreen.MainScreen.Bounds;
View.BackgroundColor = UIColor.Red;
button = UIButton.FromType(UIButtonType.RoundedRect);
button.SetTitle("Click me", UIControlState.Normal);
button.TouchUpInside += (object sender, EventArgs e) =>
{
button.SetTitle(String.Format("clicked {0} times", numClicks++), UIControlState.Normal);
};
View.AddSubview(button);
const int ButtonWidth = 75;
const int HPadding = 22;
const int VPadding = 44;
View.ConstrainLayout(() =>
button.Frame.Width == ButtonWidth &&
button.Frame.Left == View.Frame.Left + HPadding &&
button.Frame.Top == View.Frame.Top + VPadding);
}
In the MainController.cs replace
navigation.ViewControllers = Array.ConvertAll (Tasks, title =>
new UINavigationController (new TaskPageController (navigation, title))
);
with
navigation.ViewControllers = Array.ConvertAll(Tasks, title =>
new UINavigationController(new MyViewController(navigation))
);
I'm saying 'make every view a view that implements NSLayoutConstraints'.
Run Application, first view returns with:
Select the same item from the FlyoutNavigation menu and it will then properly draw.
I've traced through FlyoutNavigationController.cs a couple of times and it appears on the second time selecting the item from FlyoutNavigation, on line 238:
this.View.AddSubview (mainView);
ViewControllers[0].ChildViewControllers[0].View.Frame {{X=160,Y=208,Width=0,Height=0}} System.Drawing.RectangleF
This is the incorrect size for the view, however after I step over line 238:
ViewControllers[0].ChildViewControllers[0].View.Frame {{X=0,Y=0,Width=320,Height=416}} System.Drawing.RectangleF
The position is fixed, and the view will draw correctly.
Summary - I've tried using the gist with the NSLayoutConstraints by itself in a single page window application without issue, and I'm thinking since it does eventually draw properly after a second invokation of FlyoutNavigation I'm thinking there is a 'something' I'm missing with the FlyoutNavigation, or setting incorrectly that I can't put my finger on.

IOS: Creating full screen 'overlay' UIView (Monotouch)

I have a view within a navigationcontroller, and would like to create a 'full (application) screen' overlay that says a couple of things about what the user should do. I've seen this done with a bit of transparency on other apps and it works well. I'm trying the below, but the content ends up beneath my navcontroller headers. Investigations talk about converting the rectangle to a 'window level' location etc, but still it is underneath.
Any alternatives to my feeble attempt below? Or a link to a sample would be great too.
Thanks!
HelpOverlayUIView _overlayView;
public void PresentHelpOverlay()
{
RectangleF windowFullFrame = new RectangleF(0,0,UIScreen.MainScreen.Bounds.Width,UIScreen.MainScreen.Bounds.Height);
// Conversion?
//[aView convertPoint:localPosition toView:nil];
RectangleF overlayFrame = View.ConvertRectFromView(windowFullFrame ,null);
// Clear old one if it exists.
if (_overlayView != null) _overlayView = null;
// Instantiate popup view and add to (in this case the 2nd tier view). This is in an abstract class, if in a concrete one it'd normally just be View.Add
_overlayView = new HelpOverlayUIView(this, overlayFrame);
// tried th, didn't change it.
// this.WantsFullScreenLayout = true;
// _childView.BringSubviewToFront(_overlayView);
_overlayView.Alpha = 0;
_childView.Add (_overlayView);
// Setup event to close without doing anything.
_overlayView.CloseView += (sender, e) => {
Console.WriteLine ("close called");
// animate modal popup's departure
UIView.Animate (
0.5f,
() => {
// Anim Code
_overlayView.Alpha = 0;
},
null
);
};
// animate modal popup's arrival
UIView.Animate (
0.5f,
() => {
// Anim Code
_overlayView.Alpha = 1;
},
null
);
}
(The view is just a UIView with an overload to the Draw() method that places text etc into the view)
You could add the _overlayView to something higher up in the view hierarchy such as the NavigationViewController. If your NavigationViewController is set to be your RootViewController (well, regardless of what is really) you could try this.
((AppDelegate)UIApplication.SharedApplication.Delegate).Window.RootViewController.Add(_overlayView);
You can also bring a subview to the front like this, but this is only to the front of that view, not to the front of everything (which isn't really what you wanted unless _childView was your NavigationViewController).
_childView.BringSubviewToFront(_overlayView);

Resources