Compartir a través de


Trabajar con vistas apiladas de tvOS en Xamarin

Advertencia

iOS Designer quedó en desuso en la versión 16.8 de Visual Studio 2019 y la 8.8 de Visual Studio 2019 para Mac, y se ha eliminado de la versión 16.9 de Visual Studio 2019 y la 8.9 de Visual Studio para Mac. La manera recomendada de compilar interfaces de usuario de iOS es directamente en un equipo Mac que ejecute Interface Builder de Xcode. Para obtener más información, consulte Diseño de interfaces de usuario con Xcode.

El control Vista de pila (UIStackView) aprovecha la eficacia de las clases de diseño automático y tamaño para administrar una pila de subvistas, ya sea horizontal o verticalmente, que responde dinámicamente a los cambios de contenido y el tamaño de pantalla del dispositivo Apple TV.

La disposición de todas las subvistas adjuntas a una vista de pila son gestionadas por ésta basándose en propiedades definidas por el desarrollador como el eje, la distribución, la alineación y el espaciado:

Diagrama de diseño de subvista

Cuando se usa en UIStackView una aplicación de Xamarin.tvOS, el desarrollador puede definir las subvistas dentro de un guión gráfico en iOS Designer o agregando y quitando subvistas en código de C#.

Acerca de los controles de vista apiladas

UIStackView está diseñado como una vista de contenedor que no es de representación y, como tal, no se dibuja en el lienzo como en otras subclases de UIView. Establecer propiedades como BackgroundColor o invalidar DrawRect no tendrá ningún efecto visual.

Hay varias propiedades que controlan cómo una vista de pila organizará su colección de subvistas:

  • Eje : determina si la vista de pila organiza las subvistas horizontal o verticalmente.
  • Alineación : controla cómo se alinean las subvistas dentro de la vista de pila.
  • Distribución : controla el tamaño de las subvistas dentro de la vista de pila.
  • Espaciado : controla el espacio mínimo entre cada subvista de la vista de pila.
  • Valor relativo de línea base: si es true, el espaciado vertical de cada subvista se derivará de su línea base.
  • Márgenes de diseño relativos: coloca las subvistas en relación con los márgenes de diseño estándar.

Normalmente, usará una vista de pila para organizar un pequeño número de subvistas. Las interfaces de usuario más complejas se pueden crear anidando una o varias vistas de pila entre sí.

Puede ajustar aún más la apariencia de las interfaces de usuario agregando restricciones adicionales a las subvistas (por ejemplo, para controlar el alto o el ancho). Sin embargo, se debe tener cuidado de no incluir restricciones conflictivas a las introducidas por la propia vista de pila.

Clases de tamaño y diseño automático

Cuando se agrega una subvista a una vista de pila, su diseño está totalmente controlado por esa vista de pila mediante el diseño automático y las clases de tamaño para colocar y ajustar el tamaño de las vistas organizadas.

La vista de pila anclará la primera y la última subvista de su colección a los bordes superior e inferior para las vistas de pila vertical o los bordes izquierdo y derecho para las vistas de pila horizontal. Si establece la LayoutMarginsRelativeArrangement propiedad trueen, la vista ancla las subvistas a los márgenes pertinentes en lugar del borde.

La vista de pila usa la propiedad de IntrinsicContentSize la subvista al calcular el tamaño de las subvistas a lo largo del definido Axis (excepto para FillEqually Distribution). FillEqually Distribution Cambia el tamaño de todas las subvistas para que tengan el mismo tamaño, rellenando así la vista pila a lo largo de Axis.

Con la excepción de Fill Alignment, la vista de pila usa la propiedad de IntrinsicContentSize la subvista para calcular el tamaño de la vista perpendicular al especificado Axis. Fill AlignmentPara, todas las subvistas tienen un tamaño para que rellenen la vista de pila perpendicular a la especificada Axis.

Posicionamiento y ajuste del tamaño de la vista de pila

Aunque la vista de pila tiene control total sobre el diseño de cualquier subvista (en función de propiedades como Axis y Distribution), todavía tiene que colocar la vista pila (UIStackView) dentro de su vista primaria mediante el diseño automático y las clases de tamaño.

Por lo general, esto significa anclar al menos dos bordes de la vista de pila para expandir y contraer, definiendo así su posición. Sin restricciones adicionales, la vista de pila se cambiará automáticamente para ajustarse a todas sus subvistas de la siguiente manera:

  • El tamaño a lo largo de su Axis será la suma de todos los tamaños de subvista más cualquier espacio que se haya definido entre cada subvista.
  • Si la LayoutMarginsRelativeArrangement propiedad es true, el tamaño de las vistas de pila también incluirá espacio para los márgenes.
  • El tamaño perpendicular al Axis se establecerá en la subvista más grande de la colección.

Además, puede especificar restricciones para el alto y el ancho de la vista de pila. En este caso, las subvistas se colocarán (tamaño) para rellenar el espacio especificado por la vista de pila según lo determinen las Distribution propiedades y Alignment.

Si la BaselineRelativeArrangement propiedad es true, las subvistas se colocarán en función de la línea base de la primera o última subvista, en lugar de usar la posición Superior, Inferior o Central - Y. Estos se calculan en el contenido de la vista de pila de la siguiente manera:

  • Una vista de pila vertical devolverá la primera subvista de la primera línea base y la última para la última. Si cualquiera de estas subvistas son vistas de pila, se usará su primera o última línea de base.
  • Una vista de pila horizontal usará su subvista más alta para la primera y la última línea base. Si la vista más alta también es una vista de pila, usará su subvista más alta como línea base.

Importante

La alineación de línea base no funciona en tamaños de subvista extendidos o comprimidos, ya que la línea base se calculará en la posición incorrecta. En Alineación de línea base, asegúrese de que el alto de la subvista coincide con el alto de la vista de contenido intrínseco.

Usos comunes de la vista de pila

Hay varios tipos de diseño que funcionan bien con los controles Vista de pila. Según Apple, estos son algunos de los usos más comunes:

  • Defina el tamaño a lo largo del eje: al anclar ambos bordes a lo largo de la vista de pila Axis y uno de los bordes adyacentes para establecer la posición, la vista Pila crecerá a lo largo del eje para ajustarse al espacio definido por sus subvistas.
  • Definir la posición de la subvista: al anclar a los bordes adyacentes de la vista de pila a la vista primaria, la vista pila crecerá en ambas dimensiones para ajustarse a las subvistas que contiene.
  • Definir el tamaño y la posición de la pila: al anclar los cuatro bordes de la vista de pila a la vista primaria, la vista pila organiza las subvistas en función del espacio definido en la vista de pila.
  • Definir el tamaño perpendicular al eje: al anclar ambos bordes perpendiculares al de la vista de Axis pila y uno de los bordes del eje para establecer la posición, la vista Pila crecerá perpendicular al eje para ajustarse al espacio definido por sus subvistas.

Vistas de pila y guiones gráficos

La manera más fácil de trabajar con las vistas de pila en una aplicación de Xamarin.tvOS es agregarlas a la interfaz de usuario de la aplicación mediante iOS Designer.

  1. En el Panel de solución, haga doble clic en el archivo Main.storyboard y ábralo para editarlo.

  2. Diseñe el diseño de los elementos individuales que va a agregar a la vista Pila:

    Ejemplo de diseño de elemento

  3. Agregue las restricciones necesarias a los elementos para asegurarse de que se escalan correctamente. Este paso es importante una vez que el elemento se agrega a la vista de pila.

  4. Realice el número necesario de copias (cuatro en este caso):

    Número necesario de copias

  5. Arrastre una vista de pila desde el cuadro de herramientas y colóquela en la vista:

    Una vista de pila

  6. Seleccione la Vista de pila, en la pestaña Widget del Panel de propiedades, seleccione Rellenar para la alineación, Rellenar igualmente para la distribución y escriba 25 para el espaciado:

    La pestaña Widget

  7. Coloque la vista de pila en la pantalla donde desee y agregue restricciones para mantenerlo en la ubicación necesaria.

  8. Seleccione los elementos individuales y arrástrelos a la vista Pila:

    Los elementos individuales de la vista pila

  9. El diseño se ajustará y los elementos se organizarán en la vista de pila en función de los atributos establecidos anteriormente.

  10. Asigne nombres en la pestaña Widget del Explorador de propiedades para trabajar con los controles de interfaz de usuario en código de C#.

  11. Guarde los cambios.

Importante

Aunque es posible asignar acciones como TouchUpInside a un elemento de interfaz de usuario (como UIButton) en el Diseñador de iOS al crear un controlador de eventos, nunca se llamará porque Apple TV no tiene una pantalla táctil ni admite eventos táctiles. Siempre debe usar el valor predeterminado Action Type al crear acciones para elementos de la interfaz de usuario de tvOS.

Para obtener más información sobre cómo trabajar con guiones gráficos, consulte nuestra Guía de inicio rápido de Hello, tvOS.

En el caso de nuestro ejemplo, hemos expuesto una salida y una acción para el control de segmento y una salida para cada "tarjeta de jugador". En el código, ocultamos y mostramos al jugador en función del segmento actual. Por ejemplo:

partial void PlayerCountChanged (Foundation.NSObject sender) {

    // Take Action based on the segment
    switch(PlayerCount.SelectedSegment) {
    case 0:
        Player1.Hidden = false;
        Player2.Hidden = true;
        Player3.Hidden = true;
        Player4.Hidden = true;
        break;
    case 1:
        Player1.Hidden = false;
        Player2.Hidden = false;
        Player3.Hidden = true;
        Player4.Hidden = true;
        break;
    case 2:
        Player1.Hidden = false;
        Player2.Hidden = false;
        Player3.Hidden = false;
        Player4.Hidden = true;
        break;
    case 3:
        Player1.Hidden = false;
        Player2.Hidden = false;
        Player3.Hidden = false;
        Player4.Hidden = false;
        break;
    }
}

Cuando se ejecuta la aplicación, los cuatro elementos se distribuirán igualmente en nuestra vista de pila:

Cuando se ejecuta la aplicación, los cuatro elementos se distribuirán igualmente en nuestra vista de pila

Si se reduce el número de jugadores, las vistas no utilizadas se ocultan y la vista de pila ajusta el diseño que se ajustará:

Si se reduce el número de jugadores, las vistas sin usar se ocultan y la vista de pila ajusta el diseño para ajustarlo

Rellenar una vista de pila desde código

Además de definir totalmente el contenido y el diseño de una vista de pila en iOS Designer, puede crearlo y quitarlo dinámicamente del código de C#.

Tome el ejemplo siguiente que usa una vista de pila para controlar "estrellas" en una revisión (de 1 a 5):

public int Rating { get; set;} = 0;
...

partial void IncreaseRating (Foundation.NSObject sender) {

    // Maximum of 5 "stars"
    if (++Rating > 5 ) {
        // Abort
        Rating = 5;
        return;
    }

    // Create new rating icon and add it to stack
    var icon = new UIImageView (new UIImage("icon.png"));
    icon.ContentMode = UIViewContentMode.ScaleAspectFit;
    RatingView.AddArrangedSubview(icon);

    // Animate stack
    UIView.Animate(0.25, ()=>{
        // Adjust stack view
        RatingView.LayoutIfNeeded();
    });

}

partial void DecreaseRating (Foundation.NSObject sender) {

    // Minimum of zero "stars"
    if (--Rating < 0) {
        // Abort
        Rating =0;
        return;
    }

    // Get the last subview added
    var icon = RatingView.ArrangedSubviews[RatingView.ArrangedSubviews.Length-1];

    // Remove from stack and screen
    RatingView.RemoveArrangedSubview(icon);
    icon.RemoveFromSuperview();

    // Animate stack
    UIView.Animate(0.25, ()=>{
        // Adjust stack view
        RatingView.LayoutIfNeeded();
    });
}

Echemos un vistazo a algunos fragmentos de este código con detalle. En primer lugar, usamos instrucciones if para comprobar que no hay más de cinco "estrellas" o menos de cero.

Para agregar una nueva "estrella", cargamos su imagen y establecemos su modo de contenido en Ajuste de aspecto de escala:

var icon = new UIImageView (new UIImage("icon.png"));
icon.ContentMode = UIViewContentMode.ScaleAspectFit;

Esto impide que el icono de "estrella" se distorsiona cuando se agrega a la vista de pila.

A continuación, agregamos el nuevo icono de "estrella" a la colección de subvistas de la vista de pila:

RatingView.AddArrangedSubview(icon);

Observará que hemos agregado el elemento UIImageView a la propiedad UIStackViewde ArrangedSubviews y no a SubView. Cualquier vista que desee que la vista de pila controle su diseño debe agregarse a la ArrangedSubviews propiedad.

Para quitar una subvista de una vista de pila, primero obtenemos la subvista para quitar:

var icon = RatingView.ArrangedSubviews[RatingView.ArrangedSubviews.Length-1];

A continuación, es necesario quitarlo de la ArrangedSubviews colección y de la Vista super:

// Remove from stack and screen
RatingView.RemoveArrangedSubview(icon);
icon.RemoveFromSuperview();

Quitar una subvista de solo la ArrangedSubviews colección lo saca del control de la vista de pila, pero no lo quita de la pantalla.

Cambio dinámico del contenido

Una vista de pila ajustará automáticamente el diseño de las subvistas cada vez que se agrega, quita o oculta una subvista. El diseño también se ajustará si se ajusta cualquier propiedad de la vista de pila (por ejemplo, su Axis).

Los cambios de diseño se pueden animar colocando dentro de un bloque de animación, por ejemplo:

// Animate stack
UIView.Animate(0.25, ()=>{
    // Adjust stack view
    RatingView.LayoutIfNeeded();
});

Muchas de las propiedades de la vista de pila se pueden especificar mediante clases de tamaño dentro de un Storyboard. Estas propiedades se animarán automáticamente es la respuesta a los cambios de tamaño o orientación.

Resumen

En este artículo se ha tratado el diseño y el trabajo con la vista apilada dentro de una aplicación de Xamarin.tvOS.