Trucos para .NET MAUI (segunda parte)

Pues eso… seguimos con los trucos para .NET MAUI, en la primera parte te mostré cómo configurar el proyecto para usar las plataformas que prefieras y cómo configurar el aprovisionamiento para iOS (necesitas una cuenta de Apple Developer). Ahora vamos a ver algunas cosillas referentes al diseño de la aplicación.

Para poder mostrarte estos trucos, he creado una aplicación para .NET MAUI con Visual Studio 2022 (community), pero no la versión Preview, ya que a la hora de escribir esto, la tengo desinstalada y así uso el .NET 6.0 (que es el que por ahora me está dando menos problemas, al menos teniendo el .NET 6 y el .NET 7 RC1).
La versión de Visual Studio 2022 es:
Microsoft Visual Studio Community 2022 (64-bit) Version 17.3.5

Acabo de instalar la versión 17.3.6 y sigue funcionando bien 😉

Truco 4: Mostrar bien los Frame sin que se corten

Cuando añades un Frame se suelen cortar los bordes (ver la figura 1)

Figura 1. Los frame se cortan las líneas

El código XAML para mostrar esto es el siguiente:

<ScrollView>
    <VerticalStackLayout
        Padding="10,0"
        VerticalOptions="Center">

        <Frame>
            <VerticalStackLayout Spacing="25">
                    <Image
                            Source="dotnet_bot.png"
                            SemanticProperties.Description="Cute dot net bot waving hi to you!"
                            HeightRequest="200"
                            HorizontalOptions="Center" />

                    <Label
                            Text="Hello, World!"
                            SemanticProperties.HeadingLevel="Level1"
                            FontSize="32"
                            HorizontalOptions="Center" />

                    <Label
                            Text="Welcome to .NET Multi-platform App UI"
                            SemanticProperties.HeadingLevel="Level2"
                            SemanticProperties.Description="Welcome to dot net Multi platform App U I"
                            FontSize="18"
                            HorizontalOptions="Center" />

                    <Button
                            x:Name="CounterBtn"
                            Text="Click me"
                            SemanticProperties.Hint="Counts the number of times you click"
                            Clicked="OnCounterClicked"
                            HorizontalOptions="Center" />

            </VerticalStackLayout>
        </Frame>
    </VerticalStackLayout>
</ScrollView>

Lo deseable es que esté como en la figura 2.

Figura 2. Los Frame deben mostrar todos los bordes

El truco consiste en añadir un margen al StackLayout que esté contenido en el Frame.

<Frame>
    <VerticalStackLayout Spacing="25" Margin="4">

¿Fácil verdad?

Nota:
Este fallo solo ocurre en las aplicaciones de Windows (WinUI)

Tal como te acabo de decir, este fallo (de que se corten las líneas del Frame) solo ocurre en las aplicaciones para Windows (WinUI), al menos en iOS y Android no pasa, tal como puedes ver en las capturas 3 y 4.

Figura 3. La app de prueba en un iPhone 7 plus (iOS)
Figura 4. La app funcionando en un Pixel 4a (Android)

En realidad, al menos en iOS y Android, da igual que esté lo de Margin = «4» como que no, el efecto es prácticamente el mismo.

Truco 5: Cambiar el tamaño de la ventana en Windows

Otro de los problemas (al menos con la compilación actual de .NET MAUI) es que la ventana de la aplicación de Windows (WinUI) se muestra prácticamente a pantalla completa, y, ya te digo que al menos por ahora, ese tamaño no es configurable de forma automática o, que ocurra como en las aplicaciones para Xamarin en la que el usuario es el que decide qué tamaño y posición debe tener la ventana, de forma que en las próximas veces que se abra la aplicación se muestre como se dejó la última vez.

Nota:
En esta «issue de MAUI» dicen que se podrá hacer: Desktop: set window size and position #771 (pero ni idea de cómo o cuando estará disponible).

Lo que yo hago en estos casos es usar un tamaño «fijo» (que no es lo suyo, pero…) y asignarlo de esta forma en el constructor de la clase App.

public App()
    {
         InitializeComponent();

        // Indicar el tamaño para la app de Windows.
        Microsoft.Maui.Handlers.WindowHandler.Mapper.AppendToMapping(nameof(IWindow), (handler, view) =>
        {
#if WINDOWS

                // Asignar manualmente el tamaño. 
                int winWidth = 1000;
                int winHeight = 900;

                var mauiWindow = handler.VirtualView;
                var nativeWindow = handler.PlatformView;
                nativeWindow.Activate();
                IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(nativeWindow);
                var windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(windowHandle);
                var appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
                appWindow.Resize(new Windows.Graphics.SizeInt32(winWidth, winHeight));

#endif
        });

        MainPage = new AppShell();
    }

Truco 6: Mostrar el título en la barra de la ventana (con colores personalizados)

Otra cosa que estoy haciendo desde hoy (al probar en la aplicación gsCrearTablas_MAUI) es posicionando la ventana y de paso cambiando el color a la barra de título (para que no se vea el color ese tan feo) y también mostrando el título en esa barra de la ventana.

Como puedes ver en la figura 2, no se muestra de color «normal» la barra de título y tampoco tiene un texto.

En la captura 5 puedes ver el color y el texto en la barra de título que podrás conseguir con el código que te muestro a continuación (después de la captura).

Figura 5. La app de Windows con texto y color en la barra de título

La asignación del color y texto de la ventana lo conseguimos haciendo esta asignación (en el código mostrado antes) lo tendrías que poner al final, después de appWindow.Resize.

// El título hay que asignarlo antes de asignar los colores.
appWindow.Title = "Trucos MAUI by elGuille";
// Este es el color que tiene en mi equipo la barra de título.
appWindow.TitleBar.BackgroundColor = Microsoft.UI.ColorHelper.FromArgb(255, 0, 120, 212);
appWindow.TitleBar.ForegroundColor = Microsoft.UI.Colors.White;

Para poder posicionarla, hace falta un truquillo más que es que la ventana se haya mostrado, ya que, si queremos acceder al tamaño de la pantalla, nos dará un valor nulo (o cero).

Nota:
El color que asigno a la propiedad BackgroundColor lo he sacado de cómo se muestra el color en mi equipo, por tanto, en tu caso, lo mismo lo tienes que cambiar: FromArgb(255, 0, 120, 212).

Truco 7: Esperar a que la ventana está mostrada para manipular la posición

Esto lo pones también en el primer código que te mostré en el truco 5, después de appWindow.Resize. Fíjate que el cambio del color y el título hay que hacerlo dentro del Dispatcher.Dispatch, si no, el título no se muestra.

// get screen size
DisplayInfo disp = DeviceDisplay.Current.MainDisplayInfo;
double x, y;

// dispatcher is used to give the window time to actually resize
Dispatcher.Dispatch(() =>
{
    disp = DeviceDisplay.Current.MainDisplayInfo;
    x = (disp.Width / disp.Density - winWidth) / 2;
    if (x < 0) 
    {
        x = 0;
    }
    y = (disp.Height / disp.Density - winHeight) / 2;
    if (y < 0)
    {
        y = 0;
    }
    appWindow.Move(new Windows.Graphics.PointInt32((int)x, (int)y));

    // Si cambiamos la posición, esto hay que hacerlo en el Dispatcher.Dispatch
    // El título hay que asignarlo antes de asignar los colores.
    appWindow.Title = "Trucos MAUI by elGuille";
    // Este es el color que tiene en mi equipo la barra de título.
    appWindow.TitleBar.BackgroundColor = Microsoft.UI.ColorHelper.FromArgb(255, 0, 120, 212);
    appWindow.TitleBar.ForegroundColor = Microsoft.UI.Colors.White;

Y con esto lo dejo por hoy… voy a seguir investigando (y probando) para poder ponerte algunos trucos más.

El código coloreado usando el condicional de WINDOWS (#if WINDOWS)

Pues eso, que habitualmente se muestra con el color grisáceo ese que te he mostrado antes cuando usas el condicional de compilación para Windows (#if WINDOWS) y, algunas veces, no sé cómo, sale coloreado (que es como debería salir).

Este código es de otra aplicación pero intentaré usar los mismos valores que en este proyecto de pruebas.

            // Indicar el tamaño para la app de Windows.
            Microsoft.Maui.Handlers.WindowHandler.Mapper.AppendToMapping(nameof(IWindow), (handler, view) =>
            {
#if WINDOWS

                // Asignar manualmente el tamaño. 
                int winWidth = 800; // 1700; // 2800;
                int winHeight = 640; //1800

                var mauiWindow = handler.VirtualView;
                var nativeWindow = handler.PlatformView;
                nativeWindow.Activate();
                IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(nativeWindow);
                var windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(windowHandle);
                var appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
                //appWindow.Resize(new Windows.Graphics.SizeInt32(winWidth, winHeight));

                // get screen size
                DisplayInfo disp = DeviceDisplay.Current.MainDisplayInfo;
                double x, y;

                // dispatcher is used to give the window time to actually resize
                Dispatcher.Dispatch(() =>
                {
                    disp = DeviceDisplay.Current.MainDisplayInfo;
                    
                    // Si Density es diferente de 1, ajustar el tamaño.
                    if (disp.Density > 1)
                    {
                        winWidth = (int)(winWidth * disp.Density);
                        winHeight = (int)(winHeight * disp.Density);
                    }
                    // El tamaño de la pantalla de este equipo.
                    int screenW = (int)(disp.Width / disp.Density);
                    int screenH = (int)(disp.Height / disp.Density);
                    // Si el alto indicado es mayor, ponerlo para que entre en esta pantalla.
                    if (winHeight > screenH)
                    {
                        winHeight = screenH - 60;
                    }
                    // Si el ancho indicado es mayor, ponerlo para que entre en esta pantalla.
                    if (winWidth > screenW)
                    {
                        winWidth = screenW - 60;
                    }
                    appWindow.Resize(new Windows.Graphics.SizeInt32(winWidth, winHeight));
                    x = (screenW - winWidth) / 2;
                    if (x < 0) 
                    {
                        x = 0;
                    }
                    y = (screenH - winHeight - 40) / 2;
                    if (y < 0)
                    {
                        y = 0;
                    }
                    appWindow.Move(new Windows.Graphics.PointInt32((int)x, (int)y));

                    // El título hay que asignarlo antes de asignar los colores.
                    appWindow.Title = "Trucos MAUI by elGuille";
                    // Este es el color que tiene en mi equipo la barra de título.
                    appWindow.TitleBar.BackgroundColor = Microsoft.UI.ColorHelper.FromArgb(255, 0, 120, 212);
                    appWindow.TitleBar.ForegroundColor = Microsoft.UI.Colors.White;
                });

#endif
            });

Y, ya sabes, si te parece bien, puedes hacer un donativo con PayPal, que es como si me invitaras a un refresco, es decir, no es necesario que me dejes toda tu herencia, solo un par de euritos de nada… 😉

Nos vemos.
Guillermo

P.S.
El repositorio de GitHub ya está creado: Trucos_MAUI.

P.S.2
Por cierto, ahora no me funciona la app para iOS.
El error que da es:

Error CS1705: Assembly ‘Microsoft.Maui’ with identity ‘Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’ uses ‘Microsoft.iOS, Version=16.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065’ which has a higher version than referenced assembly ‘Microsoft.iOS’ with identity ‘Microsoft.iOS, Version=15.4.300.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065’

He buscado (con BING, ya que con Google no encontraba nada al poner esa cadena) para ver de qué va esto y lo que he encontrado (https://github.com/dotnet/maui/issues/8858) dice que ya está resuelto (o algo así) y en teoría la solución que da a mí no me funciona, que si no he entendido mal es dotnet workload install (supongo que indicando o maui o ios) pero nada, también he probado con dotnet workload install ios, con dotnet workload update, con dotnet workload repair y posicionándome en el directorio del proyecto con dotnet workload restore Trucos_MAUI.csproj, pero nada de nada… Ni siquiera usando el peasso de comando este:
dotnet workload install maui --from-rollback-file https://aka.ms/dotnet/maui/6.0.408.json --source https://aka.ms/dotnet6/nuget/index.json --source https://api.nuget.org/v3/index.json
Pero nada de nada… ya, por último, hasta he desinstalado el Visual Studio (en realidad he usado la opción Rollback to previous version) la versión 17.3.6 (a la 17.3.5) pero tampoco ha solucionado nada de nada, así que… he vuelto a instalar la versión 17.3.6, que es la última a día de hoy.
A ver si para la siguiente tanda de trucos tengo la solución. 🤞🏻🙏🏻

P.S.3 (12-oct-22 17.35)
He creado otra entrada (Errores de iOS con .NET MAUI) con el problema este que te comento en el «P.S.2» con idea de ver si lo soluciono.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *