Aplicar estilos a aplicaciones Xamarin.Forms mediante hojas de estilo CSS
Xamarin.Forms también admite aplicar estilo a los elementos visuales mediante hojas de estilo CSS.
Se puede aplicar estilo a aplicaciones Xamarin.Forms mediante CSS. Una hoja de estilos consta de una lista de reglas, con cada regla formada por uno o varios selectores y un bloque de declaración. Un bloque de declaración consta de una lista de declaraciones entre llaves, con cada declaración formada por una propiedad, dos puntos y un valor. Cuando hay varias declaraciones en un bloque, se inserta un punto y coma como separador. En el ejemplo de código siguiente se muestran algunos CSS compatibles con Xamarin.Forms:
navigationpage {
-xf-bar-background-color: lightgray;
}
^contentpage {
background-color: lightgray;
}
#listView {
background-color: lightgray;
}
stacklayout {
margin: 20;
}
.mainPageTitle {
font-style: bold;
font-size: medium;
}
.mainPageSubtitle {
margin-top: 15;
}
.detailPageTitle {
font-style: bold;
font-size: medium;
text-align: center;
}
.detailPageSubtitle {
text-align: center;
font-style: italic;
}
listview image {
height: 60;
width: 60;
}
stacklayout>image {
height: 200;
width: 200;
}
En Xamarin.Forms, las hojas de estilo CSS se analizan y evalúan en tiempo de ejecución, en lugar de en tiempo de compilación, y las hojas de estilo se vuelven a analizar en uso.
Nota:
Actualmente, toda la aplicación de estilo que es posible con la aplicación de estilo XAML no se puede realizar con CSS. Sin embargo, los estilos XAML se pueden usar para complementar CSS para las propiedades que actualmente no son compatibles con Xamarin.Forms. Para obtener más información sobre los estilos XAML, vea Aplicación de estilo a aplicaciones Xamarin.Forms con estilos XAML.
El ejemplo muestra el uso de CSS para aplicar estilo a una aplicación sencilla y se muestra en las capturas de pantalla siguientes:
Consumo de una hoja de estilo
El proceso para agregar una hoja de estilo a una solución es el siguiente:
- Agregue un archivo CSS vacío al proyecto de biblioteca de .NET Standard.
- Establezca la acción de compilación del archivo CSS en EmbeddedResource.
Carga de una hoja de estilos
Hay una serie de enfoques que se pueden usar para cargar una hoja de estilos.
Nota:
Actualmente no es posible cambiar una hoja de estilo en runtime y aplicar la nueva hoja de estilo.
XAML
Una hoja de estilos se puede cargar y analizar con la clase StyleSheet
antes de agregarse a ResourceDictionary
:
<Application ...>
<Application.Resources>
<StyleSheet Source="/Assets/styles.css" />
</Application.Resources>
</Application>
La propiedad StyleSheet.Source
especifica la hoja de estilos como un URI relativo a la ubicación del archivo XAML envolvente, o en relación con la raíz del proyecto si el URI empieza por /
.
Advertencia
El archivo CSS no se cargará si su acción de compilación no está establecida en EmbeddedResource.
Como alternativa, una hoja de estilos se puede cargar y analizar con la clase StyleSheet
, antes de agregarla a un elemento ResourceDictionary
, insertándola en una sección CDATA
:
<ContentPage ...>
<ContentPage.Resources>
<StyleSheet>
<![CDATA[
^contentpage {
background-color: lightgray;
}
]]>
</StyleSheet>
</ContentPage.Resources>
...
</ContentPage>
Para más información sobre los diccionarios de recursos, consulta Diccionarios de recursos.
C#
En C#, se puede cargar una hoja de estilos desde StringReader
y agregarse a ResourceDictionary
:
public partial class MyPage : ContentPage
{
public MyPage()
{
InitializeComponent();
using (var reader = new StringReader("^contentpage { background-color: lightgray; }"))
{
this.Resources.Add(StyleSheet.FromReader(reader));
}
}
}
El argumento para el método StyleSheet.FromReader
es TextReader
que ha leído la hoja de estilos.
Selección de elementos y aplicación de propiedades
CSS usa selectores para determinar a qué elementos va dirigido. Los estilos con selectores coincidentes se aplican consecutivamente, en orden de definición. Los estilos definidos en un elemento específico siempre se aplican en último lugar. Para obtener más información sobre los selectores admitidos, vea Referencia del selector.
CSS usa propiedades para aplicar estilo a un elemento seleccionado. Cada propiedad tiene un conjunto de valores posibles y algunas propiedades pueden afectar a cualquier tipo de elemento, mientras que otras se aplican a grupos de elementos. Para obtener más información sobre las propiedades admitidas, vea Referencia de propiedades.
Las hojas de estilos secundarias siempre invalidan las hojas de estilos primarias si establecen las mismas propiedades. Por lo tanto, se siguen las siguientes reglas de precedencia al aplicar estilos que establecen las mismas propiedades:
- Si se establecen las mismas propiedades, el estilo definido en los recursos de la aplicación se sobrescribirá mediante un estilo definido en los recursos de la página.
- Un estilo definido en los recursos de página se sobrescribirá mediante un estilo definido en los recursos de control, si establecen las mismas propiedades.
- Si se establecen las mismas propiedades, el estilo definido en los recursos de la aplicación se sobrescribirá mediante un estilo definido en los recursos de control.
Importante
No se admiten variables CSS.
Selección de elementos por tipo
Los elementos del árbol visual se pueden seleccionar por tipo con el selector element
sin distinción entre mayúsculas y minúsculas:
stacklayout {
margin: 20;
}
Este selector identifica los elementos StackLayout
de las páginas que consumen la hoja de estilos y establece sus márgenes en un grosor uniforme de 20.
Nota:
El selector element
no identifica las subclases del tipo especificado.
Selección de elementos por clase base
Los elementos del árbol visual se pueden seleccionar mediante la clase base con el selector ^base
sin distinción entre mayúsculas y minúsculas:
^contentpage {
background-color: lightgray;
}
Este selector identifica los elementos ContentPage
que consumen la hoja de estilos y establece su color de fondo en lightgray
.
Nota:
El selector ^base
es específico de Xamarin.Forms, y no forma parte de la especificación CSS.
Selección de un elemento por nombre
Los elementos individuales del árbol visual se pueden seleccionar con el selector #id
sin distinción entre mayúsculas y minúsculas:
#listView {
background-color: lightgray;
}
Este selector identifica el elemento cuya propiedad StyleId
está establecida en listView
. Pero si la propiedad StyleId
no está establecida, el selector volverá a usar el atributo x:Name
del elemento. Por lo tanto, en el ejemplo XAML siguiente, el selector #listView
identificará el ListView
cuyo atributo x:Name
está establecido en listView
y establecerá el color de fondo en lightgray
.
<ContentPage ...>
<ContentPage.Resources>
<StyleSheet Source="/Assets/styles.css" />
</ContentPage.Resources>
<StackLayout>
<ListView x:Name="listView" ...>
...
</ListView>
</StackLayout>
</ContentPage>
Selección de elementos con un atributo de clase específico
Los elementos con un atributo de clase específico se pueden seleccionar con el selector .class
sin distinción entre mayúsculas y mayúsculas:
.detailPageTitle {
font-style: bold;
font-size: medium;
text-align: center;
}
.detailPageSubtitle {
text-align: center;
font-style: italic;
}
Una clase CSS se puede asignar a un elemento XAML estableciendo la propiedad StyleClass
del elemento en el nombre de clase CSS. Por lo tanto, en el ejemplo XAML siguiente, los estilos definidos por la clase .detailPageTitle
se asignan al primer Label
, mientras que los estilos definidos por la clase .detailPageSubtitle
se asignan al segundo Label
.
<ContentPage ...>
<ContentPage.Resources>
<StyleSheet Source="/Assets/styles.css" />
</ContentPage.Resources>
<ScrollView>
<StackLayout>
<Label ... StyleClass="detailPageTitle" />
<Label ... StyleClass="detailPageSubtitle"/>
...
</StackLayout>
</ScrollView>
</ContentPage>
Selección de elementos secundarios
Los elementos secundarios del árbol visual se pueden seleccionar con el selector element element
sin distinción entre mayúsculas y minúsculas:
listview image {
height: 60;
width: 60;
}
Este selector identifica los elementos secundarios Image
de los elementos ListView
y establece su alto y ancho en 60. Por lo tanto, en el ejemplo de XAML siguiente, el selector listview image
identificará que Image
es un elemento secundario de ListView
y establece su alto y ancho en 60.
<ContentPage ...>
<ContentPage.Resources>
<StyleSheet Source="/Assets/styles.css" />
</ContentPage.Resources>
<StackLayout>
<ListView ...>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
...
<Image ... />
...
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
Nota:
El selector element element
no requiere que el elemento secundario sea un elemento secundario directo del elemento primario: el elemento secundario puede tener un elemento primario diferente. La selección se produce siempre que un antecesor sea el primer elemento especificado.
Selección de elementos secundarios directos
Los elementos secundarios directos del árbol visual se pueden seleccionar con el selector element>element
sin distinción entre mayúsculas y minúsculas:
stacklayout>image {
height: 200;
width: 200;
}
Este selector identifica todos los elementos Image
que son elementos secundarios directos de StackLayout
elementos y establece su alto y ancho en 200. Por lo tanto, en el ejemplo XAML siguiente, el selector stacklayout>image
identificará que Image
es un elemento secundario directo de StackLayout
y establece su alto y ancho en 200.
<ContentPage ...>
<ContentPage.Resources>
<StyleSheet Source="/Assets/styles.css" />
</ContentPage.Resources>
<ScrollView>
<StackLayout>
...
<Image ... />
...
</StackLayout>
</ScrollView>
</ContentPage>
Nota:
El selector element>element
requiere que el elemento secundario sea un elemento secundario directo del elemento primario.
Referencia del selector
Los siguientes selectores CSS son compatibles con Xamarin.Forms:
Selector | Ejemplo | Descripción |
---|---|---|
.class |
.header |
Selecciona todos los elementos con la propiedad StyleClass que contiene "header". Tenga en cuenta que este selector distingue mayúsculas de minúsculas. |
#id |
#email |
Selecciona todos los elementos con StyleId establecido en email . Si StyleId no se establece, se usará x:Name . Al usar XAML, x:Name es preferible a StyleId . Tenga en cuenta que este selector distingue mayúsculas de minúsculas. |
* |
* |
Selecciona todos los elementos. |
element |
label |
Selecciona todos los elementos de tipo Label , pero no subclases. Tenga en cuenta que este selector no distingue mayúsculas de minúsculas. |
^base |
^contentpage |
Selecciona todos los elementos con ContentPage como clase base, incluido el propio elemento ContentPage . Tenga en cuenta que este selector no distingue mayúsculas de minúsculas y no forma parte de la especificación CSS. |
element,element |
label,button |
Selecciona todos los elementos Button y todos los elementos Label . Tenga en cuenta que este selector no distingue mayúsculas de minúsculas. |
element element |
stacklayout label |
Selecciona todos los elementos Label dentro de StackLayout . Tenga en cuenta que este selector no distingue mayúsculas de minúsculas. |
element>element |
stacklayout>label |
Selecciona todos los elementos Label con StackLayout como elemento primario directo. Tenga en cuenta que este selector no distingue mayúsculas de minúsculas. |
element+element |
label+entry |
Selecciona todos los elementos Entry directamente después de Label . Tenga en cuenta que este selector no distingue mayúsculas de minúsculas. |
element~element |
label~entry |
Selecciona todos los elementos Entry precedidos de Label . Tenga en cuenta que este selector no distingue mayúsculas de minúsculas. |
Los estilos con selectores coincidentes se aplican consecutivamente, en orden de definición. Los estilos definidos en un elemento específico siempre se aplican en último lugar.
Sugerencia
Los selectores se pueden combinar sin limitación, como StackLayout>ContentView>label.email
.
Actualmente no se admiten los siguientes selectores:
[attribute]
@media
y@supports
:
y::
Nota:
No se admiten la especificidad ni la anulación de especificidad.
Referencia de propiedades
Las siguientes propiedades CSS son compatibles con Xamarin.Forms (en la columna Valores, los tipos van en cursiva, mientras que los literales de cadena van en gray
):
Propiedad | Se aplica a | Valores | Ejemplo |
---|---|---|---|
align-content |
FlexLayout |
stretch | center | start | end | spacebetween | spacearound | spaceevenly | flex-start | flex-end | space-between | space-around | initial |
align-content: space-between; |
align-items |
FlexLayout |
stretch | center | start | end | flex-start | flex-end | initial |
align-items: flex-start; |
align-self |
VisualElement |
auto | stretch | center | start | end | flex-start | flex-end | initial |
align-self: flex-end; |
background-color |
VisualElement |
color | initial |
background-color: springgreen; |
background-image |
Page |
string | initial |
background-image: bg.png; |
border-color |
Button , , Frame , ImageButton |
color | initial |
border-color: #9acd32; |
border-radius |
BoxView , Button , , Frame , ImageButton |
double | initial |
border-radius: 10; |
border-width |
Button , ImageButton |
double | initial |
border-width: .5; |
color |
ActivityIndicator , BoxView , Button , CheckBox , , Editor DatePicker , Entry , Label Picker ProgressBar SearchBar Switch TimePicker |
color | initial |
color: rgba(255, 0, 0, 0.3); |
column-gap |
Grid |
double | initial |
column-gap: 9; |
direction |
VisualElement |
ltr | rtl | inherit | initial |
direction: rtl; |
flex-direction |
FlexLayout |
column | columnreverse | row | rowreverse | row-reverse | column-reverse | initial |
flex-direction: column-reverse; |
flex-basis |
VisualElement |
float | auto | initial Además, se puede especificar un rango del 0 % al 100 % con el signo % . |
flex-basis: 25%; |
flex-grow |
VisualElement |
float | initial |
flex-grow: 1.5; |
flex-shrink |
VisualElement |
float | initial |
flex-shrink: 1; |
flex-wrap |
VisualElement |
nowrap | wrap | reverse | wrap-reverse | initial |
flex-wrap: wrap-reverse; |
font-family |
Button , DatePicker , Editor , Entry , Label , Picker , SearchBar , , TimePicker Span |
string | initial |
font-family: Consolas; |
font-size |
Button , DatePicker , Editor , Entry , Label , Picker , SearchBar , , TimePicker Span |
double | namedsize | initial |
font-size: 12; |
font-style |
Button , DatePicker , Editor , Entry , Label , Picker , SearchBar , , TimePicker Span |
bold | italic | initial |
font-style: bold; |
height |
VisualElement |
double | initial |
min-height: 250; |
justify-content |
FlexLayout |
start | center | end | spacebetween | spacearound | spaceevenly | flex-start | flex-end | space-between | space-around | initial |
justify-content: flex-end; |
letter-spacing |
Button , DatePicker , Editor , Entry , Label , Picker , SearchBar , SearchHandler , , Span TimePicker |
double | initial |
letter-spacing: 2.5; |
line-height |
Label , Span |
double | initial |
line-height: 1.8; |
margin |
View |
grosor | initial |
margin: 6 12; |
margin-left |
View |
grosor | initial |
margin-left: 3; |
margin-top |
View |
grosor | initial |
margin-top: 2; |
margin-right |
View |
grosor | initial |
margin-right: 1; |
margin-bottom |
View |
grosor | initial |
margin-bottom: 6; |
max-lines |
Label |
int | initial |
max-lines: 2; |
min-height |
VisualElement |
double | initial |
min-height: 50; |
min-width |
VisualElement |
double | initial |
min-width: 112; |
opacity |
VisualElement |
double | initial |
opacity: .3; |
order |
VisualElement |
int | initial |
order: -1; |
padding |
Button , ImageButton , , Layout , Page |
grosor | initial |
padding: 6 12 12; |
padding-left |
Button , ImageButton , , Layout , Page |
double | initial |
padding-left: 3; |
padding-top |
Button , ImageButton , , Layout , Page |
double | initial |
padding-top: 4; |
padding-right |
Button , ImageButton , , Layout , Page |
double | initial |
padding-right: 2; |
padding-bottom |
Button , ImageButton , , Layout , Page |
double | initial |
padding-bottom: 6; |
position |
FlexLayout |
relative | absolute | initial |
position: absolute; |
row-gap |
Grid |
double | initial |
row-gap: 12; |
text-align |
Entry , EntryCell , , Label , SearchBar |
left | top | right | bottom | start | center | middle | end | initial . left y right deben evitarse en entornos de derecha a izquierda. |
text-align: right; |
text-decoration |
Label , Span |
none | underline | strikethrough | line-through | initial |
text-decoration: underline, line-through; |
text-transform |
Button ,Editor , Entry , Label , , , SearchBar SearchHandler |
none | default | uppercase | lowercase | initial |
text-transform: uppercase; |
transform |
VisualElement |
none , rotate , rotateX , rotateY , scale , scaleX , scaleY , translate , translateX , , translateY initial |
transform: rotate(180), scaleX(2.5); |
transform-origin |
VisualElement |
double, double | initial |
transform-origin: 7.5, 12.5; |
vertical-align |
Label |
left | top | right | bottom | start | center | middle | end | initial |
vertical-align: bottom; |
visibility |
VisualElement |
true | visible | false | hidden | collapse | initial |
visibility: hidden; |
width |
VisualElement |
double | initial |
min-width: 320; |
Nota:
initial
es un valor válido para todas las propiedades. Borra el valor (se restablece al valor predeterminado) que se estableció desde otro estilo.
Actualmente no se admiten las siguientes propiedades:
all: initial
.- Propiedades de diseño (cuadro o cuadrícula).
- Propiedades abreviadas, como
font
yborder
.
Además, no hay ningún valor inherit
y, por tanto, no se admite la herencia. Por lo tanto, no puedes, por ejemplo, establecer la propiedad font-size
en un diseño y esperar que todas las instancias Label
del diseño hereden el valor. La única excepción es la propiedad direction
, que tiene un valor predeterminado de inherit
.
Los elementos de destino Span
tienen un problema conocido que impide que los intervalos sean el destino de los estilos CSS por elemento y nombre (mediante el símbolo #
). El elemento Span
deriva de GestureElement
, que no tiene la propiedad StyleClass
, por lo que los intervalos no admiten el destino de la clase CSS. Para obtener más información, consulte No se puede aplicar el estilo CSS al control Span.
Propiedades específicas de Xamarin.Forms
También se admiten las siguientes propiedades CSS específicas de Xamarin.Forms (en la columna Valores, los tipos van en cursiva, mientras que los literales de cadena van en gray
):
Propiedad | Se aplica a | Valores | Ejemplo |
---|---|---|---|
-xf-bar-background-color |
NavigationPage , TabbedPage |
color | initial |
-xf-bar-background-color: teal; |
-xf-bar-text-color |
NavigationPage , TabbedPage |
color | initial |
-xf-bar-text-color: gray |
-xf-horizontal-scroll-bar-visibility |
ScrollView |
default | always | never | initial |
-xf-horizontal-scroll-bar-visibility: never; |
-xf-max-length |
Entry , , Editor , SearchBar |
int | initial |
-xf-max-length: 20; |
-xf-max-track-color |
Slider |
color | initial |
-xf-max-track-color: red; |
-xf-min-track-color |
Slider |
color | initial |
-xf-min-track-color: yellow; |
-xf-orientation |
ScrollView , StackLayout |
horizontal | vertical | both | initial . both solo se admite en ScrollView . |
-xf-orientation: horizontal; |
-xf-placeholder |
Entry , , Editor , SearchBar |
quoted text | initial |
-xf-placeholder: Enter name; |
-xf-placeholder-color |
Entry , , Editor , SearchBar |
color | initial |
-xf-placeholder-color: green; |
-xf-spacing |
StackLayout |
double | initial |
-xf-spacing: 8; |
-xf-thumb-color |
Slider , Switch |
color | initial |
-xf-thumb-color: limegreen; |
-xf-vertical-scroll-bar-visibility |
ScrollView |
default | always | never | initial |
-xf-vertical-scroll-bar-visibility: always; |
-xf-vertical-text-alignment |
Label |
start | center | end | initial |
-xf-vertical-text-alignment: end; |
-xf-visual |
VisualElement |
string | initial |
-xf-visual: material; |
Propiedades específicas de Shell Xamarin.Forms
También se admiten las siguientes propiedades CSS específicas de Shell Xamarin.Forms (en la columna Valores, los tipos van en cursiva, mientras que los literales de cadena van en gray
):
Propiedad | Se aplica a | Valores | Ejemplo |
---|---|---|---|
-xf-flyout-background |
Shell |
color | initial |
-xf-flyout-background: red; |
-xf-shell-background |
Element |
color | initial |
-xf-shell-background: green; |
-xf-shell-disabled |
Element |
color | initial |
-xf-shell-disabled: blue; |
-xf-shell-foreground |
Element |
color | initial |
-xf-shell-foreground: yellow; |
-xf-shell-tabbar-background |
Element |
color | initial |
-xf-shell-tabbar-background: white; |
-xf-shell-tabbar-disabled |
Element |
color | initial |
-xf-shell-tabbar-disabled: black; |
-xf-shell-tabbar-foreground |
Element |
color | initial |
-xf-shell-tabbar-foreground: gray; |
-xf-shell-tabbar-title |
Element |
color | initial |
-xf-shell-tabbar-title: lightgray; |
-xf-shell-tabbar-unselected |
Element |
color | initial |
-xf-shell-tabbar-unselected: cyan; |
-xf-shell-title |
Element |
color | initial |
-xf-shell-title: teal; |
-xf-shell-unselected |
Element |
color | initial |
-xf-shell-unselected: limegreen; |
Color
Se admiten los valores color
siguientes:
X11
colores, que coinciden con colores CSS, colores predefinidos de UWP y Xamarin.Forms colores. Tenga en cuenta que estos valores de color no distinguen mayúsculas de minúsculas.- colores hexadecimales:
#rgb
,#argb
,#rrggbb
,#aarrggbb
- colores rgb:
rgb(255,0,0)
,rgb(100%,0%,0%)
. Los valores válidos están en el rango entre 0 y 255 o entre 0 % y 100 %. - colores rgba:
rgba(255, 0, 0, 0.8)
,rgba(100%, 0%, 0%, 0.8)
. El valor de opacidad está en el rango 0,0-1,0. - Colores hsl:
hsl(120, 100%, 50%)
. El valor h está en el rango entre 0 y 360, mientras que s y l están en el rango entre 0% y 100%. - colores hsla:
hsla(120, 100%, 50%, .8)
. El valor de opacidad está en el rango 0,0-1,0.
Thickness
Se admiten uno, dos, tres o cuatro valores thickness
, cada uno separado por espacios en blanco:
- Un valor único indica un grosor uniforme.
- Dos valores indican el grosor vertical y horizontal.
- Tres valores indican el grosor superior, después horizontal (izquierda y derecha), después inferior.
- Cuatro valores indican el grosor superior, después derecho, inferior e izquierdo.
Nota:
Los valores thickness
CSS difieren de los valores Thickness
XAML. Por ejemplo, en XAML, un valor Thickness
de dos indica el grosor horizontal y vertical, mientras que un valor Thickness
de cuatro indica el grosor izquierdo, después superior, derecho e inferior. Además, los valores Thickness
XAML están delimitados por comas.
NamedSize
Se admiten los siguientes valores namedsize
que no distinguen mayúsculas de minúsculas :
default
micro
small
medium
large
El significado exacto de cada valor namedsize
es dependiente de la plataforma y de la vista.
Funciones
Los degradados lineales y radiales se pueden especificar mediante las funciones CSS linear-gradient()
y radial-gradient()
, respectivamente. El resultado de estas funciones debe asignarse a la propiedad background
de un control.
CSS en Xamarin.Forms con Xamarin.University
Xamarin.Forms Vídeo CSS 3.0