Apply CSS StyleSheet to HTML document in webview in Xamarin - xamarin.forms

i have a HTML document rendered from Server Side in Xamarin WebView.
I want to apply CSS Stylesheet to the HTML document in webview.
using (HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse())
{
using (Stream stream = httpResponse.GetResponseStream())
{
string response = (new StreamReader(stream)).ReadToEnd();
ArticleData article = JsonConvert.DeserializeObject<ArticleData>(JsonConvert.DeserializeObject<ArticleDetails>(response).d);
var htmlSource = new HtmlWebViewSource();
htmlSource.Html = "<html><head><link rel='stylesheet' type='text/css' href='Assets/Main.css' /></head><body>" + article.Html + "</body></html>";
webView.Source = htmlSource;
}
}

According to your code, the css is inside the Assets. Due to i did not have the article.Html, i created a local.html in Assets folder for reference.
local.html:
<html>
<head>
<title>webViewSample</title>
<link rel="stylesheet" type="text/css" href="Main.css" />
</head>
<body>
<h1>Xamarin.Forms</h1>
<p>This is a local Android Html page</p>
<img src="XamarinLogo.png" />
</body>
</html>
Main.css:
html,body{margin:0;padding:10px}
body, p, h1 {
font-family: 'Roboto';
}
Use the dependency service to load the CSS and html file from the Assets folder.
[assembly: Xamarin.Forms.Dependency(typeof(BaseUrl_Android))]
namespace App27.Droid
{
public class BaseUrl_Android : IBaseUrl
{
public string Get()
{
return "file:///android_asset/";
}
}
}
Xaml:
<StackLayout>
<Button Clicked="Button_Clicked"></Button>
<WebView x:Name="webView" HeightRequest="500"/>
</StackLayout>
Code behind:
public interface IBaseUrl { string Get(); }
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
private void Button_Clicked(object sender, EventArgs e)
{
var htmlSource = new HtmlWebViewSource();
htmlSource.Html = "<html><head><link rel='stylesheet' type='text/css' href='Main.css' /></head><body>" + " <p><a href='local.html'>next page</a></p>" + "</body></html>";
htmlSource.BaseUrl = DependencyService.Get<IBaseUrl>().Get();
webView.Source = htmlSource;
}
}
Screenshot: https://imgur.com/My83Qvv

Related

CustomPicker Ok and Cancel buttons' color

I have this custompicker class in android project:
public class CustomPickerRenderer : PickerRenderer
{
private Context context;
private IElementController ElementController => Element as IElementController;
private AlertDialog _dialog;
public CustomPickerRenderer(Context context) : base(context)
{
this.context = context;
}
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
if (Control == null || e.NewElement == null) return;
Control.Click += Control_Click1;
}
protected override void Dispose(bool disposing)
{
Control.Click -= Control_Click1;
base.Dispose(disposing);
}
private void Control_Click1(object sender, EventArgs e)
{
Picker model = Element;
var picker = new NumberPicker(Context);
if (model.Items != null && model.Items.Any())
{
picker.MaxValue = model.Items.Count - 1;
picker.MinValue = 0;
picker.SetDisplayedValues(model.Items.ToArray());
picker.WrapSelectorWheel = false;
picker.DescendantFocusability = DescendantFocusability.BlockDescendants;
picker.Value = model.SelectedIndex;
}
var layout = new LinearLayout(Context) { Orientation = Orientation.Vertical };
layout.AddView(picker);
ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, true);
var builder = new AlertDialog.Builder(Context);
builder.SetView(layout);
builder.SetTitle(model.Title ?? "");
//change the text or color here
builder.SetNegativeButton(Html.FromHtml("<font color='#039BE5'>Cancel</font>"), (s, a) =>
{
ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
// It is possible for the Content of the Page to be changed when Focus is changed.
// In this case, we'll lose our Control.
Control?.ClearFocus();
_dialog = null;
});
//change the text or color here
builder.SetPositiveButton(Html.FromHtml("<font color='#039BE5'>OK</font>"), (s, a) =>
{
ElementController.SetValueFromRenderer(Picker.SelectedIndexProperty, picker.Value);
// It is possible for the Content of the Page to be changed on SelectedIndexChanged.
// In this case, the Element & Control will no longer exist.
if (Element != null)
{
if (model.Items.Count > 0 && Element.SelectedIndex >= 0)
Control.Text = model.Items[Element.SelectedIndex];
ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
// It is also possible for the Content of the Page to be changed when Focus is changed.
// In this case, we'll lose our Control.
Control?.ClearFocus();
}
_dialog = null;
});
_dialog = builder.Create();
_dialog.DismissEvent += (ssender, args) =>
{
ElementController?.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
};
_dialog.Show();
}
}
I tried running my project on my phone Xiaomi POCOPHONE F1 (Android 9) and 2 emulators (Android 8.1) and the colors of cancel and ok buttons are designed Perfectly. But when I tried running the project on Huawei PLE-701L and SAMSUNG SM-T365 (Android 5.1) the color of the buttons didn't changed.
Any suggestions?
Get the button object through the API of dialog and set the text color of the button. This method can be personalized. One point needs to be noted: it must be called after show
in your custom renderer,below _dialog.Show();
....
_dialog.Show();
Button btnOk = _dialog.GetButton((int)DialogInterface.ButtonPositive);
btnOk .SetTextColor(Color.Red);
Button btnCancel= _dialog.GetButton((int)DialogInterface.ButtonNegative);
btnCancel.SetTextColor(Color.Red);
add this style in style.xml
<style name="SpinnerDialog" parent="Theme.AppCompat.Light.Dialog">
<item name="android:popupBackground">#ff00ff</item>
<item name="colorPrimary">#ff00ff</item>
<item name="colorPrimaryDark">#ffff00</item>
<item name="colorAccent">#ff0000</item>
</style>
you can change allthe color including buttons.
and you can also use
<style name="AlertDialogCustom" parent="android:Theme.Material.Light.Dialog.Alert">
<item name="android:colorPrimary">#1e87f0</item>
<item name="android:colorAccent">#1e87f0</item>
</style>
<style name="AppCompatDialogStyle" parent="Theme.AppCompat.Light.Dialog">
<item name="colorAccent">#1e87f0</item>
</style>
The Question is answered here: Picker button's color not changing on android 5.1
I added the styles code in the correct answer in the link, and it worked!

Rounded corner for Entry - Xamarin forms UWP

Is there anything possible to customize the radius of Entry to having a slightly rounded corner?
You can use Custom Renderer in xamarin.forms
in iOS
//...
using App11;
using App11.iOS;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(MyEntry), typeof(MyiOSEntry))]
namespace App11.iOS
{
public class MyiOSEntry:EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.Layer.MasksToBounds = true;
Control.Layer.CornerRadius = 10; //set the rounded corner
Control.Layer.BorderColor = UIColor.Red.CGColor;
Control.Layer.BorderWidth = 3;
}
}
}
}
in Android
creat a xml file in the folder Resource->drawable edit_text_style.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:shape="rectangle">
<solid
android:color="#ffffff" />
<corners
android:radius="10dp" />
<stroke
android:width="2dp"
android:color="#3bbdfa" />
</shape>
</item>
in Custom Renderer
using Android.Support.V4.Content.Res;
using App11;
using App11.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(MyEntry), typeof(MyAndriodEntry))]
namespace App11.Droid
{
public class MyAndriodEntry:EntryRenderer
{
public MyAndriodEntry(Context context):base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if(Control!=null)
{
Control.SetBackground(ResourcesCompat.GetDrawable(Resources, Resource.Drawable.edit_text_style, null) );
}
}
}
}
in UWP
create a folder named Styles and add a new item as type Resource Dictionary and name it Dictionary1.xaml
in Dictionary1.xaml put this code for a rounded Textbox .
in Custom Renderer
using App11;
using App11.UWP;
using Windows.UI.Xaml.Controls;
using Xamarin.Forms;
using Xamarin.Forms.Platform.UWP;
[assembly: ExportRenderer(typeof(MyEntry), typeof(MyUWPEntry))]
namespace App11.UWP
{
public class MyUWPEntry:EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if(Control!=null)
{
Control.Style = (Windows.UI.Xaml.Style)App11.UWP.App.Current.Resources["StyleRoundedTextBox"];
}
}
}
}
how do I changed this style and how do I create this code ?
It's simple , in msdn.com search for "objectName" default style in uwp then you will find default style for the object you need . change it in the way you want and add it to application resources directly or link it (like what I did here) then load your style in CustomRenderer
for more detail about UWP yo can refer here
in Forms
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
namespace App11
{
public class MyEntry : Entry
{
public MyEntry()
{
}
}
}
in xxx.cs file
Content = new StackLayout
{
Children = {
new MyEntry {Text = "In Shared Code",}
},
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
For Windows app you can customize an entry using a renderer.
public class CustomEntryRenderer : ViewRenderer<CustomEntry, TextBox>
{
protected override void OnElementChanged(ElementChangedEventArgs<CustomEntry> e)
{
base.OnElementChanged(e);
var textBox = new TextBox();
textBox.BorderThickness = new Windows.UI.Xaml.Thickness(1);
textBox.BorderBrush = new SolidColorBrush(GetSolidColorBrush("#444444").Color);
textBox.CornerRadius = new Windows.UI.Xaml.CornerRadius(10);
this.SetNativeControl(textBox);
}
public SolidColorBrush GetSolidColorBrush(string hex)
{
hex = hex.Replace("#", string.Empty);
byte r = (byte)(Convert.ToUInt32(hex.Substring(0, 2), 16));
byte g = (byte)(Convert.ToUInt32(hex.Substring(2, 2), 16));
byte b = (byte)(Convert.ToUInt32(hex.Substring(4, 2), 16));
SolidColorBrush myBrush = new SolidColorBrush(Windows.UI.Color.FromArgb(255, r, g, b));
return myBrush;
}
}
Holy shmoley it's not that hard.
Unless I'm missing something, just wrap it in a Frame that has IsClippedToBounds set to true and then put a corner radius on the frame.
Maybe there's some reason that's not a good solution, I guess, but it's one I use a lot.

call a java method from javascript in javafx

I have a javafx application. Initially it loads a login page using WebView. Login page takes user name and redirects to another page. In this html page I have a function inside javascript. I want to call a java method while executing the script. but I end up getting an error saying
ReferenceError: Can't find variable: OpenDoc[at 17]
This my html
html>
<body onload="login()">
<div id="jnlpStart_EN">
<H2>Welcome to Home Page</H2>
</div>
</body>
<script type="text/javascript">
function login() {
OpenDoc.passDocId('q56wre');
}
</script>
</html>
This is my java code
public class WebEngineTest1 extends Application {
#Override
public void start(Stage primaryStage) {
WebConsoleListener.setDefaultListener((webView, message, lineNumber, sourceId) -> {
System.out.println(message + "[at " + lineNumber + "]");
});
WebView webView = new WebView();
WebEngine engine = webView.getEngine();
engine.load("http://localhost:8001/app/login");
engine.locationProperty().addListener((obs, oldLocation, newLocation) -> {
if (newLocation != null && newLocation.endsWith("/home")) {
JSObject window = (JSObject) engine.executeScript("window");
window.setMember("OpenDoc", new OpenDoc());
}
});
Scene scene = new Scene(webView, 300, 150);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
public class OpenDoc {
public void passDocId(String id) {
System.out.println(id);
}
}
}
I have found the answer.
Since after login it redirects to an URL. I had to add a listener with documentProperty(). Inside I add the code for calling java method from javascript. So while loading the page I don't get ReferenceError: Can't find variable: OpenDoc[at 17] message since I added the reference already. here is the code
engine.documentProperty().addListener((v, o, n) -> {
String newLocation = webEngine.getLocation();
if (newLocation != null && newLocation.endsWith("/home")) {
JSObject window = (JSObject) engine.executeScript("window");
window.setMember("OpenDoc", new OpenDoc());
}
});
First you have to enable JavaScript on the WebEngine
webEngine.setJavaScriptEnabled(true);
and this line will do the trick
webengine.executeScript("initOpenDoc(\"ID\")");

Why does :host(:hover) not work here?

I am not able to figure out how :host(:hover) works on child custom elements of a parent custom element. Can someone explain how to make this work?
todoitem.html
<!-- import polymer-element's definition -->
<link rel="import" href="packages/polymer/polymer.html">
<polymer-element name="my-li" extends="li">
<style>
:host(:hover){
color: red;
}
</style>
<template>
<content></content>
</template>
<script type="application/dart" src="todoitem.dart"></script>
</polymer-element>
todoitem.dart
import 'package:polymer/polymer.dart';
import "dart:html" as html;
import 'package:logging/logging.dart';
final Logger _widgetlogger = new Logger("todo.item");
#CustomTag('my-li')
class MyListElement extends html.LIElement with Polymer, Observable {
factory MyListElement() => new html.Element.tag('li', 'my-li');
MyListElement.created() : super.created() {
polymerCreated();
}
#override
void attached() {
super.attached();
_widgetlogger.info("todoitem attached");
}
#override
void detached() {
super.detached();
_widgetlogger.info("todoitem detached");
}
}
todowidget.html
<!-- import polymer-element's definition -->
<link rel="import" href="packages/polymer/polymer.html">
<link rel="import" href="todoitem.html">
<polymer-element name="todo-widget" attributes="title">
<template>
<style>
:host(.colored){
color: blue;
}
</style>
<div>
<h1>{{title}}</h1>
<div>
<input id="inputBox" placeholder="Enter Todo item" on-change="{{addToList}}">
<button id="deleteButton" on-click="{{deleteAll}}">Delete All</button>
</div>
<ul id="todolist">
</ul>
</div>
</template>
<script type="application/dart" src="todowidget.dart"></script>
</polymer-element>
Corresponding Dart Script
import 'package:polymer/polymer.dart';
import "dart:html" as html;
import "todoitem.dart";
import 'package:logging/logging.dart';
final Logger _widgetlogger = new Logger("todo.widget");
#CustomTag('todo-widget')
class TodoWidget extends PolymerElement {
#published String title;
html.InputElement todoInput;
// html.ButtonElement deleteButton;
html.UListElement todolist;
#override
void attached() {
super.attached();
todolist = $["todolist"];
todoInput = $["inputBox"];
}
TodoWidget.created() : super.created() {
//This can go into template!!!
if (title == null) {
title = "My Todo App";
}
;
}
void deleteAll(html.Event e, var detail, html.Node target) {
_widgetlogger.info("All items deleted");
todolist.children.clear();
// print("Clicked");
}
void addToList(html.Event e, var detail, html.Node target) {
_widgetlogger.info("Item added");
MyListElement li = new MyListElement();
li
..text = todoInput.value
..classes.add("todoitem")
..onClick.listen((e) => e.target.remove());
todolist.children.add(li);
todoInput.value = "";
}
}
Upon running I see no hovering effect. How can I fix this?
I guess the problem is that the style tag is outside the <template> tag. It should be inside. I played around with your code (same as in your previous question) and moved the style inside the <template> tag without knowing that I was deviating from the code you posted in your question (I built the element from scratch instead copying the code from your question).

How to set initial values for properties in Ext.Net

How can I set the initial values for custom (or even non custom) controls properties in Ext.Net (an .net wrapper for extjs)?
Currently I'm doing the following:
public class CpfField : Ext.Net.TextField {
public CpfField() {
this.SelectOnFocus = true;
this.AllowBlank = false;
this.MaxLength = 14;
this.FieldLabel = "CPF";
this.LabelAlign = Ext.Net.LabelAlign.Top;
this.Plugins.Add(new CpfInputMask());
}
}
As you can see, I'm using the constructor just to set the default values, I'm not overriding any behavior of the control. So far, so good. It works as expected, but I have this.LabelAlign = Ext.Net.LabelAlign.Top set on each control I inherited.
This smells like violating the DRY principle. Is there a way to set this (and other properties) in global scope?
What you have here is fine, although I did notice a couple issues.
The .LabelAlign property must be set at the Container level. The Container must use a FormLayout as well. Unfortunately the .LabelAlign cannot be rendered differently at the Field level.
Setting the .FieldLabel property to "CPF" shouldn't really be required, unless you anticipate all these "CpfField" components being labeled as "CPF". The .FieldLabel is generally set at the Field configuration level, either in markup or code-behind when the field is instantiated.
Another "global" option you could investigate is using a .skin file. The example below demonstrates this option by "globally" setting a property of all TextField components.
The following sample demonstrates several options including a setting the properties in the OnInit event of the object.
Example (.skin)
<%# Register assembly="Ext.Net" namespace="Ext.Net" tagprefix="ext" %>
<ext:TextField runat="server" Icon="Accept" />
Example (.aspx)
<%# Page Language="C#" Theme="Skin1" %>
<%# Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
var form = new FormPanel
{
Height = 215,
Width = 350,
Title = "Example",
Padding = 5,
DefaultAnchor = "100%",
Items = {
new MyField
{
FieldLabel = "My Field"
},
new AnotherField
{
FieldLabel = "Another Field"
},
new TextField
{
FieldLabel = "A TextField"
}
}
};
this.Form.Controls.Add(form);
}
public class MyField : TextField
{
public MyField()
{
this.SelectOnFocus = true;
this.AllowBlank = false;
this.MaxLength = 14;
}
}
public class AnotherField : TextField
{
protected override void OnInit(EventArgs e)
{
this.SelectOnFocus = true;
this.AllowBlank = false;
this.MaxLength = 14;
base.OnInit(e);
}
}
</script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Ext.NET Example</title>
</head>
<body>
<form runat="server">
<ext:ResourceManager runat="server" />
</form>
</body>
</html>
Hope this helps.

Resources