How to set style in Xamarin programmatically / code - behind - xamarin.forms

I need to set style at the back of the code. How do I achieve that? I have set style in the app, however I am using on Idom and seems I can't add OnPlatform to the same style so I have decided to keep on Idiom and set this in the back of the page
I have this and this throws an exception
if (DefaultSettings.DevicePlatform == "iOS" )
{
layout.Style = (Style)Resources["Relative"];
}
else
{
layout.Style = (Style)Resources["RelativeAndroid"];
}

App.xaml
<Style x:Key="YouriOSStyle" TargetType="RelativeLayout">
<Setter Property="BackgroundColor" Value="Blue"/>
</Style>
<Style x:Key="YourAndroidStyle" TargetType="RelativeLayout">
<Setter Property="BackgroundColor" Value="Red"/>
</Style>
Code behind
// better statement would be this
if(Device.RuntimePlatform == Device.iOS)
{
layout.SetDynamicResource(RelativeLayout.StyleProperty, "YouriOSStyle");
}
else
{
layout.SetDynamicResource(RelativeLayout.StyleProperty, "YourAndroidStyle");
}

Related

tailwind dark mode isn't extending fully when scrolling all the way on page

using dark mode in a nextjs web app with tailwind, when scrolling, if you scroll past the scroll container (almost like your bouncing off the bottom or top of the page when scrolling), the dark mode isn't extending all the way, so the color isn't applying and it's just the previous color underneath (white in this case), what is the reason for this and is there a way to extend the dark mode fully?
Browsers that don't work
Firefox
Brave
Chrome
Browsers that do work
Safari
stackoverflow and tailwindcss.com in dark mode handle this well and the dark mode extends fully on the whole page
_app.tsx
<Store state={state} dispatch={dispatch}>
<Head>
<meta charSet="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
</Head>
<div className="h-screen dark dark:bg-black dark:text-white overscroll-auto lg:overscroll-contain">
<Component {...pageProps} id="app" />
</div>
</Store>{" "}
You must apply the styles to the body or :root (HTML) element. For the examples, I'll show them applied to the :root element.
You have two primary options in Next.js - global stylesheet or inline.
Global stylesheet with tailwind directives
Global styles
global.css
#tailwind base;
#layer base {
:root {
#apply dark:bg-black dark:text-white;
}
}
inline class
To apply styles inline, you must create a custom _document page. Again, you can apply the styles to either the body or html tags.
_document.js
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html className="dark:bg-black dark:text-white">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
I believe you need to add these classes to the <body> of the document, not just the main div.
There are a few ways to do add css classes to the body in NextJS, but one of the more common ways is to add it in a useEffect or componentDidMount of your Layout component depending on what kind it is.
For example:
useEffect(() => {
document.querySelector("body").classList.add("dark dark:bg-black dark:text-white");
}, []);
I was running into the same problem. Turns out it was because my dark background/foreground color styling was on a React component (a container layout component) rather than being on the body element.
I fixed it by setting the dark background/foreground directly on the body element in my css file:
#layer base {
body {
#apply dark:bg-slate-800 dark:text-white;
}
}
Then in your pages/_app.jsx file or wherever, you can call document.documentElement.classList.add("dark"); and the dark mode will be set properly even on scroll.
https://tailwindcss.com/docs/dark-mode
I tried all of previous answers and none of them worked for me. The only thing that finally worked was to create a _document.js, and add an id to the HTML section:
_document.js
import React from 'react'
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html id="html" className="bg-white">
<Head />
<body className="bg-bg-light dark:bg-bg-dark">
<Main />
<NextScript />
</body>
</Html>
)
}
Then add and remove the dark background (without the 'dark:' prefix) during the toggle:
DarkMode.jsx
useEffect(() => {
if (darkMode !== undefined) {
if (darkMode) {
document.body.classList.add("dark");
document.getElementById("html").classList.add("bg-black")
} else if (!darkMode) {
document.body.classList.remove("dark");
document.getElementById("html").classList.remove("bg-black")
}
}
}, [darkMode])
I did not add the tailwind directive to globals.css
Thanks to Sean W for setting me in the right direction.

Why doesn't my TemplateBinding to my custom TemplatedView's BindableProperty work

Here's my XAML:
<?xml version="1.0" encoding="UTF-8"?>
<TemplatedView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:control="clr-namespace:Core.View.Control"
x:Class="Core.View.Control.MyButton">
<TemplatedView.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="MyButtonTemplate">
<Grid BackgroundColor="Teal">
<!-- other irrelevant stuff. Trust me, it's irrelevant. -->
<Grid x:Name="MyGrid" Grid.Row="1" ColumnSpacing="0" BackgroundColor="{TemplateBinding Parent.BGCol}"> <!-- Can't get this TemplateBinding to work -->
<!-- If I change the above to something static, like BackgroundColor="Orange", it works. -->
</ControlTemplate>
<Style TargetType="TemplatedView" x:Key="MyButtonStyle">
<Setter Property="ControlTemplate" Value="{StaticResource MyButtonTemplate}" />
</Style>
And my code behind:
namespace Core.View.Control
{
public partial class MyButton : TemplatedView
{
public static readonly BindableProperty BGColProperty =
BindableProperty.Create("BGCol", typeof(Color), typeof(MyButton), Color.Orange);
public Color BGCol
{
get
{
return (Color)GetValue(BGColProperty);
}
set
{
SetValue(BGColProperty, value);
}
}
public MyButton()
{
InitializeComponent();
Style = (Style)this.Resources["MyButtonStyle"];
}
// ...
If I change BGColproperty to be of type string and use "Orange" instead of Color.Orange everywhere...it still doesn't work.
How do I bind the background property of the Grid control in my ControlTemplate to BGCol?
[ignore]
Irrelevant text because SO is still not happy, saying too much code.
Sometimes code with inline comments (as I've done) pretty much explains it better than any amount of text can, and you'd think that a site like SO would understand this, but nah.
More blabber.
More still.
Oh here we go, this seems enough.
[/ignore]
<Grid x:Name="MyGrid" BackgroundColor="{TemplateBinding BGCol}" >
Template Bindings go to the control, so the Parent is just confusing it.

How to get navigation bar background color?

In my Xamarin.Forms app, I want my Grid background color to be the same as the Navigation Bar's background color, something like this:
BackgroundColor="{StaticResource BarBackgroundColor}"
How can I do this?
You can retrieve the color of your navbar by casting your current page to a navigation page. Then you can simply change the color of your grid with that retrieved color. On the OnAppearing override of your page, use the following code to obtain your nav bar color:
protected override void OnAppearing()
{
var navPage = Application.Current.MainPage as NavigationPage;
if (navPage != null)
{
var barColor = navPage.BarBackgroundColor;
}
base.OnAppearing();
}
Or, as someone mentioned earlier, you can predefine your colors in App.xaml and then simple use it from there.
<Style TargetType="NavigationPage">
<Setter Property="BarBackgroundColor" Value="Blue"/>
<Setter Property="BarTextColor" Value="White"/>
</Style>
The BarBackgroundProperty is an attached property from NavigationPage. Be aware that it can change on every page you push to your NavigationPage.
Supposing you have an App.Current.MainPage set like this:
Page main = new MainPage();
Page navigation = new NavigationPage(main)
{
BarBackgroundColor = Color.Red,
BarTextColor = Color.Yellow
};
The navigation page is the one that owns the BarBackgroundColor property. So if you want to retrieve it, you should get it from there. I can't see how you can get this through a StaticResource.
I guess you can achieve this through a property on your viewmodel. For example:
public class MyViewModel
{
...
public Color BarBackgroundColor
{
get
{
return ((NavigationPage)App.Current.MainPage)?.BarBackgroundColor;
}
}
...
}
And to use it on your XAML (Once MyViewModel {or some inheritance of it} is the BindingContext or your page):
BackgroundColor="{Binding BarBackgroundColor}"
I hope it helps.
You may use global style by placing the code below into App.xaml
<Application.Resources>
<ResourceDictionary>
<Color x:Key="NavigationPrimary">#1A237E</Color>
<Style TargetType="NavigationPage">
<Setter Property="BarBackgroundColor" Value="{StaticResource NavigationPrimary}" />
<Setter Property="BarTextColor" Value="White" />
</Style>
<Style TargetType="Grid">
<Setter Property="BackgroundColor" Value="{StaticResource NavigationPrimary}" />
</Style>
</ResourceDictionary>
</Application.Resources>

Problem with HtmlPanelGrid.setRowClasses()

I have one more question! I am trying to configure HtmlPanelGrid from bean. I bound panelGrid to this bean and want to set css row classes.
Here is me stylesheet.css:
.list-row-even {
background-color: silver;
}
.list-row-odd {
background-color: red;
}
my jsf page:
<rich:tab label="Top-List" id="screenTop">
<h:panelGrid id="topListTable" binding="#{chartBean.topListTable}" />
</rich:tab>
and my bean:
public TopListChartWrapper(Iterator<Entry> treeIt) {
this.grid = new HtmlPanelGrid();
//this.grid.setBgcolor("yellow");
this.grid.setColumns(2);
this.grid.setBorder(0);
this.grid.setCellpadding("0");
this.grid.setCellspacing("0");
this.grid.setWidth("100%");
this.grid.setRowClasses("list-row-even, list-row-odd");
this.treeIterator = treeIt;
this.prepareGrid();
}
Any ideas? maybe somewhere I need register my stylesheet?
Thanks!
Sorry - about forget the question)
I figure out what was wrong:
I need replace the line:
link href="./css/default.css" rel="stylesheet" type="text/css"
with this one:
link href="#{facesContext.externalContext.requestContextPath}/css/default.css" rel="styleSheet" type="text/css"/
Thanks!

Allowing the <font> tag to override CSS?

I have some user generated content I'm trying to render on my site. The rich text box editor I'm using renders font changes using <font /> tags, which are overridden by CSS on the page.
Does anyone know if there is a way to allow rules defined using the <font /> tag to show through?
UPDATE
Since changing the control I'm using for my rich text editor is not an option and my users have no knowledge of HTML to understand the difference between a <font> tag and any other type of tag, I had no choice but to create a hack to fix my problem. Below is the code I used to solve it. It's a jQuery script that changes all <font /> tag attributes into inline CSS.
(function() {
$('font[size]').each(function() {
var fontSize = this.size;
if (fontSize == 1) {
$(this).css("font-size", 8);
} else if (fontSize == 2) {
$(this).css("font-size", 9);
} else if (fontSize == 3) {
$(this).css("font-size", 11);
} else if (fontSize == 4) {
$(this).css("font-size", 15);
} else if (fontSize == 5) {
$(this).css("font-size", 20);
} else if (fontSize == 6) {
$(this).css("font-size", 25);
}
});
$('font[face]').each(function() {
$(this).css('font-family', this.face);
});
$('font[color]').each(function() {
$(this).css('color', this.color);
});
})();
A year late, but thought I'd share nonetheless.
I was frustrated by this, as well. I was using a freeware RTE JavaScript component that produced <FONT /> tags. It wasn't convenient to replace it, as it was for a client and it was a callback to fix this CSS override problem.
Unfortunately, none of the other solutions worked in my case, so after thinking I came up with this JavaScript solution:
var fontEl=document.getElementsByTagName("font");
for(var i=0;i<fontEl.length;i++) {
var f = fontEl[i];
if(f.size)
f.style.fontSize=(Math.round(parseInt(f.size)*12*0.6)).toString()+'px';
if(f.face)
f.style.fontFamily=f.face;
if(f.color)
f.style.color=f.color;
}
The formula for converting font size is incorrect, but accurate enough to produce believable results.
I would suggest overriding the CSS with your own styles that implement the !important attribute.
div.MyClass p
{
font-size: 0.7em !important;
}
The font tag, technically should override most styles as long as it's the closest element to the raw text.
If it's failing it's likely due to the CSS using the !important attribute to override it.
You could convert it to a style tag on the element. Anything in that would take precedence over style sheet defined rules.
Honestly? Get a new rich text editor! TinyMCE or FCKeditor are both okay choices. Either that or educate your users to understand that the styles they set in the editor won't necessarily appear that way when published. Once thing I've done with FCKeditor in the past is limit its toolbar to the basics, like lists, links, headings etc., no styling options whatsoever.
<font> is just an element like any other; it can be styled using CSS. You can write CSS to allow the font tag's styles to push down as follows:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
<style type="text/css">
body { color: black}
a { color: red; font-family: Sans; font-size: 14px;}
font * { color: inherit; font-family: inherit; font-size: inherit}
</style>
</head>
<body>
This is outside inside outside. <font color="green" face="Times New Roman" size="20">Outside inside outside</font>.
</body>
</html>

Resources