En ocasiones estamos en la necesidad de filtrar elementos dentro de nuestra pantalla, para ello decidimos optar por utilizar un campo de texto para elegir un criterio de búsqueda de aquello que queremos mantener a la vista.
Claramente para los fines funciona de maravilla. Escribes lo que necesitas y esto se filtra tal y como lo deseas, pero el usuario de tu aplicación podría sentirse un poco incomodo con esto, ya que las aplicaciones que el posiblemente suele usar son un poco diferente a esto que planteas, sin olvidar que los elementos ocupan mas pantalla de la que deberían.
Este post es para introducirte a una manera más estética e intuitiva de realizar una búsqueda en Xamarin Forms.
Expectativas
El ejemplo que te muestro izquierda es el resultado de lo que tratamos en este post.
Si te fijas las animaciones que utilizamos son las Simple Animations que aparecen en la documentación de Xamarin, los elementos visuales utilizados son los de Xamarin propios incluidos dentro de un Title
View que viene incluido desde en la version 3.2.0 Xamarin.Forms y para el calculo de tamaño de pantalla utilizaremos Xamarin.Essentials DeviceDisplay(opcional).
De igual manera antes de iniciar debemos saber de antemano que no evaluaremos el funcionamiento de filtrado de list view, solamente el comportamiento visual del panel de navegación y la barra de búsqueda. Ademas de que dicho ejemplo esta siendo trabajado en un version superior a 3.2.0 de Xamarin Forms.
Trabajando con el XAML (Barra de Búsqueda)
Para iniciar un Title View es la representación visual del contenido dentro del NavigationPane o panel de navegación de una aplicación escrita en Xamarin Forms del content page donde este es invocado. Para este ser invocado es necesario que el tipo de Page que lo contiene posea un NavigationPane, es decir, debe ser un derivado de NavigationPage.
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> <NavigationPage.TitleView> <RelativeLayout o StackLayout o AbsoluteLayout o Grid Etc> <!--Algunos elementos visuales aqui para el NavigationPane--> </RelativeLayout> </NavigationPage.TitleView> <StackLayout> <!--mas elementos visuales aqui para el cuerpo--> </StackLayout> </ContentPage>
Una vez familiarizado con el TitleView solo debemos jugar con los elementos que mostramos en pantalla. Por ejemplo en el caso mostrado en la ultima imagen yo inicie solapando un Frame (para que se visualize detrás un cuadro blanco redondeado) que posee un SearchBar contra StackLayout que tiene en su interior un Label de un lado y un icono (Image) de Search del otro lado, utilizando RelativeLayout. De esa forma y sin la animación tenemos texto e icono ambos a cada lado de la pantalla detrás y delante tapándolos tenemos el rectángulo con el campo de búsqueda.
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> <NavigationPage.TitleView> <RelativeLayout> <StackLayout Margin="0, 8, 12, 6" x:Name="TitleControls" Orientation="Horizontal" RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}"> <Label TextColor="White" FontSize="20" HorizontalOptions="StartAndExpand" VerticalOptions="CenterAndExpand" FontAttributes="Bold" Text="Mi Titulo"/> <Image x:Name="SearchIndicator" Source="SearchWhite" WidthRequest="25" HorizontalOptions="End" VerticalOptions="CenterAndExpand"> <Image.GestureRecognizers> <TapGestureRecognizer Tapped="Search_Tapped" NumberOfTapsRequired="1" /> </Image.GestureRecognizers> </Image> </StackLayout> <Frame x:Name="SearchFrame" HasShadow="False" IsClippedToBounds="True" Margin="0, 6, 12, 6" VerticalOptions="CenterAndExpand" RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}" Padding="0"> <Frame.Content> <SearchBar x:Name="SearchBar" Placeholder="Buscar" HorizontalOptions="FillAndExpand" VerticalOptions="CenterAndExpand" HeightRequest="35" Unfocused="SearchBar_Unfocused"> </SearchBar> </Frame.Content> </Frame> </RelativeLayout> </NavigationPage.TitleView> <StackLayout> <!--mas elementos visuales aqui para el cuerpo--> </StackLayout> </ContentPage>
Recordemos que para que la imagen pueda visualizarse hay que hacer los procedimiento para cada una de las plataformas que tengamos en el proyecto. Si nos fijamos en el código anterior tenemos 2 evento que nos servirá para detonar los eventos que moverán a nuestro Searchbar hacia adentro y hacia afuera de la pantalla, estos son » Search_Tapped » que es el evento touch de la lupa de «buscar» y «SearchBar_Unfocused» que es el evento que se detonara cuando dejemos de usar nuestro campo de búsquedas (Advertencia en la linea 29, solemos usar el HeightRequest y WidthRequest lo menos posible pero este caso especial lo requiere en android 7).
Utilizando el Code Behind
Lo siguiente ahora es indicarle los movimientos deseados a los elementos correspondientes de nuestro panel de navegación. Si ponemos mucha atención a las animaciones de la segunda imagen ubicada más arriba podemos ver lo siguiente.
- Al tocar el icono de búsqueda este sutil y rápidamente crece y disminuye. Este es el método «ScaleTo(multiplicador de tamaño[double], mili segundos de ejecución[double])» repetido 2 veces uno para crecer y otro para disminuir.
- Después que esto sucede el titulo y el icono de búsqueda se desvanecen. Esto es la ejecución del método «FadeTo(opacidad a la que se quiere llegar[double], mili segundos de ejecución[double])» sobre el StackLayout que los contiene a ambos.
- Y finalmente aparece nuestra barra de búsqueda desde la derecha hacia la izquierda mediante la ejecución de 2 métodos. El anterior FadeTo y el «TranslateTo(posición en eje x [double], posición en eje y[double], mili segundos de ejecución[double])»
Lo demás es el mismo funcionamiento pero a la inversa. Todos estos métodos pueden ser encontrados en la doc Simple Animations donde podrán también encontrar usos mas variados para ello. Una vez entendido lo anterior vamos a visualizar como hacerlos trabajar en armonía para mejor transición visual.
public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); SearchFrame.TranslateTo(transition, 0,1); SearchFrame.FadeTo(0, 1); SearchFrame.IsVisible = false; } private double transition = (DeviceDisplay.ScreenMetrics.Width / DeviceDisplay.ScreenMetrics.Density) / 2; private async void Search_Tapped(object sender, EventArgs e) { SearchFrame.IsVisible = true; TitleControls.FadeTo(0, 200); await SearchIndicator.ScaleTo(1.4, 85); SearchIndicator.ScaleTo(1, 85); SearchFrame.FadeTo(1,170); await SearchFrame.TranslateTo(0, 0, 200); SearchBar.Focus(); } private async void SearchBar_Unfocused(object sender, FocusEventArgs e) { TitleControls.FadeTo(1, 200); SearchFrame.TranslateTo(transition, 0, 200); await SearchFrame.FadeTo(0, 200); SearchFrame.IsVisible = false; } }
Anteriormente mencione que utilizo un paquete llamado Xamarin.Essentials para medir las pantallas del dispositivo donde se ejecuta la app. Pues aquí » (DeviceDisplay.ScreenMetrics.Width / DeviceDisplay.ScreenMetrics.Density) / 2;» lo que hago es obtener una ubicación dirigida al lado derecho de la pantalla sacando la barra de búsqueda 70% fuera de la pantalla. Si lo desea puede colocar otra cantidad siempre y cuanto sea del tipo double.
Luego de determinar el sitio donde colocar la barra de búsqueda la ocultamos para poder tocar nuestro icono buscar. Lo que nos lleva al anterior mencionado evento «Search_Tapped» donde visibilizamos la barra, vamos desvaneciendo el texto y la lupa, pero mientras eso pasa en menor tiempo mostramos la lupa crecida y disminuida y secuencialmente luego de ello la barra va apareciendo y simultáneamente moviéndose a su respectivo lugar.
Finalmente, al desenfocar la barra de búsqueda hacemos lo anterior de manera inversa sin la parte de la animación «ScaleTo» del icono de búsqueda.
Consideraciones
- El Navigation «TitleView» funciona separado del Content del Page que lo contiene.
- Al igual que todo Content solo admite un solo elemento por lo que se recomienda lo mismo que con los Contents utilizar un elemento visual que sea capaz de englobar varios de los mismos Como StackLayout o Grids.
- Puedes tener a la vista dentro de un «TitleView» tantos elementos quepan en el tamaño. De superar este tamaño estos serán solapado detrás del padding del NavigationPane.
- Puedes tener varias animaciones corriendo simultáneamente pero debes tener cuidado con el procesamiento ya que cada animación al ser asíncronas utilizan multi hilos y regularmente evitamos irrumpir en la experiencia de usuario.
Sigue adelante
El contenido de este blog no quiere limitarte, todo lo contrario lo que busca es inspirarte para que puedas crear interfaces más vivas y que la interacción con el usuario sea lo mas intuitiva posible. Este fue solo un ejemplo super básico de cómo se puede integrar elementos en el NavigationPane, nada que no pueda superar un día o noche de inspiración acompañado de una bebida caliente.