<p>Xamarin.Forms.Shell Spec</p>

Criado em 10 abr. 2018  ·  199Comentários  ·  Fonte: xamarin/Xamarin.Forms

Xamarin.Forms Shell Spec

Faça com que seja simples e direto para novos desenvolvedores obterem uma experiência de aplicativo completa que seja devidamente estruturada, use os elementos certos, com muito pouco esforço e um caminho claro para ser bom por padrão.

Shell é uma API opinativa em alguns pontos, nem sempre padroniza todos os valores para algum .Default, que pode mudar com base na plataforma em execução. Em vez disso, pode definir um valor que é então respeitado em todas as plataformas, independentemente de qual seja o padrão da plataforma.

Nota: Especificações de desenho movidas para: # 2452

Tratamento Visual

Necessita de capturas de tela ...

Hierarquia de Shell

Compreender a hierarquia da Shell no início pode parecer opressor no início. Ele representa uma hierarquia complexa e fornece mecanismos poderosos para minimizar a quantidade de xaml clichê necessária para criar hierarquias ricas.

Portanto, ao aprender o shell pela primeira vez, é mais fácil aprender sem os atalhos primeiro e, em seguida, apresentar os atalhos para ver como minimizar facilmente a quantidade de XAML que está sendo escrita.

Observe que todos os exemplos a seguir não usam o modelo ShellContent, que é discutido em outra parte da especificação. A falha em usar ShellContents com um ContentTemplate resultará no carregamento de todas as páginas na inicialização, o que afetará negativamente o desempenho da inicialização. Esses exemplos são apenas para fins de aprendizagem.

Felizmente, usar ShellContents com ContentTemplates geralmente é mais conciso do que não usá-los.

Sem atalhos

Muitos desses exemplos parecerão desnecessariamente complexos e, na realidade, são. Na próxima seção, eles serão simplificados.

Um aplicativo simples de uma página

<Shell xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:local="clr-namespace:MyStore"
       FlyoutBehavior="Disabled"
       x:Class="MyStore.Shell">

  <ShellItem>
    <ShellSection>
      <ShellContent>
        <local:HomePage />
      </ShellContent>
    </ShellSection>
  </ShellItem>
</Shell>

step1

A barra superior pode ser totalmente escondida configurando Shell.NavBarVisible="false" na MainPage. O Flyout também ficaria esparso neste modo e, portanto, está desabilitado neste exemplo.

Aplicativo de duas páginas com guias inferiores

<Shell xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:local="clr-namespace:MyStore"
       FlyoutBehavior="Disabled"
       x:Class="MyStore.Shell">

  <ShellItem>

    <ShellSection Title="Home" Icon="home.png">
      <ShellContent>
        <local:HomePage />
      </ShellContent>
    </ShellSection>

    <ShellSection Title="Notifications" Icon="bell.png">
      <ShellContent>
        <local:NotificationsPage />
      </ShellContent>
    </ShellSection>

  </ShellItem>
</Shell>

step2

Adicionando uma seção ShellSection a ShellItem outra guia inferior aparece. As configurações de título e ícone apropriados permitem controlar o título e o ícone do item da guia.

Aplicativo de duas páginas com guias superior e inferior

<Shell xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:local="clr-namespace:MyStore"
       FlyoutBehavior="Disabled"
       x:Class="MyStore.Shell">

  <ShellItem>

    <ShellSection Title="Home" Icon="home.png">
      <ShellContent>
        <local:HomePage />
      </ShellContent>
    </ShellSection>

    <ShellSection Title="Notifications" Icon="bell.png">

      <ShellContent Title="Recent">
        <local:NotificationsPage />
      </ShellContent>

      <ShellContent Title="Alert Settings">
        <local:SettingsPage />
      </ShellContent>

    </ShellSection>

  </ShellItem>
</Shell>

step3

Ao adicionar um segundo ShellContent a ShellSection uma barra de guia superior é adicionada e as páginas podem ser alternadas quando a guia inferior é selecionada.

Aplicativo de duas páginas usando navegação flyout

<Shell xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:local="clr-namespace:MyStore"
       x:Class="MyStore.Shell">

  <Shell.FlyoutHeader>
    <local:FlyoutHeader />
  </Shell.FlyoutHeader>

  <ShellItem Title="Home" Icon="home.png">
    <ShellSection>
      <ShellContent>
        <local:HomePage />
      </ShellContent>
    </ShellSection>
  </ShellItem>

  <ShellItem Title="Notifications" Icon="bell.png">
    <ShellSection>
      <ShellContent>
        <local:NotificationsPage />
      </ShellContent>
    </ShellSection>
  </ShellItem>
</Shell>

step4

O flyout é reativado neste exemplo. Aqui, o usuário pode alternar entre as duas páginas usando o menu desdobrável como intermediário. Um cabeçalho também foi adicionado para ter uma boa aparência.

Usando sintaxe abreviada

Agora que todos os níveis da hierarquia foram mostrados e explicados de maneira resumida, é possível deixar de lado a maior parte do acondicionamento desnecessário ao definir uma hierarquia. Shell apenas contém ShellItem s que contém apenas ShellSection s que, por sua vez, contém apenas ShellContent s. No entanto, existem operadores de conversão implícitos para permitir o agrupamento automático.

Um aplicativo simples de uma página

<Shell xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:local="clr-namespace:MyStore"
       FlyoutBehavior="Disabled"
       x:Class="MyStore.Shell">

  <local:HomePage />
</Shell>

Com o empacotamento implícito, a página é automaticamente empacotada até ShellItem . Não é necessário escrever todas as camadas intermiedate. O Title e Icon de Page serão vinculados a quaisquer pais gerados implicitamente.

Aplicativo de duas páginas com guias inferiores

<Shell xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:local="clr-namespace:MyStore"
       FlyoutBehavior="Disabled"
       x:Class="MyStore.Shell">

  <ShellItem>
    <local:HomePage Icon="home.png" />
    <local:NotificationsPage Icon="bell.png" />
  </ShellItem>
</Shell>

As páginas agora estão implicitamente agrupadas em ShellContent e suas próprias ShellSections. Isso resulta na criação de duas guias diferentes, exatamente como antes.

Aplicativo de duas páginas com guias superior e inferior

<Shell xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:local="clr-namespace:MyStore"
       FlyoutBehavior="Disabled"
       x:Class="MyStore.Shell">

  <ShellItem>
    <local:HomePage Icon="home.png" />

    <ShellSection Title="Notifications" Icon="bell.png">
        <local:NotificationsPage />
        <local:SettingsPage />
    </ShellSection>
  </ShellItem>
</Shell>

Aplicativo de duas páginas usando navegação flyout

<Shell xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:local="clr-namespace:MyStore"
       x:Class="MyStore.Shell">

  <Shell.FlyoutHeader>
    <local:FlyoutHeader />
  </Shell.FlyoutHeader>

  <local:HomePage Icon="home.png" />
  <local:NotificationsPage Icon="bell.png" />
</Shell>

Aqui, a embalagem implícita vai até o item de casca, portanto, não há necessidade de fazermos qualquer embalagem nós mesmos.

Modelo de Navegação

Push Navigation

Toda a navegação é baseada na propriedade .Navigation do View. Os envios vão para o ShellSection atual que é exibido. Isso significa que, em um evento push, as guias superiores desaparecerão e as inferiores permanecerão.

Navegação URI

O Shell pode ser navegado usando a propriedade Navigation padrão, conforme discutido acima, no entanto, o shell apresenta um mecanismo de navegação muito mais conveniente.

Os URIs de navegação são formatados da seguinte forma:

[Shell.RouteScheme]://[Shell.RouteHost]/[Shell]/[ShellItem]/[ShellSection]/[ShellContent]/[NavStack1]/[NavStack2]...

Todos os itens na hierarquia do shell têm uma rota associada a eles. Se a rota não for definida pelo desenvolvedor, a rota é gerada em tempo de execução. Rotas geradas em tempo de execução não são garantidas para serem estáveis ​​em diferentes execuções do aplicativo e, portanto, não são úteis para links diretos.

Manuseando o Botão Voltar

Como o Shell estará na posição invejável de não ter que usar controles nativos, todas as formas de anulação do botão Voltar podem e devem ser suportadas.

O manuseio adequado do botão Voltar deve oferecer suporte aos seguintes recursos:

  • Interceptando interações e parando-as
  • Substituindo o botão Voltar por outro
  • Escondendo o botão Voltar totalmente quando desejado
  • Trabalhe para botões de software e hardware

A API precisa ser granular para o nível da página para facilidade de uso, mas também pode ser manipulada mais acima na pilha em um nível mais geral.

Amostras de código e API

Amostras

<Shell>
  <Shell.FlyoutHeaderTemplate>
    <DataTemplate>
      <Grid>
        <Label Text="{x:Bind HeaderText}" />
      </Grid>
    </DataTemplate>
  </Shell.FlyoutHeaderTemplate>

  // Flyout Item 1
  <ShellItem Title="My music" ItemsSource="{x:Bind MyMusicModels}" TabLocation="Bottom">
    <ShellItem.ItemTemplate>
      <local:MyMusicItemTemplateSelection />
    </ShellItem.ItemTemplate>
  </ShellItem>

  // Flyout Item 2
  <ShellItem Title="Home" Icon="home.png" GroupBehavior="ShowTabs">
    <ShellContent Title="My Friends">
      <local:FriendsPage />
    </ShellContent>
    <local:FeedPage />
    <local:ProfilePage />
  </ShellItem>

  // Flyout Item 3
  <local:SettingsPage />

  // Flyout Item 4
  <MenuItem Text="Log Out" Command="{x:Bind LogOutCommand}" />
</Shell>

Aplicativo de página única usando Shell

<Shell FlyoutVisibility="Disabled">
  <local:MyPage />
</Shell>

Aplicativo de grupo único de guias (sem flyout)

<Shell FlyoutVisibility="Disabled">
  <ShellItem>
    <local:MyPage />
    <local:MySecondPage />
    <local:MyThirdPage />
  </ShellItem>
</Shell>

Várias páginas em submenu sem guias

<Shell FlyoutVisibility="Disabled">
  <local:MyPage />
  <local:MySecondPage />
  <local:MyThirdPage />
</Shell>

Aplicativo pesquisável de página única

<Shell FlyoutVisibility="Disabled">
  <local:MyPage />
</Shell>

`` `csharp
public class MyPage: ContentPage
{
public class MyPageSearchHandler: SearchHandler
{
public MyPageHandler ()
{
SearchBoxVisibility = SearchBoxVisibility.Collapsed;
IsSearchEnabled = true;
Espaço reservado = "Procure-me!";
}

protected override async void OnSearchConfirmed (string query)
{
  IsSearching = true;

  await PerformSearch (query);
  UpdateResults ();

  IsSearching = false;
}

protected override void OnSearchChanged (string oldValue, string newValue)
{
  // Do nothing, we will wait for confirmation
}

}

public MyPage ()
{
Shell.SetSearchHandler (this, new MyPageSearchHandler ());
}
}

## API Definition

### Shell
This is the base class for Shell's. It defines a somewhat strict navigational model however all shells must adhere to it in general. It does not include any theming or design language specific features.

```csharp
[ContentProperty("Items")]
public class Shell : Page, IShellController
{
  // Attached Properties
  public static readonly BindableProperty BackButtonBehaviorProperty;
  public static readonly BindableProperty FlyoutBehaviorProperty;
  public static readonly BindableProperty NavBarVisibleProperty;
  public static readonly BindableProperty SearchHandlerProperty;
  public static readonly BindableProperty SetPaddingInsetsProperty;
  public static readonly BindableProperty TabBarVisibleProperty;
  public static readonly BindableProperty TitleViewProperty;
  public static readonly BindableProperty ShellBackgroundColorProperty;
  public static readonly BindableProperty ShellDisabledColorProperty;
  public static readonly BindableProperty ShellForegroundColorProperty;
  public static readonly BindableProperty ShellTabBarBackgroundColorProperty;
  public static readonly BindableProperty ShellTabBarDisabledColorProperty;
  public static readonly BindableProperty ShellTabBarForegroundColorProperty;
  public static readonly BindableProperty ShellTabBarTitleColorProperty;
  public static readonly BindableProperty ShellTabBarUnselectedColorProperty;
  public static readonly BindableProperty ShellTitleColorProperty;
  public static readonly BindableProperty ShellUnselectedColorProperty;

  public static BackButtonBehavior GetBackButtonBehavior(BindableObject obj);
  public static FlyoutBehavior GetFlyoutBehavior(BindableObject obj);
  public static bool GetNavBarVisible(BindableObject obj);
  public static SearchHandler GetSearchHandler(BindableObject obj);
  public static bool GetSetPaddingInsets(BindableObject obj);
  public static bool GetTabBarVisible(BindableObject obj);
  public static View GetTitleView(BindableObject obj);
  public static void SetBackButtonBehavior(BindableObject obj, BackButtonBehavior behavior);
  public static void SetFlyoutBehavior(BindableObject obj, FlyoutBehavior value);
  public static void SetNavBarVisible(BindableObject obj, bool value);
  public static void SetSearchHandler(BindableObject obj, SearchHandler handler);
  public static void SetSetPaddingInsets(BindableObject obj, bool value);
  public static void SetTabBarVisible(BindableObject obj, bool value);
  public static void SetTitleView(BindableObject obj, View value);
  public static Color GetShellBackgroundColor(BindableObject obj);
  public static Color GetShellDisabledColor(BindableObject obj);
  public static Color GetShellForegroundColor(BindableObject obj);
  public static Color GetShellTabBarBackgroundColor(BindableObject obj);
  public static Color GetShellTabBarDisabledColor(BindableObject obj);
  public static Color GetShellTabBarForegroundColor(BindableObject obj);
  public static Color GetShellTabBarTitleColor(BindableObject obj);
  public static Color GetShellTabBarUnselectedColor(BindableObject obj);
  public static Color GetShellTitleColor(BindableObject obj);
  public static Color GetShellUnselectedColor(BindableObject obj);
  public static void SetShellBackgroundColor(BindableObject obj, Color value);
  public static void SetShellDisabledColor(BindableObject obj, Color value);
  public static void SetShellForegroundColor(BindableObject obj, Color value);
  public static void SetShellTabBarBackgroundColor(BindableObject obj, Color value);
  public static void SetShellTabBarDisabledColor(BindableObject obj, Color value);
  public static void SetShellTabBarForegroundColor(BindableObject obj, Color value);
  public static void SetShellTabBarTitleColor(BindableObject obj, Color value);
  public static void SetShellTabBarUnselectedColor(BindableObject obj, Color value);
  public static void SetShellTitleColor(BindableObject obj, Color value);
  public static void SetShellUnselectedColor(BindableObject obj, Color value);

  // Bindable Properties
  public static readonly BindableProperty CurrentItemProperty;
  public static readonly BindableProperty CurrentStateProperty;
  public static readonly BindableProperty FlyoutBackgroundColorProperty;
  public static readonly BindableProperty FlyoutHeaderBehaviorProperty;
  public static readonly BindableProperty FlyoutHeaderProperty;
  public static readonly BindableProperty FlyoutHeaderTemplateProperty;
  public static readonly BindableProperty FlyoutIsPresentedProperty;
  public static readonly BindableProperty GroupHeaderTemplateProperty;
  public static readonly BindableProperty ItemsProperty;
  public static readonly BindableProperty ItemTemplateProperty;
  public static readonly BindableProperty MenuItemsProperty;
  public static readonly BindableProperty MenuItemTemplateProperty;

  public Shell();

  public event EventHandler<ShellNavigatedEventArgs> Navigated;

  public event EventHandler<ShellNavigatingEventArgs> Navigating;

  public ShellItem CurrentItem {get; set;}

  public ShellNavigationState CurrentState {get; }

  public Color FlyoutBackgroundColor {get; set;}

  public FlyoutBehavior FlyoutBehavior {get; set;}

  public object FlyoutHeader {get; set;}

  public FlyoutHeaderBehavior FlyoutHeaderBehavior {get; set;}

  public DataTemplate FlyoutHeaderTemplate {get; set;}

  public bool FlyoutIsPresented {get; set;}

  public DataTemplate GroupHeaderTemplate {get; set;}

  public ShellItemCollection Items {get; }

  public DataTemplate ItemTemplate {get; set;}

  public MenuItemCollection MenuItems {get; }

  public DataTemplate MenuItemTemplate {get; set;}

  public string Route {get; set;}

  public string RouteHost { get; set; }

  public string RouteScheme { get; set; }

  public async Task GoToAsync(ShellNavigationState state, bool animate = true);

  protected virtual void OnNavigated(ShellNavigatedEventArgs args);

  protected virtual void OnNavigating(ShellNavigatingEventArgs args);
}

Descrição

Propriedades anexadas:

| API | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| SearchHandlerProperty | Propriedade anexada para a definição de um recurso de Pesquisa no nível da página. Pode ser anexado em vários pontos da hierarquia. Usa alguns dos recursos definidos aqui https://material.io/guidelines/patterns/search.html#search -in-app-search |
| BackButtonBehavior | Permite a substituição completa do comportamento do botão Voltar. Aplica-se aos botões voltar na tela e físicos. |
| FlyoutBehavior | Define como o Flyout deve se apresentar. Isso pode ser anexado a ShellItem s, ShellContent s ou Page s para substituir o comportamento padrão. |
| NavBarVisibleProperty | Propriedade definida em Page para definir se a NavBar deve ser visível quando for apresentada |
| SetPaddingInsetsProperty | Definir essa propriedade em um Page fará com que seu Padding seja definido de forma que seu conteúdo não flua sob nenhum cromo Shell. |
| TabBarVisibleProperty | Propriedade definida em um Page para definir se o TabBar deve ser visível quando for apresentado |
| TitleViewProperty | Propriedade definida em Page para definir o TitleView |
| ShellBackgroundColorProperty | Descreve a cor de fundo que deve ser usada para os elementos cromados do Shell. Esta cor não será preenchida por trás do Conteúdo da Shell. |
| ShellDisabledColorProperty | A cor para sombrear o texto / ícones que estão desativados |
| ShellForegroundColorProperty | A cor para sombrear o texto normal / ícones no shell |
| ShellTabBarBackgroundColorProperty | Substituição de ShellBackgroudnColor para TabBar. Se não for definido, ShellBackgroundColor será usado |
| ShellTabBarDisabledColorProperty | Substituição de ShellDisabledColor para TabBar. Se não for definido, ShellDisabledColorProperty será usado |
| ShellTabBarForegroundColorProperty | Substituição de ShellForegroundColorProperty para TabBar. Se não for definido, ShellForegroundColorProperty será usado |
| ShellTabBarTitleColorProperty | Substituição de ShellTitleColorProperty para TabBar. Se não for definido, ShellTitleColorProperty será usado |
| ShellTabBarUnselectedColorProperty | Substituição de ShellUnselectedColorProperty para TabBar. Se não for definido, ShellUnselectedColorProperty será usado |
| ShellTitleColorProperty | A cor usada para o título da página atual |
| ShellUnselectedColorProperty | A cor usada para texto / ícones não selecionados no cromo do shell |

Propriedades:

| API | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| CurrentItem | O ShellItem selecionado atualmente |
| CurrentState | O estado de navegação atual do Shell. Passar esse estado de volta para GoToAsync fará com que o Shell retorne para navegar de volta ao estado. |
| FlyoutBackgroundColorProperty | A cor de fundo do menu flyout |
| FlyoutBehavior | Define o FlyoutBehavior padrão para Shell . |
| FlyoutHeader | O objeto usado como cabeçalho do Flyout. Se FlyoutHeaderTemplate não for nulo, isso é passado como BindingContext para o objeto inflado. Se FlyoutHeaderTemplate for nulo e FlyoutHeader for do tipo View ele será usado diretamente. Caso contrário, será mostrado chamando ToString () e exibindo o resultado. |
| FlyoutHeaderBehavior | Define o comportamento de FlyoutHeader quando o menu desdobrável precisa ser rolado para mostrar o conteúdo. |
| FlyoutHeaderTemplate | O modelo usado para criar um cabeçalho para o Flyout. |
| FlyoutIsPresented | Obtém ou define se o Flyout está ou não visível no momento |
| GroupHeaderTemplate | O DataTemplate usado para mostrar um cabeçalho de grupo se um ShellItem solicitar ser exibido como um grupo de guias no submenu. Se nulo, nenhum cabeçalho é exibido. |
| Itens | O conteúdo principal de um Shell. Os itens definem a lista de itens que serão exibidos no menu desdobrável, bem como o conteúdo que será exibido quando um item da barra lateral for selecionado. |
| ItemTemplate | O DataTemplate costumava mostrar itens da coleção Items no menu desdobrável. Permite que o desenvolvedor controle os visuais no Flyout. |
| MenuItems | Uma coleção de MenuItem s que aparecerá no menu desdobrável em sua própria seção. |
| MenuItemTemplate | O DataTemplate a ser usado quando exibido um MenuItem no menu desdobrável. |
| Rota | A parte da rota para abordar este elemento ao realizar links diretos. |
| RouteHost | A string a ser colocada na parte do host do URI gerado ao criar links profundos |
| RouteScheme | A string a ser colocada na parte do esquema do URI gerado ao criar links profundos |

Métodos públicos:

| API | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| GoToAsync | Navegue até ShellNavigationState . Retorna uma Tarefa que será concluída assim que a animação for concluída. |

Eventos Públicos:

| API | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| Navegando | O Shell está prestes a realizar uma navegação devido à interação do usuário ou ao desenvolvedor chamando uma API. O desenvolvedor pode cancelar a navegação aqui, se possível. |
| Navegado | O Shell concluiu um evento de navegação. |

ShellItemCollection

Uma coleção por ShellItem s

public sealed class ShellItemCollection : IEnumerable<ShellItem>, IList<ShellItem>

MenuItemCollection

Uma coleção por MenuItem s

public sealed class MenuItemCollection : IEnumerable<MenuItem>, IList<MenuItem>

ShellSectionCollection

Uma coleção por ShellSection s

public sealed class ShellSectionCollection : IEnumerable<ShellSection>, IList<ShellSection>

ShellContentCollection

Uma coleção por ShellContent s

public sealed class ShellContentCollection : IEnumerable<ShellContent>, IList<ShellContent>

ShellNavigatingEventArgs

Um EventArgs usado para descrever um evento de navegação que está prestes a ocorrer. O ShellNavigationEventArgs também pode ser usado para cancelar o evento de navegação se o desenvolvedor desejar.

public class ShellNavigatingEventArgs : EventArgs
{
  public ShellNavigationState Current { get; }

  public ShellNavigationState Target { get; }

  public ShellNavigationSource Source { get; }

  public bool CanCancel { get; }

  public bool Cancel ();
}

Propriedades:

| API | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| Atual | O NavigationState atual de Shell . Chamar GoToAsync com este ShellNavigationState desfará efetivamente este evento de navegação. |
| Alvo | O estado em que Shell estará após a conclusão deste evento de navegação. |
| Fonte | O tipo de navegação que ocorreu para acionar este evento. Pode haver vários sinalizadores definidos. |
| CanCancel | Se o evento de navegação pode ou não ser cancelado. Nem todos os eventos podem ser cancelados. |

Métodos públicos:

| API | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| Cancelar | Cancela o evento de navegação atual. Retorna verdadeiro se o cancelamento for bem-sucedido. |

ShellNavigatedEventArgs

public class ShellNavigatedEventArgs : EventArgs
{
  public ShellNavigationState Previous { get; }

  public ShellNavigationState Current { get; }

  public ShellNavigationSource Source { get; }
}

Propriedades:

| API | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| Anterior | O NavigationState anterior do Shell . |
| Atual | O novo estado em que Shell encontra quando este evento de navegação é concluído. |
| Fonte | O tipo de navegação que ocorreu para acionar este evento. Pode haver vários sinalizadores definidos. |

ShellNavigationState

public class ShellNavigationState
{
  public Uri Location { get; set; }

  public ShellNavigationState ();
  public ShellNavigationState (string location);
  public ShellNavigationState (Uri uri);

  public static implicit operator ShellNavigationState (Uri uri);
  public static implicit operator ShellNavigationState (String value);
}

Propriedades:

| API | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| Localização | O Uri que descreve o estado de navegação de Shell |

Construtores:

| API | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| (vazio) | Cria um novo ShellNavigationState com um local nulo |
| (String) | Cria um novo ShellNavigationState com a localização definida para o string |
| (Uri) | Cria um novo ShellNavigationState com o local definido para o Uri |

ShellNavigationSource

[Flags]
public enum ShellNavigationSource
{
  Unknown = 0,
  Push,
  Pop,
  PopToRoot,
  Insert,
  Remove,
  ShellItemChanged,
  ShellSectionChanged,
  ShellContentChanged,
}

BaseShellItem

public class BaseShellItem : NavigableElement
{
  public static readonly BindableProperty FlyoutIconProperty;
  public static readonly BindableProperty IconProperty;
  public static readonly BindableProperty IsCheckedProperty;
  public static readonly BindableProperty IsEnabledProperty;
  public static readonly BindableProperty TitleProperty;

  public ImageSource FlyoutIcon { get; set; }

  public ImageSource Icon { get; set; }

  public bool IsChecked { get; }

  public bool IsEnabled { get; set; }

  public string Route { get; set; }

  public string Title { get; set; }
}

Propriedades:

| API | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| FlyoutIcon | O ícone padrão a ser usado quando exibido no menu desdobrável. O padrão será o ícone se não for definido. |
| Ícone | O ícone a ser exibido em partes do cromo que não são o Flyout. |
| IsChecked | Se BaseShellItem estiver marcado no menu desdobrável (e, portanto, deve ser destacado) |
| IsEnabled | Se BaseShellItem for selecionável no cromo |
| Rota | Equivelant para definir Routing.Route |
| Título | O título a ser exibido na IU |

ShellGroupItem

public class ShellGroupItem : BaseShellItem
{
  public static readonly BindableProperty FlyoutDisplayOptionsProperty;;

  public FlyoutDisplayOptions FlyoutDisplayOptions { get; set; }
}

Propriedades:

| API | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| FlyoutDisplayOptions | Controla como este item e seus filhos são exibidos no menu desdobrável |

ShellItem

[ContentProperty("Items")]
public class ShellItem : ShellGroupItem, IShellItemController, IElementConfiguration<ShellItem>
{
  public static readonly BindableProperty CurrentItemProperty;

  public ShellItem();

  public ShellSection CurrentItem { get; set; }

  public ShellSectionCollection Items;

  public static implicit operator ShellItem(ShellSection shellSection);

  public static implicit operator ShellItem(ShellContent shellContent);

  public static implicit operator ShellItem(TemplatedPage page);

  public static implicit operator ShellItem(MenuItem menuItem);
}

Propriedades:

| API | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| CurrentItem | Os ShellSection selecionados. |
| Itens | O ShellSectionCollection que é o conteúdo principal de um ShellItem. Esta coleção define todas as guias em um ShellItem. |

ShellSection

[ContentProperty("Items")]
public class ShellSection : ShellGroupItem, IShellSectionController
{
  public static readonly BindableProperty CurrentItemProperty;
  public static readonly BindableProperty ItemsProperty

  public ShellSection();

  public ShellContent CurrentItem { get; set; }

  public ShellContentCollection Items { get; }

  public IReadOnlyList<Page> Stack { get; }

  public static implicit operator ShellSection(ShellContent shellContent);

  public virtual async Task GoToAsync(List<string> routes, IDictionary<string, string> queryData, bool animate);

  protected virtual IReadOnlyList<Page> GetNavigationStack();

  protected virtual void OnInsertPageBefore(Page page, Page before);

  protected async virtual Task<Page> OnPopAsync(bool animated);

  protected virtual async Task OnPopToRootAsync(bool animated);

  protected virtual Task OnPushAsync(Page page, bool animated);

  protected virtual void OnRemovePage(Page page);
}

Propriedades:

| API | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| CurrentItem | O ShellContent selecionado da seção Shell. |
| Itens | O ShellContentCollection que é o conteúdo raiz do ShellSection. |
| Stack | A pilha de navegação enviada atual no ShellSection. |

Métodos:

| API | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| GoToAsync | Usado por links diretos para navegar até um local conhecido. Não deve ser necessário ligar diretamente na maioria dos casos. |
| GetNavigationStack | Retorna a pilha de navegação atual |
| OnInsertPageBefore | Chamado quando o método INavigation interfaces InsertPageBefore é chamado |
| OnPopAsync | Chamado quando o método INavigation interfaces PopAsync é chamado |
| OnPopToRootAsync | Chamado quando o método INavigation interfaces PopToRootAsync é chamado |
| OnPushAsync | Chamado quando o método INavigation interfaces PushAsync é chamado |
| OnRemovePage | Chamado quando o método INavigation interfaces RemovePage é chamado |

ShellContent

[ContentProperty("Content")]
public class ShellContent : BaseShellItem, IShellContentController
{
  public static readonly BindableProperty ContentProperty;
  public static readonly BindableProperty ContentTemplateProperty;
  public static readonly BindableProperty MenuItemsProperty;

  public ShellContent();

  public object Content { get; set; }

  public DataTemplate ContentTemplate { get; set; }

  public MenuItemCollection MenuItems { get; }

  public static implicit operator ShellContent(TemplatedPage page);
}

Propriedades:

| API | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| Conteúdo | O conteúdo de um ShellContent. Normalmente ContentPage ou BindingContext de Page inflado por ContentTemplate |
| ContentTemplate | Usado para aumentar dinamicamente o conteúdo de ShellContent . A propriedade Content será definida como BindingContext após a inflação. |
| MenuItems | Os itens a serem exibidos no Flyout quando este ShellContent for a página apresentada |

SearchHandler

public class SearchHandler : BindableObject, ISearchHandlerController
{
  public static readonly BindableProperty ClearIconHelpTextProperty;
  public static readonly BindableProperty ClearIconNameProperty;
  public static readonly BindableProperty ClearIconProperty;
  public static readonly BindableProperty ClearPlaceholderCommandParameterProperty;
  public static readonly BindableProperty ClearPlaceholderCommandProperty;
  public static readonly BindableProperty ClearPlaceholderEnabledProperty;
  public static readonly BindableProperty ClearPlaceholderHelpTextProperty;
  public static readonly BindableProperty ClearPlaceholderIconProperty;
  public static readonly BindableProperty ClearPlaceholderNameProperty;
  public static readonly BindableProperty CommandParameterProperty;
  public static readonly BindableProperty CommandProperty;
  public static readonly BindableProperty DisplayMemberNameProperty;
  public static readonly BindableProperty IsSearchEnabledProperty;
  public static readonly BindableProperty ItemsSourceProperty;
  public static readonly BindableProperty ItemTemplateProperty;
  public static readonly BindableProperty PlaceholderProperty;
  public static readonly BindableProperty QueryIconHelpTextProperty;
  public static readonly BindableProperty QueryIconNameProperty;
  public static readonly BindableProperty QueryIconProperty;
  public static readonly BindableProperty QueryProperty;
  public static readonly BindableProperty SearchBoxVisibilityProperty;
  public static readonly BindableProperty ShowsResultsProperty;

  public ImageSource ClearIcon { get; set; }

  public string ClearIconHelpText { get; set; }

  public string ClearIconName { get; set; }

  public ICommand ClearPlaceholderCommand { get; set; }

  public object ClearPlaceholderCommandParameter { get; set; }

  public bool ClearPlaceholderEnabled { get; set; }

  public string ClearPlaceholderHelpText { get; set; }

  public ImageSource ClearPlaceholderIcon { get; set; }

  public string ClearPlaceholderName { get; set; }

  public ICommand Command { get; set; }

  public object CommandParameter { get; set; }

  public string DisplayMemberName { get; set; }

  public bool IsSearchEnabled { get; set; }

  public IEnumerable ItemsSource { get; set; }

  public DataTemplate ItemTemplate { get; set; }

  public string Placeholder { get; set; }

  public string Query { get; set; }

  public ImageSource QueryIcon { get; set; }

  public string QueryIconHelpText { get; set; }

  public string QueryIconName { get; set; }

  public SearchBoxVisiblity SearchBoxVisibility { get; set; }

  public bool ShowsResults { get; set; }

  protected virtual void OnClearPlaceholderClicked();

  protected virtual void OnItemSelected(object item);

  protected virtual void OnQueryChanged(string oldValue, string newValue);

  protected virtual void OnQueryConfirmed();
}

Propriedades:

| API | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| ClearIconHelpText | O texto de ajuda acessível para o ícone claro |
| ClearIconNameProperty | O nome do ícone claro para uso com leitores de tela |
| ClearIcon | O ícone exibido para limpar o conteúdo da caixa de pesquisa. |
| ClearPlaceholderCommandParameter | O parâmetro para ClearPlaceholderCommand |
| ClearPlacehodlerCommand | O comando a ser executado quando o ícone ClearPlaceholder é tocado |
| ClearPlaceholderEnabled | O estado habilitado do ClearPlaceholderIcon. O padrão é verdadeiro. |
| ClearPlaceholderHelpText | O texto de ajuda acessível para o ícone claro de espaço reservado |
| ClearPlaceholderIcon | O ícone exibido no local ClearIcon quando a caixa de pesquisa está vazia. |
| ClearPlaceholderName | O nome do ícone de espaço reservado para uso com leitores de tela |
| CommandParameter | O parâmetro para Command |
| Command | O ICommand para executar quando uma consulta for confirmada
| DisplayMemberPath | O nome ou caminho da propriedade que é exibido para cada item de dados em ItemsSource . |
| IsSearchEnabled | Controla o estado habilitado da caixa de pesquisa. |
| ItemsSource | Uma coleção de itens a serem exibidos na área de sugestão. |
| ItemTemplate | Um modelo para os itens exibidos na área de sugestões. |
| Placeholder | Uma string a ser exibida quando a caixa de pesquisa estiver vazia. |
| QueryIconHelpTextProperty | O texto de ajuda acessível para o ícone de consulta |
| QueryIconNameProperty | O nome do ícone de consulta para uso com leitores de tela |
| QueryIcon | O ícone usado para indicar ao usuário que a pesquisa está disponível |
| Query | A string atual na caixa de pesquisa. |
| SearchBoxVisibility | Define a visibilidade da caixa de pesquisa no cromo Shell s. |
| ShowsResults | Determina se os resultados da pesquisa devem ser esperados na entrada de texto |

Métodos protegidos:

| API | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| OnClearPlaceholderClicked | Chamado sempre que o ícone ClearPlaceholder é pressionado. |
| OnItemSelected | Chamado sempre que um resultado da pesquisa é pressionado pelo usuário |
| OnQueryConfirmed | Chamado sempre que o usuário pressiona enter ou confirma sua entrada na caixa de pesquisa. |
| OnQueryChanged | Chamado quando Query é alterado. |

SearchBoxVisiblity

public enum SearchBoxVisiblity
{
  Hidden,
  Collapsable,
  Expanded
}

| Valor | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| Oculto | A caixa de pesquisa não está visível ou acessível. |
| Dobrável | A caixa de pesquisa fica oculta até que o usuário execute uma ação para revelá-la. |
| Expandido | A caixa de pesquisa é visível como uma entrada totalmente expandida. |

BackButtonBehavior

public class BackButtonBehavior : BindableObject
{
  public ImageSource IconOverride { get; set; }
  public string TextOverride { get; set; }
  public ICommand Command { get; set; }
  public object CommandParameter { get; set; }
}

| API | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| IconOverride | Altera o ícone usado para o botão Voltar. |
| TextOverride | Altera o texto usado para indicar a navegação para trás se for usado texto. |
| Command | Fornece um comando de substituição a ser invocado quando o botão Voltar é pressionado. |
| CommandParameter | O parâmetro de comando usado com Command |

FlyoutDisplayOptions

Determina como ShellGroupItem deve ser exibido no FlyoutMenu.

  public enum FlyoutDisplayOptions
  {
    AsSingleItem,
    AsMultipleItems,
  }

| Valor | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| AsSingleItem | ShellGroupItem ficará visível como uma única entrada no menu desdobrável. |
| AsMultipleItems | O ShellGroupItem ficará visível como um grupo de itens, um para cada criança no submenu. |

FlyoutHeaderBehavior

Controla o comportamento do FlyoutHeader ao rolar.

public enum FlyoutHeaderBehavior {
  Default,
  Fixed,
  Scroll,
  CollapseOnScroll,
}

| Valor | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| Padrão | Comportamento padrão da plataforma. |
| Corrigido | O cabeçalho permanece sempre visível e inalterado |
| Scroll | Cabeçalho rola para fora de vista enquanto o usuário rola o menu |
| CollapseOnScroll | Cabeçalho é recolhido para título apenas quando o usuário rola |

FlyoutBehavior

public enum FlyoutBehavior
{
  Disabled,
  Flyout,
  Locked
}

| Valor | Descrição
| ----------- | -------------------------------------------------- -------------------------------------------- |
| Desativado | O flyout não pode ser acessado pelo usuário. |
| Flyout | O flyout funciona como um flyout normal que pode ser aberto / fechado pelo usuário. |
| Bloqueado | O Flyout está bloqueado e não pode ser fechado pelo usuário, ele não supera o conteúdo. |

DataTemplateExtension

Essa extensão converte rapidamente um tipo em um ControlTemplate. Isso é útil para casos em que o modelo seria especificado como

<ListView>
  <ListView.ItemTemplate>
    <DataTemplate>
      <local:MyCell />
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

Isso pode ser condensado em

<ListView ItemTemplate="{DataTemplate local:MyCell}" />
public sealed class ControlTemplateExtension : IBindingExtension<ControlTemplate>
public sealed class DataTemplateExtension : IBindingExtension<DataTemplate>

Miudezas

O que acontece quando você seleciona uma guia no submenu para a qual foi enviada?

Isso é o equivalente a focalizar a guia e chamar PopToRoot nela.

O que acontece quando eu troco ShellItems e há itens na pilha de backstack de um ShellContent do antigo ShellItem

Se o antigo ShellItem for modelado, a pilha de retorno será perdida. Se o ShellItem não tiver um modelo, o BackStack permanecerá intacto e, ao voltar para o ShellItem antigo, o backstack será refletido corretamente. Voltar pode limpar o backstack, no entanto, conforme indicado na resposta acima.

Carregamento eficaz de páginas

Um grande problema com o uso do Shell é a facilidade com que um usuário pode acabar carregando todas as páginas no início da execução do aplicativo. Essa grande alocação antecipada pode resultar em um desempenho de inicialização bastante ruim se um grande número de páginas de conteúdo for necessário. A fim de corrigir esse modelo, deve-se empregar sempre que possível.

ShellContents com modelo

A modelagem de itens da guia shell é a forma mais granular de modelagem disponível e, felizmente, também a mais fácil de fazer. Pegue a seguinte concha.

<?xml version="1.0" encoding="utf-8" ?>
<MaterialShell xmlns="http://xamarin.com/schemas/2014/forms"
               xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
               xmlns:local="clr-namespace:MyStore"
               x:Class="MyStore.Shell">

  <ShellItem Title="My apps &amp; games">
    <local:UpdatesPage />
    <local:InstalledPage />
    <local:LibraryPage />
  </ShellItem>

  <ShellItem GroupBehavior="ShowTabs">
    <local:HomePage />
    <local:GamesPage />
    <local:MoviesTVPage />
    <local:BooksPage />
    <local:MusicPage />
    <local:NewsstandPage />
  </ShellItem>
</MaterialShell>

Quando este Shell for carregado, todas as 9 páginas serão infladas de uma vez. Isso ocorre porque nenhum modelo é empregado. Para empregar modelos básicos, podemos converter isso em:

<?xml version="1.0" encoding="utf-8" ?>
<MaterialShell xmlns="http://xamarin.com/schemas/2014/forms"
               xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
               xmlns:local="clr-namespace:MyStore"
               x:Class="MyStore.Shell">

  <ShellItem Title="My apps &amp; games">
    <ShellContent Title="Updates"        Icon="updates.png" ContentTemplate="{DataTemplate local:UpdatesPage}" />
    <ShellContent Title="Installed Apps" Icon="apps.png"    ContentTemplate="{DataTemplate local:InstalledPage}" />
    <ShellContent Title="Library"        Icon="library.png" ContentTemplate="{DataTemplate local:LibraryPage}" />
  </ShellItem>

  <ShellItem GroupBehavior="ShowTabs">
    <ShellContent Title="Home"          Icon="updates.png"   ContentTemplate="{DataTemplate local:HomePage}" />
    <ShellContent Title="Games"         Icon="games.png"     ContentTemplate="{DataTemplate local:GamesPage}" />
    <ShellContent Title="Movies and TV" Icon="moviesTV.png"  ContentTemplate="{DataTemplate local:MoviesTVPage}" />
    <ShellContent Title="Books"         Icon="books.png"     ContentTemplate="{DataTemplate local:BooksPage}" />
    <ShellContent Title="Music"         Icon="music.png"     ContentTemplate="{DataTemplate local:MusicPage}" />
    <ShellContent Title="Newsstand"     Icon="newsstand.png" ContentTemplate="{DataTemplate local:NewsstandPage}" />
  </ShellItem>
</MaterialShell>

As páginas agora são carregadas apenas conforme necessário e podem ser descarregadas conforme necessário também. Se necessário, os próprios ShellItem também podem ser modelados com uma coleção e um DataTemplateSelector que evita que até mesmo os ShellContents tenham que ser carregados avidamente; no entanto, isso é amplamente desnecessário e modelar ShellItem é mais útil para Shells que têm ShellItems com um grande número de guias semelhantes. . A modelagem do ShellContent deve ser a área-chave para fornecer a modelagem para questões de desempenho.

Reconstruindo a interface do usuário da Google Play Store

Observe que isso não tem a intenção de ser uma demonstração da melhor maneira de codificar um aplicativo, mas, na verdade, o formato mais conciso para juntar a IU para GPS. Ele também não tenta virtualizar as páginas relevantes usando ViewModels e DataTemplateSelector's. Isso significa que o desempenho seria muito ruim, pois todas as páginas seriam carregadas no início do aplicativo. O leitor é avisado.

Todo o conteúdo da página está funcionando corretamente, isso é apenas para se ter uma ideia geral do cromo.

Shell.xaml

Uma implementação adequada disso usaria ShellItems para cada página e definiria ItemsSource e ItemTemplate. Isso permitiria que cada página fosse carregada apenas uma vez que fosse necessária e descarregada quando não fosse mais necessária.

<?xml version="1.0" encoding="utf-8" ?>
<MaterialShell xmlns="http://xamarin.com/schemas/2014/forms"
               xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
               xmlns:local="clr-namespace:MyStore"
               x:Class="MyStore.Shell"
               FlyoutHeaderBehavior="Fixed"
               FlyoutHeader="{x:Bind HeaderViewModel}">
  <MaterialShell.FlyoutHeaderTemplate>
    <local:CircleImageAndLabelControl HeightRequest="350" />
  </MaterialShell.FlyoutHeaderTempalte>

  <ShellItem Title="My apps &amp; games">
    <ShellItem.ShellAppearance>
      <MaterialShellAppearance NavBarCollapseStyle="Full">
    </ShellItem.ShellAppearance>
    <local:UpdatesPage />
    <local:InstalledPage />
    <local:LibraryPage />
  </ShellItem>

  <local:NotificationsPage Title="My notifications" />

  <local:SubscriptionsPage />

  <ShellItem GroupBehavior="ShowTabs">
    <ShellItem.ShellAppearance>
      <MaterialShellAppearance NavBarCollapseStyle="Full" TabBarCollapseStyle="Full" UseSwipeGesture="false">
    </ShellItem.ShellAppearance>
    <local:HomePage />
    <local:GamesPage />
    <ShellContent Title="Movies &amp; TV" Icon="moviesTV.png" ContentTemplate="{DataTemplate local:MoviesTVPage}">
      <ShellContent.MenuItems>
        <MenuItem Title="Open Movies &amp; TV app" Command="{xBind MoviesTVAppCommand}" />
      </ShellContent.MenuItems>
    </ShellContent>
    <ShellContent Title="Books" Icon="books.png" ContentTemplate="{DataTemplate local:BooksPage}">
      <ShellContent.MenuItems>
        <MenuItem Title="Open Books app" Command="{xBind BooksAppCommand}" />
      </ShellContent.MenuItems>
    </ShellContent>
    <ShellContent Title="Music" Icon="music.png" ContentTemplate="{DataTemplate local:MusicPage}">
      <ShellContent.MenuItems>
        <MenuItem Title="Open Music app" Command="{xBind MusicAppCommand}" />
      </ShellContent.MenuItems>
    </ShellContent>
    <ShellContent Title="Newsstand" Icon="newsstand.png" ContentTemplate="{DataTemplate local:NewsstandPage}">
      <ShellContent.MenuItems>
        <MenuItem Title="Open Newsstand app" Command="{xBind NewsstandAppCommand}" />
      </ShellContent.MenuItems>
  </ShellItem>

  <local:AccountPage />

  <MenuItem Title="Redeem" Icon="redeem.png" Command="{x:Bind RedeemCommand}" />

  <local:WishlistPage />

  <MenuItem Title="Play Protect" Icon="protect.png" Command="{x:Bind NavigateCommand}" CommandParameter="ProtectPage" />

  <MenuItem Title="Settings" Icon="settings.png" Command="{x:Bind SettingsCommand}" CommandParameter="SettingsPage" />

  <MaterialShell.MenuItems>
    <MenuItem Title="Help &amp; feedback" Command="{x:Bind NavigateCommand}" CommandParameter="HelpPage" />
    <MenuItem Title="Parent Guide" Command="{x:Bind NavigateCommand}" CommandParameter="ParentPage" />
    <MenuItem Title="Help &amp; feedback" Command="{x:Bind UrlCommand}" CommandParameter="http://support.google.com/whatever" />
  </MaterialShell.MenuItems>
</MaterialShell>

As páginas da loja

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:MyStore"
             x:Class="MyStore.HomePage"
             Title="Home"
             Icon="home.png"
             ShellAppearance.BackgroundColor="Green">
  <Label Text="Home content here" />
</ContentPage>
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:MyStore"
             x:Class="MyStore.MoviesTVPage"
             Title="Movies &amp; TV"
             Icon="movies.png"
             ShellAppearance.BackgroundColor="Red">
  <Label Text="Movies and TV content here" />
</ContentPage>

E para adicionar a barra de pesquisa.

public class HomePage : ContentPage
{
  public class HomeSearchHandler : SearchHandler
  {
    public HomeSearchHandler ()
    {
      SearchBoxVisibility = SearchBoxVisibility.Expanded;
      IsSearchEnabled = true;
      Placeholder = "Google Play";
      CancelPlaceholderIcon = "microphone.png"
    }

    protected override void OnSearchConfirmed (string query)

{      // Navigate to search results page here
    }

    protected override void OnSearchChanged (string oldValue, string newValue)
    {
    }

    protected override void OnCancelPlaceholderPressed ()
    {
      // Trigger voice API here
    }
  }

  public HomePage
  {
    Shell.SetSearchHandler (this, new HomeSearchHandler ());
  }  
}

E assim por diante, definindo as cores e o conteúdo corretamente.

Para páginas como a página Configurações, em que o menu desdobrável não deve estar acessível até que o botão Voltar seja pressionado:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:MyStore"
             x:Class="MyStore.SettingsPage"
             Title="Settings"
             Icon="settings.png"
             ShellAppearance.BackgroundColor="Grey"
             MaterialShell.FlyoutBehavior="Disabled">
  <Label Text="Settings content here" />
</ContentPage>

PENDÊNCIA

  • [x] Adicionar API para caixa de pesquisa
  • [x] Adicionar API para manipulação de ContentSafeArea
  • [x] Adicionar API para menu flutuante
  • [x] Adicionar API para itens de menu de janela
  • [x] Adicionar API para snackbar
  • [x] Adicionar API para interrupção de navegação
  • [x] Adicionar API para folha inferior
  • [x] Adicionar API para posicionar FAB
  • [x] Adicionar histórias para tornar as ideias de navegação mais claras (parcialmente concluído)
  • [x] Adicionar API de estilo LeftBarButton
  • [x] Adicionar mecanismo para obter Back Stack de ShellContent
  • [x] Adicionar API para alterar a cor da faixa de opções com base na guia selecionada
  • [x] Adicionar suporte de sugestão opcional para SearchHandler
  • [x] Adicionar suporte para configurar a barra de pesquisa sempre expandida vs barra de pesquisa como ícone
  • [x] Adicionar API para obter a página "Atual" da classe MaterialShell. Necessário para alguns cenários de navegação.
  • [x] Adicionar API para salvar "estados" na pilha posterior
  • [x] Adicionar API para impedir que o flyout seja lançado
  • [x] Adicionar API para itens de "submenu" para o ala GPS de ShellContent -> Música -> Abrir aplicativo de música
  • [x] Adicionar API para comando e ícone CancelPlaceholder (geralmente usado para ícone de microfone para pesquisa por voz)
  • [x] API Segue
  • [x] Descubra o que fazer com o INavigation
  • [] Expandir API da folha inferior para corresponder aos recursos do Google Maps
  • [x] API para lidar com a apresentação Flyout
  • [] API para desativar o gesto Flyout quando necessário
  • [] API de título grande
  • [] API de Transições

Problemas

ISearchHandler [CORRIGIDO]

Essa interface está fazendo muitas coisas e, pior, provavelmente precisará ser expandida com o passar do tempo. Portanto, é lógico que, provavelmente, em vez disso, seja uma classe base abstrata que o usuário possa implementar. Este infeliz significa ainda outra alocação de objeto. No entanto, ele mantém a flexibilidade no futuro. É provável que essa mudança aconteça.

Menu Flutuante

A API de anexos é um pouco pesada e talvez muito confusa para os usuários. Pior, pode não mapear muito bem para todas as plataformas para garantir que o anexo funcione com animações. É necessário mais trabalho para validar esta API.

shell enhancement ➕

Comentários muito úteis

Gente, ontem Jason e eu conversamos sobre como melhorar esta especificação e faremos uma grande atualização, estamos dividindo isso em diferentes questões.

Todos 199 comentários

Vamos começar a conversa animada, porque realmente precisamos ouvir de você, nossa comunidade de desenvolvedores!

PRIMEIRO, obrigado @jassmith por trabalhar para capturar isso e criar uma proposta para discutirmos abertamente aqui.

Vou compartilhar alguns de meus pensamentos, fazer algumas perguntas estúpidas e fazer algumas perguntas que espero não sejam muito importantes. Como gerente de programa do Xamarin. Formulários, muitas vezes tenho que fazer perguntas de uma forma que parece que não tenho a menor ideia (às vezes não), mas na verdade eu só preciso ouvir coisas de VOCÊ, sem colocando palavras em sua boca.

Há coisas de que gosto nesta proposta, porque posso ver como elas podem resolver alguns dos problemas que tenho falado com muitos, muitos de vocês, e estamos trabalhando para resolver.

Eu também tenho reservas.

Vou começar aqui com alguns tópicos gerais de reflexão sobre o conceito Shell e a experiência do desenvolvedor.

Experiência de aplicativo

para obter uma experiência de aplicativo completa e devidamente estruturada, usa os elementos certos, com muito pouco esforço e um caminho claro para ser bom por padrão.

Se eu usar essa abordagem para descrever meu aplicativo no nível superior, obtenho:

  • um aplicativo com o mesmo tema em todas as plataformas
  • padrões de material design (neste caso) ativados por padrão
  • os padrões de navegação mais recentes habilitados com configuração
  • Não tenho que trabalhar para personalizar a entrada ou o botão para ter a mesma aparência no iOS, Android e UWP?

Isso é correto? Outros benefícios que devo destacar?

Em vez de App eu tenho MaterialShell . Preciso aprender / adotar um novo paradigma de aplicativo de nível superior para me beneficiar disso?

Assim que entrar em meu aplicativo, estou de volta ao terreno de ContentPage , correto? Mas todos os meus Button s e Entry s são materiais e bonitos. Ainda posso OnPlatform e similares para divergir a aparência (ou comportamento) para ser diferente em outra plataforma?

Qual é a aparência do meu caminho de migração de um aplicativo existente para usar este "shell"? Eu apresento o novo MaterialShell , descrevo como quero que meu aplicativo tenha estrutura e aparência e apenas o executo para ver as novas vantagens.

Customizando

Quais são minhas opções se gosto da aparência de Flyout ou dos itens do menu, mas preciso ajustá-los para que correspondam às composições de meus designers? Em que ponto estou dizendo "Ugh, eu deveria ter feito isso sozinho" e movendo o que tenho para uma estrutura de aplicativo Xamarin.Forms padrão?

Se eu tiver que abandonar totalmente MaterialShell , eu perco todas as qualidades do estilo e estou de volta onde comecei (como hoje) com um Entry parecendo bem diferente entre iOS e Android e UWP ? Eu gostaria de não.

Há um ponto de inflexão que estou antecipando. Depois de usar essa abordagem para começar rapidamente, atingirei algumas limitações e preciso explorar minhas opções. O que são e em que ponto é melhor não usar MaterialShell ?

O problema

Vou encerrar este primeiro comentário com algumas perguntas para todos que estão lendo.

  • O problema que esta proposta tenta resolver está bem definido?
  • É um problema que você compartilha?
  • Ao ler esta especificação, quais problemas você enfrentou em projetos anteriores você acha que isso resolveria para você?

Se possível, capturas de tela / imagens de design seriam ainda melhores.

Verifique também:

http://www.noesisengine.com/webgl/Samples.Buttons.html

@jassmith Teria sido ótimo se toda a ideia fosse apresentada como imagens. Parabéns pelo esforço de colocar as especificações acima. Minhas perguntas podem não estar corretas.

Minhas dúvidas são

  • Suporte para tablet, capacidade de resposta do aplicativo adaptando-se a layout diferente não é abordada.
  • A migração do modelo atual para o novo modelo será um desafio? Da perspectiva do desenvolvedor de aplicativos e da perspectiva dos contribuidores do Xamarin Forms.
  • Eu concordo que a maioria do aplicativo precisa de uma única IU (causa a quantidade de renderizadores personalizados que temos que escrever em algum momento para atingir os mesmos conceitos de IU) sem respeitar as especificações da plataforma, a nova direção removerá todos os recursos existentes, como ainda desenvolveremos Xamarin.Forms aplicativos com interface de usuário específica da plataforma, ou todos serão forçados a novos padrões.
  • Os conceitos de renderizador ainda existirão dentro do MaterialShell
  • Podemos dizer que, no iOS, queremos que isso seja renderizado dessa forma? Flutter tem Cupertino Styles (apple UI), que funciona no Android, e Android UI, que funciona no iOS. Em que direção os Formulários Xamarin se moverão. O desenvolvedor terá esse tipo de capacidade que a vibração oferece agora.

Isso também incluirá algo semelhante ao TextInputLayout para oferecer suporte a rótulos / marcadores flutuantes, bem como mensagens de erro? Se sim, então acho que Binding deve ser estendido para incluir 'ValidateOnDataErrors` semelhante a wpf.

Veja minha implementação disso aqui
https://github.com/XamFormsExtended/Xfx.Controls/blob/develop/src/Xfx.Controls/XfxBinding.cs

Além disso, eu me pergunto se o MaterialShell deve estender o Shell para que se possa criar um HumanInterfaceShell para a aparência do iOS.

@ChaseFlorell esse seria meu comentário também. O material é ótimo, mas é outra coisa se quisermos escrever nossos próprios shells para atender às necessidades específicas da IU.

@davidortinau , @jassmith ,

Obrigado por reunir esta especificação e nos permitir fornecer comentários.

O problema que esta proposta tenta resolver está bem definido?

sim. O sistema de navegação não está totalmente desenvolvido no Xamarin Forms, portanto, há uma questão em aberto sobre como completá-lo ou contorná-lo completamente.

É um problema que você compartilha?

sim.

Ao ler esta especificação, quais problemas você enfrentou em projetos anteriores você acha que isso resolveria para você?

Vou responder com essa pergunta dizendo que não acho que isso resolverá os problemas. Nossos problemas particulares são que o sistema de navegação atual é muito rígido, não que não seja rígido o suficiente. O exemplo mais claro para nós é o TabbedPage. Não há visualização TabbedView, portanto, se quisermos guias em nosso aplicativo, devemos usar TabbedPage. Portanto, toda a tela deve ser ocupada pela TabbedPage e não podemos usar o estado real para os próprios botões ou outros controles que possamos querer colocar na tela. Minha recomendação teria sido mover mais funcionalidade _ fora de_ Páginas e para baixo para Visualizações, em vez de mover a funcionalidade em Páginas para uma camada ainda mais alta.

Coisas como FloatingMenu e FlyoutBehavior me assustam porque implicam que a navegação será ainda mais codificada no sistema Xamarin.Forms e controle adicional será retirado dos desenvolvedores de software. Eu posso ver algum valor em ter uma abordagem mais padronizada, mas isso certamente terá um custo.

Sempre trabalhamos em outras tecnologias baseadas em XAML, como Silverlight, WPF e UWP. Nessas tecnologias, temos uma abordagem muito mais aberta, onde podemos definir mais sobre como a navegação funciona. Recentemente, contratamos um consultor de UI / UX. Ele não sabia das peculiaridades de XF. Nós apenas pedimos a ele que construísse algumas telas com base na funcionalidade de nosso software. Grandes partes do que ele recomendou não puderam ser implementadas por causa de coisas como não ter um TabbedView. Temo que, em vez de tornar a navegação mais fácil, o que acontecerá é que esse framework tornará mais difícil implementar os designs que nos são fornecidos pelos designers de UX / UI.

A outra coisa que eu diria é que essa estrutura parece sem precedentes em outras plataformas XAML, e eu diria que a prioridade deve ser fornecer padronização entre as plataformas, em vez de fornecer novas estruturas com as quais as outras plataformas não sejam compatíveis. No momento, estamos construindo para três plataformas: Silverlight, Xamarin.Forms e WPF. O que precisamos é padronização entre essas plataformas para criar menos desvio, não mais.

@dylanberry ,

outra coisa é se quisermos escrever nossos próprios shells para atender às necessidades específicas da IU.

sim. Essa é a minha preocupação. Cada aplicativo tem seus próprios casos de uso específicos, e mais rigidez provavelmente tornará isso mais difícil - não mais fácil de implementá-los.

Também existe essa preocupação: https://github.com/xamarin/Xamarin.Forms/issues/2452#issuecomment -380991817

Vou repetir o que foi dito acima, e também perguntar como os gestos e ponteiros funcionarão em seus primitivos de forma.

Um comentário geral é que para cada linha de código adicionada a um sistema, há mais de 3 chances de código com erros sendo adicionado. Já existem muitos bugs no Xamarin Forms que precisam ser corrigidos. Mais código significa que as chances de bugs serem adicionados aumentam exponencialmente. Haverá mais bugs. Acho que a equipe do XF deve trabalhar para reduzir o tamanho da base de código, em vez de aumentá-la. Diminuir a base de código é a única maneira de diminuir a probabilidade de ocorrência de bugs.

Por que inventar uma coisa nova novamente em vez de consertar os bugs existentes e primeiro ter certeza de que tudo é sólido como uma rocha?

Para mim, foi abordado, mas a navegação é o maior obstáculo no Xamarin Forms e me causou mais dor de cabeça nos últimos três anos.

A navegação não é consistente em todas as três plataformas com o padrão MasterDetail causando muitos problemas com o hambúrguer forçando você a empurrar as páginas modais, então você tem que implementar uma barra de navegação personalizada, pois você não pode adicionar de volta, mas a animação parece horrível no Android (mesmo em MD).

  • Idealmente, você deve ser capaz de cancelar e substituir o conteúdo da barra de navegação por seu próprio ContentView em muitos casos. PlatformSpecifics foi originalmente cogitado como algo que teria permitido o posicionamento de itens da barra de ferramentas (quando eu estava falando com Bryan), mas parecia ser algo de uso limitado.

  • Capacidade de sobrescrever coisas da estrutura, como animações pop-up de página

Muito do que é proposto parece muito útil, contanto que você possa apenas usar o material shell em páginas específicas e não seja para todo o aplicativo, o código será realmente útil. Certamente é algo que usaríamos porque no momento eu continuo dizendo "é uma limitação do Xamarin Forms" para nosso cara de UX (como eu fiz em meu papel anterior). Atrevo-me a dizer, devemos obter o feedback de uma perspectiva de UX que já estilizou os aplicativos Forms. Deve ser opcional como o XamlC.

Não tenho certeza sobre o nome, porém, FlexShell faria mais sentido ... mas agora temos Flexbox (embora nunca tenhamos pedido por isso ... desculpe David, não pude evitar 😄)

Além disso, isso significaria que os temas estão meio mortos? nunca os usei de qualquer maneira.

@mackayn

Certamente é algo que usaríamos porque no momento eu continuo dizendo "é uma limitação do Xamarin Forms" para nosso cara de UX (como eu fiz em meu papel anterior).

OK, mas não faria mais sentido corrigir ou melhorar a implementação atual em vez de criar uma completamente nova, que virá com bugs e limitações também? Diz aí que:

MaterialShell é uma API opinativa em alguns pontos "

Sério, em quantas direções diferentes os Formulários Xamarin podem ir? A equipe do XF mal consegue manter a correção da implementação atual do XF pelo menos para Android e iOS, e agora isso? E quanto à correção de bugs, correção de visualização XAML, e quanto ao desempenho?

Alguém \ foi aberto um tíquete com uma proposta de adicionar suporte simples, mas muito útil, para sólido e gradiente de plataforma cruzada, mas a resposta de @jassmith foi que seria problemático. Mas agora este bilhete propõe a mesma coisa ... Como isso não é mais problemático? Vai saber

@opcodewriter

Sim, eu venho dizendo isso no ano passado, há estranhezas de navegação que atrapalham a equipe do Prism, por exemplo, e eles nunca conseguiram resolver os problemas.

No entanto, estou apenas tentando oferecer um feedback construtivo, o Xamarin Forms está em um momento crítico em sua evolução, esta API pode resolver muitos dos pontos problemáticos se for implementada de forma flexível e não em uma abordagem ampla do aplicativo.

@jassmith isso significa que o XF usará a abordagem Flutter (usando um mecanismo de renderização em vez de controles nativos) para o Shell?

Gente, ontem Jason e eu conversamos sobre como melhorar esta especificação e faremos uma grande atualização, estamos dividindo isso em diferentes questões.

Eu gostaria de repetir alguns dos sentimentos acima: por favor, vamos apenas melhorar o que temos, a menos que você tenha recursos ilimitados, então vá em frente 😉

Há tantas coisas ainda deixadas de fora: consertar ListView (difícil de acreditar que ainda não funciona corretamente), implementar controles como CheckBox, RadioButton, implementar suporte a pincel (SolidColorBrush, GradientBrush), capacidade de exibir um Popup baseado em uma página ou ContentView, corrigindo bugs (veja bug relatado recentemente sobre visualizações transparentes), desempenho, ferramentas e muito mais ....

Por que você quer começar uma coisa nova ?????

@TonyHenrique Sim, as fotos seriam ótimas. Infelizmente, não sou um artista e não detenho os direitos das imagens que uso para minha referência. Espero que algum membro da equipe de design tenha tempo para me ajudar a produzir imagens adequadas para as especificações.

@muhaym

  • Suporte para tablet. O objetivo é garantir que o layout seja adaptável a tablets. Isso não vai cobrir casos de layout dentro de suas páginas de conteúdo, é claro, isso seria um recurso diferente. Em grande parte, eu lidaria com isso com o novo VSM.
  • Principalmente apenas colocando suas páginas de conteúdo no lugar certo e adaptando-se aos novos conceitos de navegação. Não direi que sempre será trivial, mas também não deve ser debilitante.
  • Absolutamente não removerá nenhum recurso. Na verdade, estou trabalhando na atualização das especificações para incluir uma classe base Shell que perde alguns dos recursos do MaterialShell, mas é uma versão de interface do usuário específica da plataforma do Shell.
  • sim. Adicionar um desenho apenas muda o renderizador que você obtém para algo que sabe como lidar com um desenho.
  • sim. Você pode trocar qual renderizador é usado em qualquer nível da hierarquia. Os renderizadores são alterados apenas por modelos sendo configurados com chaves especiais nos dicionários de recursos. Você pode alterar esses modelos para o que quiser ou desativá-los definindo nulos para eles.

@ChaseFlorell não, mas estou aberto a sugestões se você quiser anexar uma emenda às especificações. Quanto à coisa Shell vs MaterialShell, abordei isso acima. A etapa 1 foi garantir que o MaterialShell fazia sentido, em seguida, dividi-lo em uma classe base é a etapa 2.

@dylanberry a classe base realmente não tornará isso muito mais fácil. Não é tão simples quanto alterar DrawingTemplates. Pretendo implementar o aspecto MaterialShell disso no código específico da plataforma para obter um desempenho ideal.

Gestos @ RichiCoder1 virão aqui, mas a essência é que as visualizações com gestos de sub-região vêm como parte da API CommandableSpan e serão expandidos para oferecer suporte a desenhos com gestos também. No entanto, em geral, seria aconselhável NÃO usar gestos e deixar os back-ends nativos manipularem a entrada. Isso não está relacionado à especificação do MaterialShell neste momento e pertence à especificação do Drawing, onde estou feliz em entrar em mais detalhes. O longo e o curto são o motivo pelo qual o DrawingTemplate é importante é que podemos incluir um SliderDrawingTemplate que tem vários Drawings dos quais o renderizador sabe como compor um controle deslizante e permite que a manipulação de entrada continue a ser tratada no backend nativo. Isso não significa que você seria forçado a fazer isso, seria simplesmente uma coisa opcional tornar o renderizador o mais rápido possível.

@mackayn uma API de Transitions / Segue está chegando e deve chegar aqui em breve. Ainda estou trabalhando na nomenclatura da minha proposta inicial. Certamente será algo que vem em fases, com apenas Transistions de página na fase 1. Isso permitirá que você substitua as animações do framework. Quanto ao opt-in. O Shell deve ser a raiz do seu aplicativo e não pode aninhar nada além do TemplatedPage. Dito isso, o tema do controle interno está 100% sob seu controle. É pouco mais do que um botão mágico para ligar / desligar os novos modelos e você pode controlar esse botão da mesma forma que faremos. Isso permite que você aceite e exclua os temas na página, no layout ou até mesmo no nível de controle.

@ encrypt0r não exatamente. Pense nisso como um híbrido. Ele permitirá a renderização, mas, por baixo do capô, todos os controles específicos da plataforma serão apenas temáticos com o código de desenho. No entanto, há uma saída de emergência para o Skia que pode ser facilmente adicionada (embora eu duvide que seja perto de uma v1).

@opcodewriter ListView2 (obviamente não será chamado assim) está finalmente no roteiro deste ano. Por que um novo ListView? Bem, a API original leva a um número quase ilimitado de bugs e problemas que não podemos corrigir de forma eficaz sem quebrar totalmente a compatibilidade com versões anteriores. Coisas como Cell / ViewCell e ItemsViewe a TemplatedItemsList, embora funcionassem bem para o que deveriam ser 1.0, não são nem de longe capazes do que precisam para o uso moderno da API.

Infelizmente, não consigo pensar em nenhuma maneira de resolver isso no próprio tipo de ListView e, infelizmente, não acho que a comunidade tenha conseguido. A melhor opção agora é manter ListView como está e, em seguida, fazer algo muito mais elegante com menos sobrecarga, menos contabilidade, menos tipos estranhos que não precisam existir e confiar nas estruturas de destino para fazer o que fazem melhor.

Simplesmente removendo a estratégia de reciclagem antiga, que seria uma grande alteração de quebra de backcompat que não podemos fazer, removeria uma parte considerável da base de código Xamarin.Forms. ListView2 o deixará muito mais perto do metal removendo esses itens que deveriam ser grades de proteção (ou, no caso do Cell, a fusão profana de 2 projetos internos diferentes) e agora estão prejudicando a todos.

A velha estratégia de cache impacta TODOS os renderizadores existentes hoje. É a razão pela qual todo renderizador suporta que seu Elemento seja alterado. Se isso sumisse de acordo com minha melhor estimativa, cerca de 10% de todo o código do projeto iria embora. É realmente o maior câncer do projeto.

@davidortinau você recebe seu próprio comentário só porque o seu tem uma formatação adorável!

Se eu usar essa abordagem para descrever meu aplicativo no nível superior, obtenho:

  • um aplicativo com o mesmo tema em todas as plataformas
  • padrões de material design (neste caso) ativados por padrão
  • os padrões de navegação mais recentes habilitados com configuração
  • Não tenho que trabalhar para personalizar a entrada ou o botão para ter a mesma aparência no iOS, Android e UWP?

Isso é correto? Outros benefícios que devo destacar?

Sim, está correto. Existem muitos outros benefícios que você pode destacar, mas eles devem se tornar óbvios assim que você começar a mexer com eles. Assim como você pode fazer folhas de baixo, ter um FAB, navegar usando URLs (atualização ainda em breve) e muito mais.

Em vez de App, tenho MaterialShell. Preciso aprender / adotar um novo paradigma de aplicativo de nível superior para me beneficiar disso?

Errado. Seus aplicativos MainPage é o MaterialShell. O aplicativo ainda é a raiz do aplicativo.

Assim que entrar em meu aplicativo, estou de volta ao terreno da página de conteúdo, correto? Mas todos os meus botões e entradas são materiais e bonitos.

Com exceção de onde você estava errado acima, sim, isso está correto.

Posso ainda OnPlatform e similares para divergir a aparência (ou comportamento) para ser diferente em outra plataforma?

sim.

Qual é a aparência do meu caminho de migração de um aplicativo existente para usar este "shell"?

Veja o caso de reprodução da Google Play Store, imagine colocar todas as páginas atuais de seus aplicativos lá. Isso apenas substitui as áreas em seu aplicativo onde você está usando diretamente as páginas Nav / Tab / MD. Não tem nenhum impacto em suas páginas de conteúdo.

Eu apresento o novo MaterialShell, descrevo como quero que meu aplicativo tenha estrutura e aparência e apenas o executo para ver as novas vantagens.

Bingo

Quais são minhas opções se gostar da aparência do Flyout ou dos itens de menu, mas preciso ajustá-los para que correspondam às composições de meus designers?

Você controla totalmente o cabeçalho, como o cabeçalho é recolhido e oculto. Você controla totalmente a aparência de cada uma das "Células" (elas não serão células) no menu desdobrável. Você também controla totalmente o cabeçalho de cada grupo. Na verdade, você controla a "aparência" de tudo, no entanto, ainda precisamos adicionar alguns lugares adicionais para você colocar conteúdo extra.

Em que ponto estou dizendo "Ugh, eu deveria ter feito isso sozinho" e movendo o que tenho para uma estrutura de aplicativo Xamarin.Forms padrão?

Se o menu desdobrável do layout físico da Google Play Store parecer completamente diferente do que você deseja. Não marginalmente diferente, completamente diferente.

Se eu tiver que abandonar totalmente o MaterialShell, eu perco todas as qualidades do estilo e estou de volta onde comecei (como hoje) com um Entry que parece bastante diferente entre iOS e Android e UWP? Eu gostaria de não.

No MaterialShell está apenas configurando alguns recursos padrão para que seus filhos os obtenham. Você poderá fazer isso sozinho. Você pode ter que fazer isso de qualquer maneira, na verdade não nos comprometemos a fazer o MaterialShell fazer isso por padrão. Se o fizermos opt-in em vez de opt-out, será uma única chamada de API para qualquer subárvore.

Há um ponto de inflexão que estou antecipando. Depois de usar essa abordagem para começar rapidamente, atingirei algumas limitações e preciso explorar minhas opções. O que são e em que ponto é melhor não usar o MaterialShell?

A intenção é que você NUNCA seja melhor se você não for Shell. Você pode não querer Material, mas deve sempre querer Shell (novamente, a classe base Shell está chegando). Porque? A aparência do shell será muito mais configurável, a história de navegação será muito mais unificada, não deve haver nada lógico que você possa fazer com as outras páginas que não possa ser feito com o Shell.

Melhor, a intenção é garantir que os renderizadores Shell sejam realmente configurados com facilidade e sãos. Não há classes ocultas mágicas, nem subclasses de visão nativa customizada nas quais trabalhamos intensamente. Tanto quanto possível, todos os componentes dos renderizadores serão compostos e trocáveis. Dessa forma, se não funcionar como você deseja, você pode realmente consertá-lo ...

Por que não fizemos isso no início? Não era um objetivo de design nos primeiros dias e então acabamos nos casando com isso ... Isso é grande o suficiente e novo o suficiente para que não tenhamos que carregar esse erro conosco.

@opcodewriter

Sério, em quantas direções diferentes os Formulários Xamarin podem ir? A equipe do XF mal consegue manter a correção da implementação atual do XF pelo menos para Android e iOS, e agora isso?

E quanto à correção de bugs, correção de visualização XAML, e quanto ao desempenho?

^^ Este

@migueldeicaza

Gente, ontem Jason e eu conversamos sobre como melhorar esta especificação e faremos uma grande atualização, estamos dividindo isso em diferentes questões.

Miguel, com certeza vai ser um grande trabalho. Não posso falar em nome de todos os desenvolvedores, mas posso dizer que minha equipe quer três coisas: estabilidade, desempenho e flexibilidade. Queremos bugs corrigidos. Queremos que nosso aplicativo funcione sem problemas e queremos ser capazes de implementar os designs que nossos designers de UI / UX nos fornecem sem nos virar e dizer "Desculpe, isso não é possível em nossa plataforma". Esta especificação parece ir contra esse objetivo. Isso vai exigir que mais recursos sejam empregados no trabalho, o que significa que seus recursos não serão liberados para trabalhar em estabilidade, desempenho e flexibilidade.

Seria este o novo comportamento / forma padrão de desenvolver em formulários xamarin? Ou ainda teríamos a opção de construir nossos aplicativos com aparência e comportamento específicos de cada plataforma?

@DanielCauser, embora eu suspeite que, a longo prazo, isso pode se tornar a forma "padrão", mas de forma alguma substituirá a forma atual. Será simplesmente uma forma mais integrada e moderna que fornecerá muito mais do shell que as pessoas estão construindo manualmente por padrão. Além disso, como forneceremos o shell como um único controle, podemos otimizar muito sobre como ele é desenhado e organizado. Você não terá mais 3 passes de desenho apenas para sua concha.

Sou cauteloso a favor dessa ideia, desde que as melhorias que ela propõe sejam trabalhadas por meio de melhorias no código Xamarin Forms subjacente. Se isso adicionar mais complexidade ao Formulários, eu não o usaria.
No entanto, para meu dinheiro, eu preferiria muito mais ter recursos de desenvolvedor direcionados para tornar o Forms mais flexível, rápido e finalizado do que é atualmente. Se isso acontecesse, eu poderia fazer todos os novos recursos propostos aqui para mim. DIY, neste caso, é quase certo que se adapte melhor a mim e aos meus clientes do que um kit de ferramentas genérico fornecido pela Xamarin, por melhor que seja. Com algumas exceções notáveis, esta proposta não resolve os problemas que estou enfrentando no momento.

@jassmith

  1. Existem mais de 500 questões em aberto.
  2. O Xamarin Forms tem 3 anos e ainda há bugs nos controles básicos e na funcionalidade, recursos importantes ainda estão faltando e o desempenho ainda não foi totalmente definido (sei que algumas melhorias foram feitas, mas o desempenho no Android está abaixo da média).
  3. A equipe de desenvolvimento do Xamarin Forms ainda é subdimensionada.

Por que você quer começar a trabalhar nesse novo recurso agora? Não faz mais sentido se concentrar no que precede primeiro?

Sobre o seu comentário acima relacionado ao ListView: Eu aplaudo qualquer tipo de abordagem ousada sobre ele, incluindo completamente redesenhar / substituí-lo. Não é como se tudo fosse tão bom no Xamarin Forms que as coisas não deveriam ser tocadas / alteradas.

@opcodewriter

1) Sim, existem. Eu concordo que é um problema e continuará a ser o item de trabalho prioritário que eu pessoalmente busco.

2) O desempenho no Android é parte do motivo principal para isso. Isso dá ao framework mais tempo para as transições de página, para que possamos ocultar coisas como o tempo JIT. Podemos carregar e reter páginas de maneira proativa com muito mais inteligência. O que a equipe XF não consegue consertar é o tempo JIT geral. Se você executa seu aplicativo no Android com AOT ativado e é muito mais rápido, não há nada que eu possa fazer para ajudá-lo.

3) Sem argumentos aqui.

Por que você quer começar a trabalhar nesse novo recurso agora? Não faz mais sentido se concentrar no que precede primeiro?

Este trabalho não está programado, estamos apenas discutindo uma especificação aqui. Minha gerência irá agendá-lo quando achar apropriado com meu conselho.

Sobre o seu comentário acima relacionado ao ListView: Eu aplaudo qualquer tipo de abordagem ousada sobre ele, incluindo completamente redesenhar / substituí-lo. Não é como se tudo fosse tão bom no Xamarin Forms que as coisas não deveriam ser tocadas / alteradas.

ListView é realmente o bug do Xamarin.Forms. Desses 500 problemas, 220 dos quais estão marcados como bugs (existem muitos problemas de manutenção ou aprimoramento também), ao norte de 25% são apenas para fazer com ListView. Para efeito de comparação, é quase a mesma porcentagem que tem a ver com toda a plataforma UWP. Pior, um bom número de crashers no Android que são basicamente descritos como o renderizador é usado após o descarte também são bugs do ListView, no entanto, é improvável que apareçam na minha pesquisa, já que o ListView não aparecerá em nenhum lugar na consulta de pesquisa.

@jassmith além de corrigir problemas existentes (além de ListView, há outras coisas que ainda nem sempre funcionam bem), há também recursos importantes que foram deixados de fora (ordem aleatória):
- Suporte pop-up verdadeiro (recursos básicos e comuns ainda ausentes)
- Cancele a navegação da página ao navegar de volta (há muito tempo pendente)
- Controles básicos ausentes (sem CheckBox, RadioButton e mais)
- Desenho de plataforma cruzada (controle de tela ou de alguma outra forma)
- Suporte para desenho de plataforma cruzada de pincéis sólidos \ gradientes (SolidColorBrush, GradientBrush)

Eu gostaria que mais trabalho fosse feito no sentido de tornar o framework realmente mais rico, e não adicionar coisas como estilo CSS ou Flexbox (que veio com seus próprios problemas).

@opcodewriter

Suporte pop-up verdadeiro (recursos básicos e comuns ainda ausentes)

Justo, parece que nunca é priorizado alto o suficiente para se tornar real. Isso realmente foi muito longe em um ponto.

Cancele a navegação da página ao navegar de volta (há muito tempo pendente)

Na verdade, isso é algo que o MaterialShell pretende abordar. Existem razões bastante sólidas para que isso não possa ser feito em NavigationPage.

Controles básicos ausentes (sem CheckBox, RadioButton e mais)

Alguns deles fazem parte da iniciativa F100 em andamento agora.

Desenho de plataforma cruzada (controle de tela ou de alguma outra forma)

Essa seria a API irmã para isso, conforme especificado em # 2452

Suporte para desenho de plataforma cruzada de pincéis sólidos \ gradientes (SolidColorBrush, GradientBrush)

Mesma resposta que acima.

@jassmith

Justo, parece que nunca é priorizado alto o suficiente para se tornar real. Isso realmente foi muito longe em um ponto.

OK, espero priorizá-lo até o final de 2018 :)

Na verdade, isso é algo que o MaterialShell pretende abordar. Existem razões bastante sólidas para que isso não possa ser feito em NavigationPage.

Você poderia fornecer mais detalhes por que isso não pode ser feito na implementação atual?

Alguns deles fazem parte da iniciativa F100 em andamento agora.

Entendo. Dedos cruzados..

Você poderia fornecer mais detalhes por que isso não pode ser feito na implementação atual?

Não vou entrar mais no assunto aqui porque estamos ficando totalmente fora do caminho, mas a essência é a seguinte:

  • Você não pode cancelar o gesto de deslizar para trás no iOS reativamente. Uma vez que este é o método principal que as pessoas usam para navegar de volta com os telefones maiores, isso se torna uma omissão gritante.
  • Embora seja tecnicamente possível substituir esse comportamento no iOS, é necessário aprofundar-se bastante nos detalhes internos do UINavigationController de uma forma que não podemos ter certeza de que será realmente compatível ou funcionará quando uma nova versão do iOS for lançada. Resumindo, a Apple realmente não parece gostar muito que as pessoas façam isso.

Existem algumas outras preocupações menores sobre como isso afeta o estilo. Essa é a longa história curta, no entanto. Se você ainda deseja discutir esse recurso específico, sugiro abrir um novo número :)

@jassmith
Achei que apenas manipular gestureRecognizerShouldBegin e chamar algo como OnBackButtonPressed deveria ser o suficiente.

No geral, eu realmente gosto muito do que estou lendo, no entanto, isso não parece algo que deva ser feito no núcleo do nuget / repo do Xamarin Forms.

Esta é uma abordagem opinativa que deve ser construída sobre o Xamarin Forms, não dentro dele. Eu vejo isso como uma biblioteca separada que permite aos desenvolvedores adotar uma abordagem diferente. As partes necessárias do Xamarin Forms que precisam ser expostas devem ser, e isso deve ser construído sobre essas partes.

Assim como quando os desenvolvedores decidem usar o Xamarin Classic / Native ou o Xamarin Forms, posso ver uma decisão semelhante de usar o Xamarin Forms ou o Xamarin Forms com um Shell.

Os Formulários Xamarin devem se concentrar na criação da melhor estrutura de interface do usuário entre plataformas, sem tentar conformar as plataformas para que se pareçam. Hoje, o Xamarin Forms faz um ótimo trabalho em garantir que a sensação de plataforma seja respeitada.

Pude ver um Shell de base no repositório Xamarin Forms e algum código sobre o manuseio de Shells, mas o Material Shell parece muito acoplado a uma linguagem de design e padrão de navegação específicos para que eu ache que deveria estar no repositório Xamarin Forms.

@MisterJimson
Obrigado pelo seu feedback. A localização exata da área de superfície API pública ainda não foi decidida. Existem prós e contras em ambas as abordagens.

A especificação será atualizada (esperançosamente em breve) para ter uma classe Shell e uma classe MaterialShell. A classe MaterialShell seria a parte que consideramos mover para fora do núcleo. Shell seria o que você descreveu.

Atualizado com quebra de Shell e atualização de especificações de navegação

Eu realmente gostaria que a implementação existente do XF fosse tornada ... mais forte e melhor para permitir que algo assim exista como um complemento, não como parte do BCL. Portanto, ter uma plataforma subjacente forte, correta e estável, beneficiará os aplicativos existentes e quaisquer novas camadas como esta.

Ansioso pela evolução disso.

@jassmith @brianlagunas

Apenas algumas observações.

  • BackButtonBehavior, certamente deve haver uma propriedade de visibilidade caso você não a queira de todo?
  • O esquema de navegação do materialshell é como o Prism. Ele funcionará com esses frameworks existentes? (Prisma, FreshMVVM, MVVMCross)
  • Você pode substituir completamente o layout na barra de navegação? da forma como está, o Forms é extremamente limitado a esse respeito e você acaba com barras de navegação de aparência desajeitada forçando você a seguir a rota do renderizador personalizado, com a certeza de que uma nova versão do Forms provavelmente quebrará seu código personalizado.
  • O MasterDetail não foi muito tocado, você será capaz de personalizar o menu flyout?
  • Que controle teremos sobre o hambúrguer?

Eu só quero garantir que os pontos problemáticos e limitações existentes sejam tratados, bem como novos recursos.

Parece bom.

Eu sou muito novo no XF, mas o framework tem uma certa reputação de ser um tanto frágil, embora certamente isso esteja melhorando rapidamente graças aos seus esforços.

Então, vale a pena, esta é a minha opinião :-)

É ótimo que Xamarin esteja recebendo muito amor no momento, mas eu concordo com @opcodewriter , tanto o ferramental quanto o framework poderiam pagar por algumas dívidas técnicas.

Também gosto da opinião de @MisterJimson de que esta deve ser uma camada diferente - mas vocês devem ser honestos com vocês mesmos sobre sua capacidade e quantos frameworks podem suportar. Estamos todos propensos a codificar coisas novas e brilhantes e a evitar decisões difíceis, mas contamos com você para desenvolver uma base sólida para nosso código.

Já tenho problemas suficientes para fazer meu código funcionar sem me preocupar com o de outra pessoa :-)

O XF está em um bom lugar no momento, tem potencial para se tornar um conjunto de ferramentas realmente sólido.

Obrigado por todo o seu trabalho árduo nisso, isso mostra.

@mackayn

BackButtonBehavior, certamente deve haver uma propriedade de visibilidade caso você não a queira de todo?

Defina o comando com CanExecute retornando false. Optei por não adicionar um método secundário no momento.

O esquema de navegação do materialshell é como o Prism. Ele funcionará com esses frameworks existentes? (Prisma, FreshMVVM, MVVMCross)

Eu certamente espero que sim! Não posso ter certeza, mas estava pensando neles e em todos os seus problemas. É por isso que toda navegação acontece por meio de um único evento, por exemplo.

Você pode substituir completamente o layout na barra de navegação? da forma como está, o Forms é extremamente limitado a esse respeito e você acaba com barras de navegação de aparência desajeitada forçando você a seguir a rota do renderizador personalizado, com a certeza de que uma nova versão do Forms provavelmente quebrará seu código personalizado.

Esta parte é mais difícil. Gostaria de permitir aqui o máximo de extensibilidade possível, mas estou realmente aberto a sugestões sobre como melhorar isso de uma maneira sã e razoável.

O MasterDetail não foi muito tocado, você será capaz de personalizar o menu flyout?

Você pode definir o cabeçalho para qualquer visualização arbitrária, controlar o modelo usado para cabeçalhos e itens de grupo e pode adicionar itens de menu. Você controla alguns aspectos do layout, mas não 100%. Mais uma vez, seria bom ter algumas ideias sobre o que mais você acha que precisa. Vejo claramente a necessidade de um rodapé com uma propriedade de comportamento do rodapé.

Que controle teremos sobre o hambúrguer?

BackButtonBehavior também substitui o hambúrguer. Talvez deva ser renomeado. Mais uma vez estou aberto a sugestões aqui. Originalmente eu o chamei de LeftBarButton, mas em situações RTL não está à esquerda ...

O retorno técnico da

As interações estreitas entre tabbar e navbar é uma dessas áreas, certificando-se de que a navegação entre as guias ou itens no MDP esteja livre de falhas é outra área. Existem muitas áreas onde ocorrerão pequenos soluços porque cada elemento não é capaz de ter uma visão holística do shell de seu aplicativo.

Quanto ao ferramental, há uma equipe totalmente separada dedicada a isso e eles estão fazendo grandes avanços. O ferramental interno melhorou muito nos últimos 6 meses e estou realmente ansioso para que você experimente isso!

@mackayn

O esquema de navegação do materialshell é como o Prism. Ele funcionará com esses frameworks existentes? (Prisma, FreshMVVM, MVVMCross)

Não se preocupe ,

@dansiegel

É bom saber que ambas as equipes estão em diálogo, isso é tudo que eu precisava saber 👍

@jassmith Agora é óbvio que a maneira como algumas coisas estão funcionando ou foram arquitetadas no XF não é a melhor. Então, em vez de colocar batom no porco (não quero ser rude aqui), por que não recriar um novo framework do zero ou refatorar maciçamente o existente? Eu sei, parece muito assustador, mas tenho certeza que a grande maioria dos desenvolvedores de Formulários Xamarin não se importaria, todos nós ficaríamos ansiosos para refatorar nossos aplicativos ou o que quer que seja, apenas para termos aplicativos que rodam muito melhor.
Já vi RP rejeitado com boa refatoração porque "não queremos esse tipo de mudança". Não tenho certeza de quem fez essa regra, mas ele deveria respirar fundo, relaxar e talvez reconsiderar a "regra".
O que é melhor: continuar tendo desenvolvedores frustrados usando um framework que não consegue mantê-lo ou desenvolvedores frustrados que precisam fazer algum trabalho de refatoração? Só meus 2 centavos ...

@opcodewriter você e eu concordamos, mas isso é offtopic para esta especificação.

Acabei de ler o novo material sobre navegação e gostei muito. Adoro ter uma mão de tipo para vincular comandos de navegação e orientar a navegação em torno de URLs (como e suponho que seja influenciada pelo Prism) é inteligente.

Ironicamente, o esquema de navegação URI era algo que queríamos fazer no passado e começamos a empurrar o Prism para implementar porque não podíamos colocá-lo de maneira razoável no framework. Para não tirar nenhum crédito, eles merecem 100% disso :)

A semântica exata da abreviação ainda está em jogo.

Acho que provavelmente vai acabar mais como:

<Button Command="{segue:Uri}" CommandParameter="app://Foo/Bar/Baz" />

ou

<Button Command="{segue:Push}" CommandParameter="{DataTemplate local:MyPage}" />

Portanto, as extensões podem ser mais precisas sobre quais parâmetros adotam. O namespace é usado principalmente para manter as coisas fáceis de descobrir com o intellisense.

@jassmith: Eu realmente gosto dessa coisa do segue. Posso perguntar como você pretende oferecer suporte ao modal push?

Não tenho todos os detalhes, mas poderia imaginar o url nav exatamente como o prisma, embrulhado em extensões de marcação.

<!-- push -->
<Button Command="{segue:Uri}" CommandParameter="path/to/page" />

<!-- push modal -->
<Button Command="{segue:Uri Modal='true'}" CommandParameter="path/to/page" />

<!-- reset stack -->
<Button Command="{segue:Uri}" CommandParameter="app://root/path/to/page" />

A primeira coisa a observar é que a navegação de URI só funcionará com Shell. É o único lugar em que podemos dar sentido à pilha de forma consistente sem ter casos extremos estranhos e podemos projetar as interações de navegação para apoiar o conceito.

Por enquanto, oferecemos suporte apenas a URIs completos. Parciais são muito mais difíceis de lidar porque são contextuais.

Seus 3 exemplos seriam, supondo que a localização atual seja: app: // Shell / Apps / Games / Details

Em particular, isso significa que você está em um Shell, cujo ShellItem atual tem o Apps Route, cujo ShellTabItem atual tem a rota Games, que tem um ContentPage colocado em sua pilha que tem os Detalhes da rota.

<!-- push -->
<Button Command="{segue:Uri}" CommandParameter="app://Shell/Apps/Games/Details/page" />

<!-- push modal -->
<Button Command="{segue:Uri}" CommandParameter="app://page" />

<!-- reset stack -->
<Button Command="{segue:Uri}" CommandParameter="app://Shell/Apps/Games" />

Em um uri de shell, o primeiro local é sempre um Shell. Se não for, será considerado um push modal. Em seguida está o ShellTab e, em seguida, o ShellTabItem. Depois disso, segue a pilha de navegação do ShellTabItem. Não tenho intenção de fazer backport de URI nav para todos os controles de página possíveis no momento. Isso fica MUITO cabeludo com pessoas que usam o MasterDetailPage's ...

Com o registro de rota e as propriedades de rota, não há necessidade de roteamento baseado em tipo. Vou removê-lo da especificação.

@jassmith pensando mais nessas coisas de navegação e tenho algumas perguntas

  1. como você pode lidar com CanExecute
  2. como você pode dar ao usuário controle sobre (prevenção de leitura) vários toques?
  3. como você lida com a navegação relativa? Ou seja, você tem 3 páginas de profundidade e precisa avançar, mas a pilha é totalmente dinâmica?
  4. O prisma tem essa noção fantástica de NavigationParameters meio da qual podemos passar não apenas valores básicos por meio da string de consulta /Navigation/MyPage/MyPageDetails?id=33 , mas também objetos complexos new NavigationParameters {{nameof(MyObject), MyObject}} . Você planeja apoiar algo semelhante?

@ChaseFlorell

1) Com segues? Você não pode atualmente. Definitivamente, precisa ser pensado mais. Existe uma maneira de fazer um comando segue, mas é ... uma merda. Isso deixaria você lidar com isso, mas nesse ponto REALMENTE não vale a pena.

2) Um Segue se desabilitará até que o push seja concluído. Outras tentativas de ativar o comando no-op até que a tarefa de navegação anterior seja concluída.

3) Você pode usar uma navegação tradicional como push / pop com segues. Estas são ações relativas.

4) [QueryParameterAttribute] pode ou não já existir, não posso confirmar nem negar. ;)

É improvável que adicionaremos suporte a objetos complexos. A ideia é usar conversores para pegar seus valores simples e transformá-los em objetos complexos.

A experiência do passado a construção de navegação aplicativo baseado em URI (de volta no CAB-Composite UI Application Block para p & p), eu sugiro fortemente que você não use o System.Uri tipo e ao invés de apenas fazer tudo parecer como um URI, mas não use a própria implementação de URI. @pprovost pode testemunhar as cicatrizes ao longo da vida que o trabalho deve ter deixado nele. Lembro-me de encontrar incontáveis ​​problemas quando enfrentamos restrições e erros de URI de internet (ou seja, em nomes de host) que não nos importamos menos com as coisas no aplicativo.

Parte do dano já foi feito , suponho.

Na verdade, o System.Uri é a melhor escolha ao oferecer suporte a um esquema de navegação baseado em URI. Embora CAB usasse a navegação URI, ele também fez o que você disse e fez com que "parecesse" um URI, permitindo que você use strings em vez do objeto System.Uri. Nomes de host nunca foram exigidos.

O que você está pedindo é uma API baseada em string bastante flexível, que pode aceitar qualquer sintaxe de string que você inserir, o que não é algo que produzirá resultados previsíveis. Deve haver regras em vigor para que um esquema de navegação baseado em URI / string funcione.

Um URI arbitrário também não funcionará no XF. A lista de caracteres inválidos em um URL, mas que são válidos em um sistema de arquivos, não é exatamente pequena. Esses são todos os casos em que uma string teria funcionado, e um URI não vai e vai precisar escapar ou fazer com que o usuário descubra por que as coisas não estão funcionando (ou falham?) E renomeie as coisas para serem "seguras para URI".

Você pode fazer sua própria abstração se quiser mais restritiva (ou melhor semântica / análise / validação?), Mas, IMHO, System.Uri traz muita bagagem da internet que não é de graça. Isso é semelhante a como Mono / MonoDevelop criou seu próprio FilePath para representar caminhos, que normalmente são apenas strings.

Pelo menos, parece que todos os URIs são considerados relativos, o que simplifica as coisas. No CAB, usamos uris absolutos com partes de esquema e nome de host também, o que era problemático.

Eu prefiro muito mais algo como ResoucePath , digamos, do que Uri . Mas no final do jogo, tenho certeza de que está fechado de qualquer maneira.

Não tenho certeza do que você acha que os caminhos do sistema de arquivos têm a ver com alguma coisa ...

Como você usaria um URI para confundir o sistema? Ele vai ignorar o esquema e o nome do host e começar a procurar por rotas (que são limitadas a [az] apenas). Se quaisquer caracteres estranhos que você inserir não puderem ser encontrados, simplesmente parará. E a string de consulta inserida precisa ser identificadores C # válidos ou simplesmente não será correspondida. Os dados com escape nos dados da string de consulta não terão escape.

O URI de

Faz sentido. Obrigado pela informação de fundo sobre o Prism @brianlagunas! Agora devo ler atentamente as especificações e fornecer alguns comentários realmente úteis;)

Muito boa iniciativa, mas espero que a extensibilidade e personalização sejam levadas em consideração, criando os métodos virtuais adequados ou outras formas de fazer o nosso trabalho "especial" para os nossos clientes.

Por exemplo, será possível / como:

  1. Extensibilidade das guias, por exemplo, mostrando um emblema com um ícone. Ou mostrando uma gaveta pop-up acima de uma, como um botão "mais" ou " * ".
  2. Snackbar personalizado (por exemplo, com o botão "Desfazer" para uma ação que você acabou de fazer com cores de fundo / primeiro plano personalizadas)
  3. Empurrando fragmentos no Android usando animações diferentes do padrão programado no Shell, como nenhuma animação para dar a navegação mais rápida possível.

Em uma nota técnica: o shell reciclará as páginas para que, uma vez que você navegue duas vezes para uma página, os elementos nativos sejam reutilizados com um VM diferente sob ele?

Oi @rogihee

Eu agradeço seus comentários sobre a implementação. Acho que é muito extensível: https://github.com/xamarin/Xamarin.Forms/blob/9558f2837280e02b41848d3a3c3213d49a664751/Xamarin.Forms.Platform.iOS/Renderers/ShellRenderer.cs

O Android ainda está em forte desenvolvimento agora, no entanto, usa uma abordagem idêntica.

@rogihee quanto à reciclagem de páginas, estou tentando descobrir um método lógico de tornar isso viável. De um modo geral, isso não ocorre atualmente, pois seria necessário ativá-lo explicitamente.

Parece bom essas opções "Criar *". É bom ver o rápido progresso nisso!

Eu me pergunto se há alguma implicação de desempenho com a reutilização de elementos. Pessoalmente, eu priorizaria a velocidade e a sensação "fluida" de um aplicativo em relação ao uso mais alto de Mem / CPU (embora haja uma correlação em algum lugar no final do curso). E priorize iOS / Android sobre qualquer outro :-).

A Shell está muito focada na percepção de fluidez. Ainda não está no lugar em todos os lugares, mas está se unindo.

Eu realmente preciso colocar alguns usuários iniciais no local que tentam fazer coisas malucas com o shell para ter certeza de que ele pode lidar com a carga para a qual foi projetado.

@jassmith mig acabou de mencionar o shell por 3 minutos no Build .....

Eu não sou o papai dele

+1

API atualizada para corresponder ao estado atual do mundo, ainda é necessário atualizar as amostras.

Adicionados alguns exemplos atualizados, ainda é necessário muito trabalho corrigindo outros exemplos e atualizando as descrições de rotas ao usar a sintaxe abreviada (conforme você obtém as rotas abreviadas!)

Puxa, me sinto tão atrasado para a festa. Excelente redação e discussão. Eu dei uma olhada em tudo (desculpe no aeroporto) e tenho uma sugestão própria. Desculpe se isso foi mencionado em outro lugar.

@jassmith @migueldeicaza Você pode, por favor, adicionar comportamento à barra de navegação para que possa ser rolado para fora quando o ListView estiver rolando e mostrado quando for rolado na direção oposta. Quase qualquer aplicativo profissional faz isso para mostrar mais imóveis. Isso seria especialmente útil em dispositivos pequenos.

Outra é por que você não renomeia as tags XAML para que sejam mais simples de entender? Talvez use Tab em vez de ShellSection? Existem muitas tags ShellX agora.

Para iOS, acredito que haja uma propriedade para ligar / desligar para habilitar o modo de rolagem na barra de navegação. Para Android, você precisa começar a usar os novos layouts (CoordinatorLayout, AppBarLayout, etc.). A implementação do XF no Android está bastante desatualizada a esse respeito, pois ainda está usando um RelativeLayout como o contêiner principal. Acho que há um tíquete de aprimoramento em algum lugar sobre esse problema específico. Eu adoraria ver o Shell oferecer suporte a diferentes modos de rolagem.

Além disso, muitas vezes temos que implementar um comportamento personalizado para mostrar erros / outros tipos de pop-ups na página. O shell deve oferecer suporte a essa funcionalidade fora da caixa, portanto, não precisamos recorrer a plug-ins de terceiros ou criar uma hierarquia de IU complexa.

@ adrianknight89

Você pode, por favor, adicionar comportamento à barra de navegação para que possa ser rolado para fora quando o ListView estiver rolando e mostrado quando for rolado na direção oposta. Quase qualquer aplicativo profissional faz isso para mostrar mais imóveis. Isso seria especialmente útil em dispositivos pequenos.

Isso é algo que estou realmente tentando descobrir a maneira certa de fazer. Infelizmente, nem todas as plataformas oferecem suporte a esse recurso, então provavelmente será um negócio específico para cada plataforma. O Android, no mínimo, foi construído para suportar isso, eu o ligo ocasionalmente para ter certeza de que ainda funciona.

Outra é por que você não renomeia as tags XAML para que sejam mais simples de entender? Talvez use Tab em vez de ShellSection? Existem muitas tags ShellX agora.

A nomenclatura aqui é MUITO difícil. ShellTab é um pouco confuso para cima e para baixo. Em vez disso, optei por nomes hierárquicos mais genéricos, no entanto, devo admitir que não estou feliz com nomes. Sugestões são 100% bem-vindas ... não estou totalmente ansioso para refatorar seus nomes NOVAMENTE, mas o que você pode fazer ...

Para iOS, acredito que haja uma propriedade para ligar / desligar para habilitar o modo de rolagem na barra de navegação. Para Android, você precisa começar a usar os novos layouts (CoordinatorLayout, AppBarLayout, etc.). A implementação do XF no Android está bastante desatualizada a esse respeito, pois ainda está usando um RelativeLayout como o contêiner principal. Acho que há um tíquete de aprimoramento em algum lugar sobre esse problema específico. Eu adoraria ver o Shell oferecer suporte a diferentes modos de rolagem.

O Shell usa CoordinatorLayout + AppBarLayout e basicamente "desativa" o suporte à rolagem por enquanto, mas funciona. A rolagem do iOS também é fácil de implementar. Infelizmente, o NavigationView da UWP não tem suporte para esse recurso.

Além disso, muitas vezes temos que implementar um comportamento personalizado para mostrar erros / outros tipos de pop-ups na página. O shell deve oferecer suporte a essa funcionalidade fora da caixa, portanto, não precisamos recorrer a plug-ins de terceiros ou criar uma hierarquia de IU complexa.

Exemplos, preciso de exemplos :)

@jassmith

Estou usando o plug-in de conectividade de James Montemagno para ouvir as alterações no estado da conexão de dados. Quando a conexão com a Internet cair, é uma boa prática exibir uma notificação que desliza / desaparece gradualmente ou permanece parada até que a Internet fique online novamente.

No Instagram, esta notificação é colocada logo abaixo da barra de navegação. No Tumblr, está logo acima da barra de navegação inferior. No YouTube, estranhamente, está abaixo da barra de navegação inferior. Talvez algo assim possa fazer parte da Shell?

O controle Popup proposto está, até onde eu sei, sobrepondo a janela existente, embora possa ser facilmente descartável. A notificação que acabei de mencionar e, potencialmente, outros tipos de notificações não precisam sobrepor sua janela pai (ou seja, a árvore visual pai ainda responde a gestos), então não tenho certeza se Popup é o ajuste certo.

Shell pode ter uma propriedade para definirmos como essa visualização (chame-a de Notificação [Visualização]) será exibida, bem como seu posicionamento e comportamento de animação de entrada / saída. Então, essencialmente, uma implementação de plataforma cruzada / snackbar integrada ao Shell, INavigation ou qualquer outra coisa. Isso não seria forçado a parecer nativo por plataforma, mas o mesmo em todas.

d1c014c0-fc7b-4788-9689-1948a7294426

bc91d3ca-b95f-4485-a917-db6ab47510c1

Com relação aos argumentos sendo feitos em torno de estabilidade, flexibilidade, etc., sem se livrar da arquitetura desatualizada vinda do 1.0, não acho que seja viável conseguir essas coisas. Sou muito a favor do ListView2.

@jassmith

  • Você já tem um tíquete de aprimoramento para o novo ListView?
  • Quando você acha que a v1.0 será lançada? Alguma chance de podermos ver por EOY?

Além disso, tenho a mesma preocupação sobre a equipe ser subdimensionada. Na verdade, já mencionei isso antes. Espero que a equipe possa crescer muito mais no futuro. 🙏 @davidortinau @migueldeicaza

@jassmith há algum tempo, acredito que se tivéssemos um Renderer para a classe App, poderíamos fazer muitas coisas que atualmente requerem hackeamento de terceiros. Por exemplo, o plug-in RgPopups pega a visualização principal do aplicativo e injeta visualizações renderizadas nela para fornecer uma aparência pop-up de tela inteira. Atualmente, isso é impossível de conseguir com os Formulários Xamarin "puros". No entanto, se o App tivesse um Renderer, poderíamos fazer isso sozinhos.

Sou totalmente a favor de adicionar esses tipos de notificações do sistema ao Shell, apenas tentando descobrir como isso deve ser feito.

Você pode, por favor, colocar as páginas arbitrariamente onde quiser dentro de um aplicativo? Isso é especialmente importante em tablets / desktops / laptops (dispositivos de tela maior), onde você deseja várias páginas na tela ao mesmo tempo e não necessariamente deseja organizá-las usando uma visualização dividida (página de detalhes mestre). Exemplo, consulte Google Maps:

image

Observe como o conteúdo está "flutuando" no topo do mapa (sem visualização dividida). Se você quiser usar coisas como abas ou navegação dentro da área flutuante, então você não pode fazer esse tipo de coisa com o Xamarin Forms, pronto para uso, por causa da hierarquia extremamente limitada de páginas (não é possível aninhar uma página dentro de uma visualização). Na verdade, desenvolvemos nossa própria visualização personalizada que fornece recursos semelhantes a NavigationPage, mas é uma visualização, apenas para que pudéssemos realizar esse tipo de layout, mas foi muito trabalhoso / difícil de fazer.

Deve ser possível colocar conteúdo (incluindo páginas) em qualquer lugar que você quiser dentro de um aplicativo.

Você pode, por favor, colocar as páginas arbitrariamente onde quiser dentro de um aplicativo?

Estou um pouco curioso, @jsiemens, já que essa visualização provavelmente não ficaria bem em um telefone, mas ficaria ótima no desktop e no tablet. Você pode expandir como você espera que isso funcione. No final das contas, ficaria tentado a dizer que você está trazendo o conceito de região para o Forms do Wpf. Minha reação automática é que, embora eu ame o conceito, corremos o risco de fazer uma API de navegação já complexa exigir um PhD ou pelo menos um nível de QI de gênio, o que não seria a melhor coisa para a adoção do usuário.

@dansiegel Pelo menos pessoalmente, eu provavelmente usaria VSM ou algum equivalente para mover e compactar a visualização de rolagem na parte inferior quando abaixo de um certo limite de janela de visualização (como o GMaps faz atualmente). No entanto, ficaria curioso para ver como a navegação e o gerenciamento de estado funcionariam para isso.

Navegação: tenho certeza de que esse não é um problema intransponível se você começou a partir da perspectiva da jornada do usuário e, em seguida, olhou como o usuário esperava que funcionasse. A navegação precisaria ser responsiva à natureza de tela inteira de um telefone em vez de uma exibição menor em uma tela maior, por exemplo.

O usuário 'veria' o tablet e a visualização menor como um único marco de navegação. Em uma tela pequena, pode haver dois marcos. A navegação teria, de alguma forma, que ser responsiva.

Como desenvolvedores, certamente temos que lidar com essa natureza responsiva, pois é uma coisa contextual. Não podemos contar com a estrutura para lidar com isso para nós, mas a estrutura precisa oferecer suporte.

@jsiemens @dansiegel A maneira como ControlTemplate s. Eu construo meu conteúdo do tipo "página" como ContentView s e os hospedo em um ContentPage (dentro de um NavigationPage ) que é apropriado para a plataforma. Usar ControlTemplates significa que posso ter vários limites ContentViews (geralmente em um Grid para que eu possa sobrepor coisas) que são ligados / desligados com base nas propriedades vinculáveis ​​no ControlTemplate (você também pode usar DynamicResource s). O resultado final funciona um pouco como os painéis CSS de um site, onde todo o conteúdo está na página, mas nem todo fica visível o tempo todo. ControlTemplate s são mágicos para isso e eu gostaria que seus recursos fossem preservados no Shell.

@dansiegel Eu simplesmente o codificaria para carregar um shell diferente, dependendo se o aplicativo estava sendo executado em um telefone ou em um tablet / laptop / desktop.

@jsiemens tudo bem, meu comentário destina-se apenas a estimular mais conversas e pensamento crítico para refinar ainda mais sua ideia. De certa forma, eu quase diria, dado o seu conceito aqui, que cada página poderia ser essencialmente uma MultiPage, onde uma página poderia ser anexada a um determinado controle e tratada mais como apenas outra Visualização em vez de navegação normal.

@dansiegel Sim, acho que o que estou procurando é poder simplesmente adicionar uma página a qualquer lugar dentro do aplicativo. É estranho que o Xamarin Forms imponha essa limitação quando as plataformas subjacentes não (por exemplo, iOS é apenas uma hierarquia de árvore de visualizações - você pode adicionar a visualização do NavigationController literalmente em qualquer lugar dentro do aplicativo). Além disso, meu comentário pretendia indicar que não é necessário que a especificação do Shell cubra isso - não acho que o layout "responsivo" precise ser uma preocupação. Acho que, desde que seja possível construir o layout, podemos cuidar do carregamento condicional de shells dependendo do fator de forma, e isso é bom o suficiente.

Suponho que não esteja totalmente no tópico para esta especificação, mas eu mencionei isso aqui porque estamos falando sobre como construir layouts complexos (por exemplo, a 3ª prioridade de @MelbourneDeveloper - flexibilidade), e este é certamente um layout que está no topo mente para mim e minha equipe (estamos construindo um aplicativo de mapeamento onde queremos ser capazes de flutuar painéis de conteúdo no topo do mapa, que podem conter conteúdo 'somente página', como páginas de navegação e guias).

Não sei como isso seria resolvido usando o shell, mas minha reação inicial ao shell é que ele não parece fazer nada que eu já não possa fazer. Eu geralmente sinto que a equipe do Xamarin Forms continua construindo recursos que me permitem fazer coisas que eu já poderia fazer, mas apenas de uma maneira diferente (por exemplo, CSS, Visual State Manager e agora as especificações de desenho e shell). Então isso não traz muito valor para mim. Prefiro ter novos recursos que me permitam fazer coisas que antes não podia (fora de controles personalizados e / ou renderizadores). Se shell é a resposta para isso porque a sintaxe é mais elegante, então eu sou totalmente a favor, mas no final das contas eu gostaria que fosse mais poderoso e mais expressivo do que a hierarquia de Página / Visualização atual, pois realmente agrega valor.

Você poderia desacoplar a criação de visualização nativa por visualização xamarin se todas as subvisualizações em um layout pudessem ser renderizadas sem o uso de widgets nativos? Uma espécie de abordagem híbrida automática de flutter / xamarin, em que grupos de visualizações XF são renderizados em uma única superfície e apenas combinados em uma visualização nativa. Seria útil evitar a criação de visualização / layout do Android c # -> custo de interoperabilidade java.

em progresso!!

@jassmith após o

o shell oferecerá suporte a macos e wpf?

@juepiezhongren os alvos iniciais são iOS e Android. Outras plataformas serão priorizadas depois disso.

O desenho não está sendo desenvolvido. Em sua especificação atual, seria válido com a Shell. Assim como hoje, você pode usar os controles baseados no SkiaSharp e Skia no Xamarin.Forms.

Estamos trabalhando em outras estratégias nativas para oferecer suporte a um design consistente para materiais e outros estilos de design.

@davidortinau O shell torna o suporte RTL melhor?

Melhor de que maneira? O que está faltando no suporte RTL hoje? Devemos abordar isso em todos os lugares.

Para ser honesto, não faço o desenvolvimento do XF há algum tempo, mas a maioria das limitações são conhecidas: dê uma olhada em # 1222 e # 2448

Talvez o shell possa ajudar com estas limitações gerais:

  • A localização do botão NavigationPage, a localização do item da barra de ferramentas e a animação de transição são atualmente controladas pela localidade do dispositivo, não pela configuração FlowDirection.
  • Configuração global do aplicativo para FlowDirection

E algumas outras limitações específicas da plataforma

A característica mais importante do Xamarin.Forms. Ele deveria ter sido construído assim em primeiro lugar.

sem desenhar, xf ainda carece de bastante

@juepiezhongren

Basta usar o Skiasharp

@mackayn eu usei muito
https://github.com/xamarin/Xamarin.Forms/issues/1789
aparência universal é obrigatória

adam ficou agitado, é realmente um triste sinal para xf, onde xamarin originalmente poderia facilmente alcançar uma reputação muito melhor

xamarin.native é muito mais sólido para xf do que qualquer outra solução de plataforma cruzada, qualquer que seja sua reação nativa ou flutter. Como amante do dotnet, a situação atual de xf é sempre um pouco decepcionante para mim.

@juepiezhongren

Esta discussão é inútil, se não atender às suas necessidades, use o Flutter, nos permite entregar aplicativos em várias plataformas (iOS e Android apenas com o Flutter, etc.), essas alterações farão uma aparência consistente mais alcançável.

Reclamações simples e pequenas, até certo ponto. Ainda hooray para shell!

Eu concordo que seria melhor ter o Skia muito mais embutido na API do Forms (como a Telerik fez). Eu concordo.

Fico feliz que eles estejam investindo esforços no Shell & CollectionView.

oi, por favor, todos digam, como posso usar deve flayout na direita, para a linguagem da direita para a esquerda.

Oi,

Adoro a ideia, mas tenho apenas algumas pequenas informações.
Acho que estou um pouco atrasado, mas a nomenclatura é um pouco confusa, eu acho.

  1. Item, Seção e Conteúdo são nomes realmente gerais. Não está claro em que relação essas coisas estão. É Conteúdo => Seção => Item ou Seção => Conteúdo => Item ou Item => Seção => Conteúdo.
    Portanto, podemos especificar um pouco mais quais são as diferentes "coisas", encontrando um nome mais específico.

  2. Isso me leva à próxima entrada. Temos um Shell como recipiente para todos os itens internos. Portanto, não podemos simplesmente usar nomes diretos como "Item" em vez de "ShellItem" dentro. Parece-me um pouco desnecessário chamar todas as "coisas" Shelltem, ShellSection etc. mas ok. isso é discutível.

Ai

Ainda será lançado em 2018?

Temos uma versão prévia disponível AGORA! Dê uma olhada em https://blog.xamarin.com/connect-2018-xamarin-announcements/ para alguns exemplos excelentes.

Precisamos mesmo do Android 9? Isso parece ser um pouco uma limitação.

Tudo parece muito bom, mas parece ser baseado puramente em torno da interação da interface do usuário.
Acho que vou descobrir quando tentar, mas minha preocupação inicial é como direcionar a navegação a partir da lógica de negócios ou código, por exemplo, mensagens recebidas de um dispositivo conectado por Bluetooth que aciona uma mudança de página, enquanto mantenho uma separação decente de preocupações?

@hassanrahimi

oi, por favor, todos digam, como posso usar deve flayout na direita, para a linguagem da direita para a esquerda.

Embora RTL seja compatível, o menu suspenso ainda aparece à esquerda. Esta é uma limitação atual.

É possível personalizar a interface do usuário da barra de guias inferior?

É possível adicionar controles ao shell que não sejam recarregados ao navegar dentro do shell? Por exemplo, um FAB ..

A interface do usuário da barra de @stfnilsson é personalizável por meio de estilos e, em seguida, de um renderizador personalizado. Forneceremos exemplos no futuro.

Adicionando controles que são globais como você descreve como um FAB são planejados para o MaterialShell. Você pode fornecer cenários adicionais que se beneficiariam disso além do FAB?

Primeiro: eu usei meu próprio shell antes, agora posso facilmente substituir o meu pelo seu e é muito melhor. Eu realmente gosto.

Provavelmente meus casos são personalizados e não relacionados ao shell, mas:

Caso um:
Se eu quiser criar um aplicativo com um menu muito personalizado, um botão de menu em cada canto do aplicativo, como faço para adicionar os botões para que faça parte do shell (como sobreposição ou outdoor). Não quero que ele seja renderizado novamente a cada vez que navegar.

Caso dois:
Quero usar o shell, mas quero personalizar a barra de guias inferior para que o botão do meio seja mais alto (chamado de botão levantado no centro). Devo usar o renderizador e personalizar a visualização de navegação inferior?

Você acha que eu deveria usar o shell para casos especiais como este?

É claro que considero fazer isso em cada plataforma, mas os menus devem ser iguais em todas as plataformas, portanto, compartilhe o código.

Aqui está meu feedback. Eu faço este teste ( Xamarin.Forms 4.0.0.8055-pre1 ):

   <Shell.FlyoutHeader>
        <local:FlyoutHeader />
    </Shell.FlyoutHeader>

    <ShellItem Title="Home" Icon="home.png">
        <ShellSection>
            <ShellContent>
                <local:MainPage />
            </ShellContent>
        </ShellSection>
    </ShellItem>

    <ShellItem Title="Notifications" Icon="notification.png">
        <ShellSection>
            <ShellContent Title="Recent">
                <local:NotificationPage />
            </ShellContent>
        </ShellSection>
    </ShellItem>

    <ShellItem Title="Test" Icon="icon.png">
        <ShellSection Title="Home" Icon="home.png">
            <ShellContent>
                <local:MainPage />
            </ShellContent>
        </ShellSection>

        <ShellSection Title="Notifications" Icon="notification.png">
            <ShellContent Title="Recent">
                <local:NotificationPage />
            </ShellContent>

            <ShellContent Title="Settings">
                <local:SettingsPage />
            </ShellContent>
        </ShellSection>
    </ShellItem>

Tudo funciona quando tocamos no menu de hambúrguer. No entanto, se formos ao menu Test e tocarmos Home e Notifications para frente e para trás e escolhermos entre Recent ou Settings , a página será aberto respectivamente. Mas então, quando tocamos no menu de hambúrguer novamente, o aplicativo falha.

image

Como podemos usar GroupHeaderTemplate para mostrar um título para um grupo de ShellContent em um ShellItem?

Está claro para muitos usuários que o Xamarin Forms não pode ser mantido em seu tamanho e complexidade atuais, portanto, qualquer coisa nova deve diminuir a complexidade em vez de aumentá-la.

@jassmith A intenção é que você NUNCA seja melhor não

Se o Shell for concluído, o que no futuro pode ser depreciado e, quando isso for feito, a complexidade geral dos Formulários Xamarin será reduzida? Todas as outras páginas, exceto ContentPage, serão depreciadas?

A estratégia deve ser obter o máximo possível do repo. A estabilidade e a capacidade de manutenção do repositório central são as coisas mais importantes.

Além disso, se houver um motivo pelo qual o Shell não se chama ShellPage? Outras classes de Página têm nomes que terminam em "Página".

O anúncio atual da Shell (em https://blog.xamarin.com/xamarin-forms-4-0-preview/) não é promissor.

  1. Uma maneira simplificada de expressar o alto nível de sua arquitetura de aplicativo

Isso leva Xamarin além de seu propósito real. O Xamarin não é necessário para a arquitetura do aplicativo. Isso deve ser apenas sobre layout.

  1. Uma hierarquia de padrões de navegação de IU comuns que se adequam às suas plataformas móveis de destino

Espero que "móvel" seja um erro de impressão aqui, porque o Xamarin.Forms também cobre desktops.

  1. Um serviço de navegação robusto

O Xamarin.Forms não precisa de navegação. Se a navegação atual não estiver funcionando, ela pode ser depreciada porque existem muitas boas abordagens para a navegação que não requerem nada incorporado.

Olá @charlesroddie , obrigado pelo feedback.

Parece que a Shell pode não ser a certa para você no momento, e tudo bem. Você não precisa usar o Shell se ele não agregar valor aos seus aplicativos. Dito isso, a especificação do Shell é amplamente informada pelo feedback do desenvolvedor, e servir a nossa comunidade de desenvolvedores é fundamental para o nosso propósito.

Hoje em Xamarin.Forms você já descreve a arquitetura de sua aplicação, a hierarquia de conteúdo, usando TabbedPage, MasterDetailPage, com abas e itens de menu, e diferentes combinações. Isso é o que quero dizer aqui por "arquitetura". O Shell simplifica e substitui esses padrões (se você optar por usar o Shell).

"Móvel" não é um erro de impressão e é usado deliberadamente. Shell é voltado para iOS e Android. Se você tem como alvo desktop, não usará o Shell. Eu ouvi o interesse de colaboradores sobre a adição de suporte da Shell aos back-ends de desktop, e esses PRs seriam bem recebidos. Acredito que a Shell está muito bem posicionada para levar aplicativos para qualquer plataforma e ser flexível (resiliente) para se adaptar até mesmo a mudanças radicais de padrão de IU (quem sabe quais interfaces futuras adotarão). Para hoje, o campo de provas é iOS e Android.

Enquanto conversamos com os desenvolvedores sobre o Shell, fiquei surpreso ao saber que a navegação do Shell estava no topo da lista de recursos que eles valorizavam. O roteamento, os links profundos, a capacidade de interromper a navegação, a descrição instantânea do back stack, a transmissão de dados e o carregamento lento de páginas são atributos muito atraentes para os desenvolvedores que resolvem os problemas que enfrentam hoje.

Se você tem como alvo desktop, não usará Shell ... Acredito que a Shell está muito bem posicionada para levar aplicativos para qualquer plataforma

Só não quero que Xamarin entre em colapso sob seu próprio peso. Até que o Shell alcance todas as plataformas, você tem um problema de manutenção, já que é um acréscimo e não uma substituição de outras páginas. Você também tem um problema de mensagens para desenvolvedores de desktop, em um momento em que muitos estão obviamente procurando adotar uma estrutura de plataforma cruzada.

Xamarin está mostrando muitos recursos creep, por exemplo, css. Isso pode ameaçar todo o projeto e espero que alguns tomadores de decisão na organização entendam isso.

Só não quero que Xamarin entre em colapso sob seu próprio peso. Até que o Shell alcance todas as plataformas, você tem um problema de manutenção, já que é um acréscimo e não uma substituição de outras páginas. Você também tem um problema de mensagens para desenvolvedores de desktop, em um momento em que muitos estão obviamente procurando adotar uma estrutura de plataforma cruzada.

Xamarin está mostrando muitos recursos creep, por exemplo, css. Isso pode ameaçar todo o projeto e espero que alguns tomadores de decisão na organização entendam isso.

Eu concordo. Se um recurso não for compatível com desktop (UWP), não terá utilidade para nós. Eu também concordo com o CSS - parece um monte de complexidade adicional e sobrecarga de manutenção para um recurso que não me permite fazer nada que eu não poderia fazer antes. O que precisamos muito mais do que qualquer outra coisa é apenas mais controles - para todas as plataformas e mais recursos para os controles existentes. O Shell ainda tem as mesmas limitações que a infraestrutura da página tem, pois você precisa adotá-la completamente ou não pode usá-la de jeito nenhum, e ela só pode viver no nível raiz do seu aplicativo. Não só isso, mas agora você tem duas maneiras de fazer a mesma coisa, e é complicado e confuso. Portanto, se eu quiser apenas ter um menu flutuante sem usar o shell, não posso fazer isso. E é extremamente limitado na quantidade de controles para os quais os itens do shell mapeiam - guias, páginas de navegação e menus desdobráveis ​​não são suficientes para nós. Se o Xamarin Forms pudesse oferecer a amplitude de controles que um framework como o UWP tem, exposto como um conjunto de controles, assim como no UWP, e sem o inchaço inútil (por exemplo, css), eu ficaria feliz.

Acho que vocês levantaram alguns pontos válidos, mas como alguém que mantém um aplicativo UWP / iOS / Android e ficou um pouco desapontado quando soube que o Shell não suportava UWP, com apenas um "talvez" no futuro. Então eu percebi que estou perdendo o ponto da Shell. É uma ótima maneira fácil de alguém criar um aplicativo para as duas plataformas móveis principais. Como um desenvolvedor corporativo ... eu preciso de UWP, esperei até que houvesse suporte UWP para até mesmo considerar o XF ... mas eu suspeito que muitos desenvolvedores não precisam disso ... Eu também preciso de uma navegação muito mais complexa, etc. Shell fornece.

Mas também me lembro de passar muito tempo tentando começar com a navegação e as páginas ... o que pode levar algum tempo para descobrir. Mas também estou fazendo um aplicativo de linha de negócios muito complexo, há vários aplicativos simples que simplesmente não precisam desse nível de complexidade. O XF precisa evoluir para ser completo em relação a coisas como Flutter, etc. Ele também precisa continuar recebendo novos desenvolvedores para adotá-lo. E parece-me que o uso da plataforma ajudará a proteger os recursos necessários para mantê-la.

Também tenho alguns projetos futuros em que não preciso de UWP e estou ansioso para usar o Shell neles porque acho que será muito mais rápido para mim produzi-los.

Eu só uso o XF desde a versão 2.3 e embora certamente haja mais trabalho a ser feito ... a plataforma como ela existe agora se estabilizou muito ... pelo menos para mim ... então não estou preocupado com a manutenção adicional e, historicamente, parece-me que a equipe do XF está muito consciente da carga de manutenção ... então, acredito que eles a tenham sob controle.

Obrigado pela excelente adição à plataforma!

Adicionar novas formas de fazer as coisas confundirá os novos desenvolvedores até que as formas antigas sejam depreciadas e os documentos antigos removidos.

Flutter é muito mais simples. Sem linguagem de marcação, tudo em código. Xamarin não vai competir se tornando mais complexo e cheio de bugs. Ele vai competir fazendo mais do que Flutter (mais plataformas), com o mesmo foco.

Estamos chegando ao ponto de que precisamos de um Xamarin.Core, não incluindo XAML ou CSS ou associações de propriedade, não incluindo Pages ou Shells além das classes básicas, com foco no desempenho e estabilidade para este Core. Se alguns desenvolvedores quiserem esses recursos ao custo de aceitar a taxa atual de bugs, eles podem usar o Xamarin.Extensions, onde todas essas coisas estariam.

Adicionar novas formas de fazer as coisas confundirá os novos desenvolvedores até que as formas antigas sejam depreciadas e os documentos antigos removidos.

Flutter é muito mais simples. Sem linguagem de marcação, tudo em código. Xamarin não vai competir se tornando mais complexo e cheio de bugs. Ele vai competir fazendo mais do que Flutter (mais plataformas), com o mesmo foco.

Estamos chegando ao ponto de que precisamos de um Xamarin.Core, não incluindo XAML ou CSS ou associações de propriedade, não incluindo Pages ou Shells além das classes básicas, com foco no desempenho e estabilidade para este Core. Se alguns desenvolvedores quiserem esses recursos ao custo de aceitar a taxa atual de bugs, eles podem usar o Xamarin.Extensions, onde todas essas coisas estariam.

@charlesroddie Nada do que eles fizeram acima, você é forçado a usar XAML. O XAML em Xamarin.Forms é opcional - sempre foi. Eu sempre faço minha interface de usuário do aplicativo Xamarin.Forms usando apenas código - cada "tag" que você vê acima é uma classe que pode ser instalada e adicionada ao pai relevante.
Se a interface do usuário codificada não fosse possível com o Xamarin.Forms, eu não a usaria - ponto final!

Re Flutter em geral - é muito bom, mas o problema é apenas iOS e Android - isso também não funciona para mim, pois preciso direcionar o macOS, Windows 7 / 8.1 e Linux. Nada supera o Xamarin.Forms nisso!

posso definir a visualização personalizada como uma página mestra, é uma coisa muito importante incluir, não vamos preferir apenas MenuItem ou páginas

Xamarin Mac e suporte uwp?

Como você se conectaria ao processo de navegação? Eu acho que você está ciente disso, mas se você pegar o Prism por exemplo, os modelos de visualização são criados por um contêiner DI e são automaticamente configurados como BindingContext para a página solicitada.

Você também pode implementar INavigatedAware para um modelo de visualização e lidar com casos de uso específicos, como carregamento de dados, habilitação / desabilitação de serviços, etc.

Eu queria adicionar algo semelhante, então meu primeiro palpite foi o evento Shell OnNavigating e OnNavigated Shell, mas Current e Target não expõem um ShellItem, então não é possível definir o BindingContext por convenção ou acionar eventos de modelo de visualização?

Alguma sugestão para isso?

EDIT: rastreado por # 5166.

Para os ícones neste shell, é possível usar "Icon Font" em vez de uma imagem? É difícil mudar a cor durante o tempo de execução da imagem e também é difícil gerenciá-la para diferentes resoluções em diferentes plataformas. Posso sugerir fazer uma classe de ícone usando a fonte Material Design renderizada com a biblioteca SkiaSharp? A aula é relativamente fácil e fará muitos ícones prontos para uso no shell.

@vincentwx eu concordo. As fontes de ícone são muito mais fáceis de usar e também familiares.

@vincentwx @stevehurcombe absolutamente. Estou fazendo isso em um aplicativo agora:

<ShellItem>
    <ShellContent Title="Upcoming" 
                      ContentTemplate="{DataTemplate pages:UpcomingPage}">
            <ShellContent.Icon>
                <FontImageSource Glyph="{x:Static local:IconFont.Rocket}" 
                                 FontFamily='{OnPlatform iOS="Font Awesome 5 Free", Android="fa-solid-900.ttf#Font Awesome 5 Free"}'
                                 Size="18"/>
            </ShellContent.Icon>
        </ShellContent>

        <ShellContent Title="Latest" 
                      ContentTemplate="{DataTemplate pages:LatestPage}">
            <ShellContent.Icon>
                <FontImageSource Glyph="{x:Static local:IconFont.Book}" 
                                 FontFamily='{OnPlatform iOS="Font Awesome 5 Free", Android="fa-solid-900.ttf#Font Awesome 5 Free"}'
                                 Size="18"/>
            </ShellContent.Icon>
        </ShellContent>

        <ShellContent Title="Company" 
                      ContentTemplate="{DataTemplate pages:CompanyPage}">
            <ShellContent.Icon>
                <FontImageSource Glyph="{x:Static local:IconFont.Building}" 
                                 FontFamily='{OnPlatform iOS="Font Awesome 5 Free", Android="fa-solid-900.ttf#Font Awesome 5 Free"}'
                                 Size="18"/>
            </ShellContent.Icon>
        </ShellContent>
    </ShellItem>

Usei isso para fazer uma classe estática de todos os glifos: https://andreinitescu.github.io/IconFont2Code/

Há um bug com a cor do iOS que precisa ser corrigido. # 5071

Xamarin Mac e suporte uwp?

Não neste momento @mdonogma. Estamos reunindo interesse / demanda para oferecer suporte a plataformas adicionais, mas no momento não está em nosso roteiro.

@davidortinau Obrigado pelo código e link.

No Android 8.0, não consigo rolar a página da web no elemento WebView que está hospedado no Conteúdo Shell. Mas funciona bem sem o Xamarin Shell.

Formulário Xamarin 4.0.0.135214-pre4

Existe uma maneira fácil de alterar a FontFamily das guias inferiores e a visualização do título?

@varyamereon Eu fiz isso ontem. Estenda o Shell para poder definir FontFamily.
Vou publicar meu Shell estendido no GitHub em breve, mas:

Crie um Shell personalizado:

<Shell
    x:Class="X.Mobile.App.Features.AppShell.AppShell"

Em seguida, crie um renderizador personalizado Shell:

[assembly: ExportRenderer(typeof(AppShell), typeof(AppShellRenderer))]

namespace X.Mobile.App.iOS.Renderers
{
    [Preserve(AllMembers = true)]
    public class AppShellRenderer : ShellRenderer
    {
        protected override IShellItemRenderer CreateShellItemRenderer(ShellItem item)
        {
            return new CustomMenuRenderer(this)
            {
                ShellItem = item
            };
        }

Então:

 namespace X.Mobile.App.iOS.Renderers
 {
     [Preserve(AllMembers = true)]
     public class CustomMenuRenderer : ShellItemRenderer
     {
         private SKCanvasView _skiaSharpPaintView;
         public CustomMenuRenderer(IShellContext context) : base(context)
         {
         }

public override void ViewDidLoad()
{
}           
public override void ViewWillLayoutSubviews()
{
{

Em seguida, para definir a família da fonte: _ (não faça isso com frequência) _

var txtAttributes = new UITextAttributes
            {
                Font = UIFont.FromName("MyriadPro-Semibold", 12.0F)
            };
            foreach (var uiTabBarItem in TabBar.Items)
            {
                uiTabBarItem.SetTitleTextAttributes(txtAttributes, UIControlState.Normal);
            }

Alguém que estendeu o Shell com suporte para pop-up de baixo (folha de fundo)?

Mudei muito código do meu antigo Shell para o novo (composição, é claro), eu realmente gosto. Eu até o uso para um aplicativo que será lançado para produzir em maio :-) (eu depuro até o código Xamarin)

Há suporte para vincular uma lista ao Shell.MenuItems? Ou devo usar BindableLayout? Às vezes, eu preciso carregar uma lista do banco de dados e usá-la como menus. Eles têm a mesma visualização, mas carregam dados diferentes dependendo do menu selecionado.

Existe alguma maneira de alterar o OffscreenPageLimit no Android ao usar o shell? Isso é muito importante para meu aplicativo e está me impedindo de seguir em frente com a Shell.

Obrigado!

Algumas solicitações de recursos:

  1. No nível do shell, defina FontFamily para todos os títulos de página.
    por exemplo

  2. No nível do shell, defina a imagem de fundo Título / Nav para todos os títulos de página / barras de navegação, etc.
    por exemplo

GroupBehavior não funciona para mim no pre4:

<ShellItem GroupBehavior="ShowTabs" FlyoutIcon="stuff.png" Title="Discussion">...
resulta em:

xxx / Shell / Shell.xaml (14,14): Erro: Posição 108: 14. Nenhuma propriedade, propriedade vinculável ou evento encontrado para 'GroupBehavior' ou tipo incompatível entre valor e propriedade.

e GroupHeaderTemplate não parece fazer nada, mas não tem certeza de como é usado ou ativado.

Estou tentando adicionar / remover MenuItems, que adiciona itens com sucesso através de MenuItems.Add (item), mas nenhum resultado é mostrado quando o menu desdobrável é exibido novamente. Esta é a abordagem correta para fazer isso?

Não vejo nenhuma menção à manipulação de MenuItems, mas o Shell é praticamente inútil para mim (e estou pensando em muitos outros, incluindo @puppetSpace acima), a menos que esses itens possam ser mantidos dinamicamente com base em sua lógica de negócios.

Eu concordo com o dbwelch que ser capaz de alterar programaticamente o shell no arquivo cs é muito importante. Não apenas para itens de menu, mas também ShellItems & ShellSections.

Quando eu ligo o Flyout e adiciono itens de menu, obtenho um menu de hambúrguer no Android e, no iOS, se eu clicar naquele local, ele funciona, no entanto, não há nenhum ícone. Alguma ideia?

@KyleTraynor, há um problema aberto em algum lugar para isso. Você deve copiar manualmente as imagens 3bar.png e

As imagens que encontrei na fonte estão anexadas:
3bar 2x
3bar

@melucas Obrigado pela ajuda! Eu estava enlouquecendo tentando consertar isso. Funciona bem.

Você sabe como posso definir o OffscreenPageLimit para Android ao usar o Shell?

Eu tenho páginas de guia superiores feitas com 4 ShellContents dentro de 1 ShellSection, e funciona muito bem no iOS, mas no Android as páginas recarregam ao alternar entre elas, o que eu não quero. Normalmente, com minha própria página de guia, eu poderia definir o OffscreenPageLimit para corrigir esse problema, mas não consigo encontrar uma maneira de fazer isso com o Shell.

@davidortinau podemos ter a opção de definir a família de fontes nos títulos das páginas, nas guias inferior e superior? Em todos os projetos, tenho que criar renderizadores personalizados para iOS e Android para alterar as fontes.

Portanto, visto que não houve resposta à minha postagem sobre a capacidade de realmente alterar os itens no submenu Shell, talvez essa funcionalidade não esteja no escopo ou talvez esteja sendo considerada um bug?

Não tenho certeza de como um aplicativo sério pode usar este Shell sem essa funcionalidade. Apenas aplicativos muito simples não exigem a capacidade de adicionar / alterar / remover / desativar itens em seus menus com base em a) contexto do usuário (ou seja, autenticado / não autenticado), ou b) vários estados do aplicativo que seriam exigir isso.

Por curiosidade, @jassmith , as pessoas que criaram a especificação estão inseridas neste fórum ou é apenas para feedback do desenvolvedor?

A propósito, além deste item principal, implementei o Shell em meu código para um aplicativo e está funcionando muito bem, obrigado! Mas, infelizmente, terei que retirá-lo e implementar meu próprio flyout se o Shell não tiver essa funcionalidade funcionando / implementada.

@dbwelch , algumas coisas.
Você está postando na especificação, então provavelmente não obterá uma resposta como a que escreveu abrindo uma nova edição. Além disso, Jason não está mais trabalhando no Formulários, então chamá-lo é meio inútil.

Resumindo, registre um problema

@dbwelch @ChaseFlorell Abri um problema aqui: https://github.com/xamarin/Xamarin.Forms/issues/5428

@davidortinau podemos ter a opção de definir a família de fontes nos títulos das páginas, nas guias inferior e superior? Em todos os projetos, tenho que criar renderizadores personalizados para iOS e Android para alterar as fontes.

@jamiewest Envie uma solicitação de recurso! Obrigado! https://github.com/xamarin/Xamarin.Forms/issues/new?assignees=&labels=t%2Fenhancement+%E2%9E%95&template=feature_request.md&title=%5BEnhancement%5D+YOUR+IDEA%21

O recurso UseSwipeGesture pode ser implementado?
Parece que agora a classe ShellItem não tem a propriedade ShellAppearance para operar.
Mas agora, no Android, as guias do The Shell não são como TabPage (TabPage pode deslizar como padrão.)

    <ShellItem.ShellAppearance>
      <MaterialShellAppearance NavBarCollapseStyle="Full" TabBarCollapseStyle="Full" UseSwipeGesture="false">
    </ShellItem.ShellAppearance>

@jingliancui , irmão Cui, existe algum qq ou WeChat?

@juepiezhongren Olá, você pode entrar neste grupo qq para bater um papo comigo 313308215

Veremos Shell e suporte visual chegando para UWP na RTM?

Eu acolho essa ideia - independentemente do que seja mais difícil, porque trabalhar com páginas de navegação, páginas master-detail, etc. parece muito complicado. Talvez seja porque eu venho de uma experiência na web (não trabalhei muito com APIs nativas). A personalização da barra de navegação, títulos de página, botão Voltar, itens da barra de ferramentas, cabeçalhos e rodapés (ListView), etc. vêm à mente aqui.

Suponho que o que estou solicitando é que novos recursos, como * Shell, sejam enviados com personalização e extensibilidade em mente. Em muito poucas situações em que não precisamos fazer uma série de renderizadores, comportamentos, gatilhos, etc. para realizar coisas aparentemente simples.

O que quer que vocês inventem, por favor, façam o que puderem para tornar mais fácil para nós fazer com que nossos aplicativos Xamarin.Forms tenham uma aparência tão boa quanto outros aplicativos nativos! Parece que esse recurso nos dará uma plataforma de lançamento melhor para aplicativos XForms de aparência moderna!

Existe código-fonte disponível para ver como esse Shell funciona, em vez de ter que adivinhar as especificações? Por exemplo, qual estilo é usado para colorir o ícone de hambúrguer, se estiver disponível. Desculpe, novo em C # / Xamarin, mas, se o código pudesse ser visualizado em algum lugar, ajudaria tremendamente.

@dbwelch você pode navegar pelo código-fonte aqui mesmo no GitHub. Pressione "T" e digite Shell para ver as classes associadas. Esse pode não ser o melhor ponto de partida, se você for novo no C # / Xamarin. Recomendo verificar alguns dos meus exemplos até que obtenhamos mais documentação:

https://github.com/davidortinau/Gastropods
https://github.com/davidortinau/ShellGallery
https://github.com/davidortinau/TheLittleThingsPlayground

Documentos: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell?tabs=android
Artigo MSDN: https://msdn.microsoft.com/en-us/magazine/mt848639
Blog: https://blog.xamarin.com/xamarin-forms-4-0-preview/

@davidortinau obrigado, mas, pensei que era um código recém-lançado que estava disponível,

@pauldipietro Obrigado, veja agora. @davidortinau Na verdade, passei muito tempo em todos os links (exceto LittleThings, que acabei de baixar), mas não vejo como mudar uma coisa tão simples como a cor do ícone de hambúrguer. Está aparecendo roxo no meu aplicativo, mas não tenho uma cor roxa definida em nenhum lugar (que eu possa ver). Um pouco frustrante ;-).

ATUALIZAÇÃO: Acabei de encontrar o problema e, claro, é algum código nojento que existe no FinishedLaunching para adicionar TintColor. DOH!

Obrigado senhores, agradeço a ajuda!

Tenho alguns itens aparecendo no painel flutuante, o que é bom. No entanto, atualmente já existe uma maneira de ocultar / não mostrar um item de Shell (não o conteúdo do item). Exemplo, eu tenho uma ContentPage e só quero ter a navegação dentro do Shell.

<local:DetailPage />

Parece que está sempre adicionando o item no painel / lista de submenu. E se não houver Título, ele terá uma pilha vazia / espaço reservado para o item. Eu tentei muitas maneiras de esconder o item ainda sem sorte. Provavelmente alguém pode ajudar ou o recurso ainda não está disponível.

Prefácio: Sou um newb atm. Tentando não ser.

@davidortinau Então, estou tentando aprender esse recurso Shell para adicionar navegação, etc. em nosso primeiro projeto Xamarin.Forms para nossa empresa (woot!) e estou preso tentando descobrir se é possível passar 1 ou mais parâmetros de um ShellItem para outras partes do aplicativo por meio da nova funcionalidade de roteamento. Isso é uma coisa? Ou devemos nos limitar a comandar usando MenuItems dentro de uma coleção MenuItem? Se devemos usar um MenuItem para passar 1 ou mais valores do nível Flyout, parece que não podemos mais estruturar nosso aplicativo com a hierarquia do Shell, já que estamos usando MenuItems. Não perdemos isso ao usar MenuItems com parâmetros de comando?

Existe alguém que pode opinar sobre isso? Se sim, eu agradeceria muito. Basicamente adoraria usar Shell, mas ainda seria capaz de marcar qual ShellItem o usuário selecionou ao clicar em um para passar para uma página ContentTemplate ou o que for apropriado, pois muitos ShellItems estarão navegando para uma página intermediária semelhante para fazer um OrderType e selecione a lista suspensa OrderDepartment antes de ir para a tela principal do Pedido com os dados apropriados para o tipo e departamento corretos.

Além disso, peço desculpas se este for o lugar errado para isso. Se sim, por favor, me indique o lugar certo. Obrigado!

Atualizar:
Talvez eu apenas use o MenuItems por enquanto e passe um parâmetro de comando para um ShellViewModel para navegar com os valores corretos para a página de destino. Agora que penso nisso, realmente não vou precisar navegar para uma estrutura com guias daqueles MenuItems empurrando para a página ContentTemplate.

Eu também queria saber se podemos definir onde MenuItems estão localizados dentro do Flyout para que os ShellItems não apareçam no topo; e se um dia não tivermos que definir nossos MenuItems como parte de uma coleção para que eles possam se misturar com ShellItems como:
MenuItem
ShellItem
ShellItem
MenuItem
ShellItem
MenuItem
...
Isso, ou apenas tornar os ShellItems capazes de passar parâmetros em algum ponto, se ainda não puderem.

Estou com @anthcool e acho esse recurso extremamente importante. Não consegui encontrar uma maneira de fazer isso e tive que parar de usar o Shell. Só precisa ser capaz de passar algo para uma página de conteúdo para saber qual foi clicado.

@anthcoolreadonly Stack<NavigationParameter> como uma lista de pilha, ou seja,

public class Navigation
{
    readonly Stack<NavigationParameter> _stack = new Stack<NavigationParameter>();
...
    public Stack<NavigationParameter> Parameters => _stack;
}

O NavigationParameter é:

public class NavigationParameter : NameValueCollection { }

Você pode adicionar parâmetros antes do push ao navegar, por exemplo:

    var p = new NavigationParameter { { nameof(SomePage), SomeObject } };
    Navigation.Parameters.Push(p);

Assim que estiver na outra página, basta espiar ou exibir o valor e verificar a chave.
Algo como acima. Espero que ajude.

@anthcoolreadonly Stack<NavigationParameter> como uma lista de pilha, ou seja,

public class Navigation
{
    readonly Stack<NavigationParameter> _stack = new Stack<NavigationParameter>();
...
    public Stack<NavigationParameter> Parameters => _stack;
}

O NavigationParameter é:

public class NavigationParameter : NameValueCollection { }

Você pode adicionar parâmetros antes do push ao navegar, por exemplo:

    var p = new NavigationParameter { { nameof(SomePage), SomeObject } };
    Navigation.Parameters.Push(p);

Assim que estiver na outra página, basta espiar ou exibir o valor e verificar a chave.
Algo como acima. Espero que ajude.

Obrigado pela ideia @rizamarhaban! Agradeço muito por você ter concordado com isso. Obrigado! Vou verificar isso aqui em breve. Mais uma vez, agradeço!

Muito desapontado ao saber que Shell e Visual não suportam UWP.

Esta especificação está realmente concluída?
Por que fechar isso só porque agora há uma implementação do Tizen?
Tive a impressão de que a funcionalidade de navegação ainda estava em revisão.

Ainda sem suporte UWP. A maior decepção que já tive com Xamarin.

@weitzhandler Envie um e-mail para paul. [email protected] se desejar discutir isso e UWP em geral. Não estamos ignorando ativamente a plataforma, mas o Android e o iOS estão recebendo a implementação inicial e as investigações sobre o suporte da Shell para UWP estão em andamento.

@mrlacey Nah, está longe de terminar! Ele simplesmente continua sendo fechado por questões relacionadas. 😄

Para todos aqueles que pedem suporte UWP, eu tentei: https://github.com/xamarin/Xamarin.Forms/pull/6015

Existe uma maneira de implementar um modelo de barra de navegação na página de conteúdo?
Especificar NavigationPage.TitleView não se aplica como antes.
Repo para referência:
https://github.com/InquisitorJax/Xamarin-Forms-Shell

EDITAR:
Murphy ataca novamente - basta usar Shell.TitleView em vez de NavigationPage.TitleView :)

Olá,
No meu novo projeto estou usando Shell e CollectionView, e devo dizer que são ótimos!
Uma pergunta sobre a Shell

  • existe uma maneira de adicionar um item inferior fixo (exemplo de raposa um botão para logout do usuário)

Vejo que é possível adicionar um cabeçalho fixo (FlyoutHeader e FlyoutHeaderBehavior), mas não consigo encontrar nenhuma informação sobre o rodapé inferior
Obrigado!

Olá,
Tenho outra pergunta sobre RegisterRoute.
Meu aplicativo é bastante grande, com um número considerável de páginas, cerca de 30 ...
É realmente a maneira certa de adicionar o RegisterRoute para cada um deles?
Routing.RegisterRoute("blabla", typeof(BlaBlaPage)); ... ...
Ou é melhor usar o método antigo?
var blaPage = new BlaBlaPage (); await Navigation.PushAsync (blaPage);

@matteopiccioni eu recomendaria fazer assim

Routing.RegisterRoute("blabla", typeof(BlaBlaPage));

e usando
gotoasync("blabla")

Percebo agora que parece o mesmo, mas conforme os recursos aumentam, será mais relevante ter todas essas coisas operando por meio do sistema Shell

É realmente a maneira certa de adicionar o RegisterRoute para cada um deles?

se isso se tornar um ponto problemático, estamos tentando adicionar alguns recursos que apenas farão a varredura de montagem de páginas ou talvez até mesmo alguns recursos de tempo de compilação que irão gerar essas rotas.

O principal problema aqui é que qualquer tipo de reflexão tornará seu aplicativo lento, então fazer isso na inicialização custará

@PureWeen obrigado pela resposta
O tempo de inicialização lento é um dos problemas mais irritantes no xf (para Android)
Na inicialização, posso adicionar ao roteamento apenas o primeiro nível de páginas (as páginas de shellitems) e adicionar os outros apenas depois que o aplicativo for iniciado (uma espécie de carregamento lento de RegisterRoute)?

@matteopiccioni

Então, se você fizer assim, tudo de uma vez

Routing.RegisterRoute("blabla", typeof(BlaBlaPage));

está bem. Tudo o que eu estava falando é se acabarmos construindo algo que faça com que os usuários não precisem fazer isso, teremos de comparar com o desempenho. No momento, Routing.RegisterRoute("blabla", typeof(BlaBlaPage)); não faz nenhum reflexo, portanto, fazer tudo de uma vez está bom.

tudo o que faz é adicionar uma string e um tipo a um dicionário

@jassmith @jamesmontemagno @pierceboggan Uau, parece ótimo. Você já viu o aplicativo de contatos do Google usando Pie SDK em um Google Pixel? Eu amo a UI / UX, sem barra de título e o hambúrguer integrado com a parte superior do aplicativo.

Essa sugestão pode ser considerada para o seu Shell, já que é um padrão que o Google está usando, com Contatos e Mapas, e talvez outros?

Obrigado pelo seu tempo e consideração,

Karl

Observe que todos os exemplos a seguir não usam o modelo ShellContent, que é discutido em outra parte da especificação. A falha em usar ShellContents com um ContentTemplate resultará no carregamento de todas as páginas na inicialização, o que afetará negativamente o desempenho da inicialização. Esses exemplos são apenas para fins de aprendizagem.
Felizmente, usar ShellContents com ContentTemplates geralmente é mais conciso do que não usá-los.
[...]
Um grande problema com o uso do Shell é a facilidade com que um usuário pode acabar carregando todas as páginas no início da execução do aplicativo. Essa grande alocação antecipada pode resultar em um desempenho de inicialização bastante ruim se um grande número de páginas de conteúdo for necessário. A fim de corrigir esse modelo, deve-se empregar sempre que possível.

Para mim, isso soa como se você nunca devesse usar o conteúdo diretamente, mas sim modelos. Isso faz sentido para mim, então por que apoiar a abordagem de conteúdo direto? (além da simplicidade, mas é permitir que as pessoas atirem no próprio pé). Parece que poder usar conteúdo direto é mais um recurso "ótimo ao fazer uma demonstração - caso contrário, horrível".

Oi,
Eu sou novo aqui. Não tenho certeza se este é o lugar certo para fazer perguntas, caso contrário, indique-me onde perguntar:
Tentei fazer algo semelhante ao exemplo especificado acima:

  <ShellItem Title="My music" ItemsSource="{x:Bind MyMusicModels}" TabLocation="Bottom">
    <ShellItem.ItemTemplate>
      <local:MyMusicItemTemplateSelection />
    </ShellItem.ItemTemplate>
  </ShellItem>

Mas recebi os seguintes erros:

Erro XLS0413 A propriedade 'ItemsSource' não foi encontrada no tipo 'ShellItem'.
Erro XLS0415 A propriedade anexável 'ItemTemplate' não foi encontrada no tipo 'ShellItem'.

@Elashi então você espera fazer essa ideia aqui
https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/layouts/bindable-layouts

Com ShellItem?

@PureWeen, eu esperava usar essa ideia :).
Você está sugerindo que essa ideia ainda não foi implementada?
Se ainda não foi implementado, posso estar interessado em trabalhar nisso.

@Elashi não é, mas pude ver que é um recurso realmente poderoso para cenários MVVM

Se quiser trabalhar nisso, você pode criar um problema com o básico do que está pensando?

Então, por tentativa e erro ... Mesmo que ele tenha comentários sobre gestos no shell 3.2 e esteja no TheLittlePlayground, eu não posso por minha vida fazer gestos funcionarem no ANDROID com o pacote visual.

Estou faltando alguma coisa nas notas de que os gestos Shell + só funcionam com iphone?

@davidortinau Sei que são apenas algumas especificações e estão fechadas há um tempo, mas esperava que você pudesse me indicar a direção certa, já que as especificações indicam que a tarefa abaixo está concluída ou em processo de desenvolvimento:

  • Adicionar API para itens de "submenu" para o ala GPS de ShellContent -> Música -> Abrir aplicativo de música

Atualmente, como não consigo fazer os GroupHeaders funcionarem, estou tentando retrabalhar meu FlyoutMenu para classificar em 6 grupos principais e, em seguida, ter um submenu cheio de FlyoutItems que me conduzem ao roteamento que predeterminado.

Meu caso de uso é que tenho mais de 50 opções para exibir e colocar isso em um estado de rolagem não é amigável à IU, mas cada opção a ser exibida é algo que preciso permitir que meus usuários acessem com eficiência sem ter que rolar indefinidamente. Classificar em grupos com base no tema abrangente de cada opção faz mais sentido do ponto de vista de UI / UX.

Você pode lançar alguma luz sobre onde isso se encontra em termos de desenvolvimento / produção? - ou me aponte na direção de uma base de código que o implementa para que eu possa aprender? (Estou com o Xamarin há apenas 1 mês, então ainda sou novo em alguns dos recursos disponíveis).

@TheBaileyBrew

Acabei de pesquisar este repositório no Google com algo que provavelmente pode funcionar para o seu cenário. Não será Shell, mas você poderia usá-lo em uma configuração de MasterDetailPage provavelmente.

https://github.com/ishrakland/ListViewWithSubListView/

Além disso, eles mudaram e atualizaram muito do material do curso para o MSFT Learn (que estou examinando sozinho para preencher as lacunas). Isso pode ser encontrado aqui: https://docs.microsoft.com/en-us/learn/browse/?products=xamarin

Eu tentaria repassar o que precede. Boa sorte e seja bem-vindo a bordo!

Olá pessoal, quero escolher o arquivo ou as fotos da galeria ou armazenamento externo em
O xamarin forma quem escolher o arquivo? O arquivo tem apenas extensão .PDF. Para
selecione os dois arquivos Eu uso um botão então agrada me ajude !!!

Na quinta-feira, 23 de maio de 2019, 19:41, Anthony Cool [email protected] escreveu:

@TheBaileyBrew https://github.com/TheBaileyBrew

Eu apenas pesquisei este repositório com algo que poderia funcionar para o seu cenário
provavelmente. Não será Shell, mas você pode usá-lo em uma MasterDetailPage
configuração provavelmente.

https://github.com/ishrakland/ListViewWithSubListView/

-
Você está recebendo isto porque está inscrito neste tópico.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/xamarin/Xamarin.Forms/issues/2415?email_source=notifications&email_token=AK7KSYK4N3XIVP3IHOBE2P3PW3CKJA5CNFSM4EZ4GB52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODWCZR7Y#issuecomment-495294719 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AK7KSYI5XKMXD7FC7HZH45LPW3CKJANCNFSM4EZ4GB5Q
.

Ei pessoal, eu quero adicionar guias com base na condição, então como posso adicionar guias no Shell usando C # não no Xaml e também como adicionar itens de menu.

@TheBaileyBrew

é isso que você está procurando?
https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/flyout#flyout -display-options

@BeleShew sua pergunta provavelmente é mais adequada para stackoverflow ou em forums.xamarin.com

@PWaliaDev você faria isso por meio das várias coleções de itens que fazem parte do shell

Shell.Items.Add (new ShellItem ())
new ShellItem (). Items.add (new ShellSection ())
new ShellSection (). Items.Add (new ShellContent ())

Embora eu esteja supondo que, se consertamos esse problema,
https://github.com/xamarin/Xamarin.Forms/issues/5428

isso se adequaria ao seu cenário?

@PureWeen - Eu tenho as opções de exibição definidas por seu link, mas o que estou lutando está mais perto do que @BeleShew está lidando (criando / removendo itens flyout por usuário)

Consertar o # 5428 se encaixaria no que estou procurando alcançar.

Meu aplicativo tem usuários com uma infinidade de funções / acesso e eu preciso mostrar as opções de menu programaticamente apenas para aqueles usuários que estão autorizados (não quero que os usuários vejam o que eles _ não podem _ fazer, apenas o que podem.

Embora eu esteja brincando com isso, tentando descobrir se é possível inspecionar minhas opções de menu e adicionar em vez de ocultar como este código faz (mas eu teria que iterar em todas as rotas possíveis e opções de menu que consumiriam tempo de carregamento:

foreach (var item in this.Items)
        {
            if (item is FlyoutItem)
            {
                var removeSections = new List<ShellSection>();
                var fi = item as FlyoutItem;
                foreach (var child in fi.Items)
                {
                    if (child.Route == "NOT_AUTHORIZED_KEY")
                        removeSections.Add(child);
                }
                foreach (var s in removeSections)
                    fi.Items.Remove(s);
            }
        }

O Shell é ótimo em teoria, mas não em termos práticos sem esses recursos essenciais.

  1. Adicionar / remover itens de shell dinamicamente com base na função do usuário
  2. Cenário de Login / Logout ou duas rotas de navegação separadas com base nas condições.
  3. Opcionalmente, suporte para outras estruturas MVVM como Prism

Não é possível usar o Shell em aplicativos orientados a negócios até que os recursos 1 e 2 sejam fornecidos.

@ Im-PJ Por que você acha que 1 e 2 não são possíveis? (tenho certeza que eles são)

3 está em andamento e monitorado aqui .

Alguém sabe se é possível obter um evento de toque de uma guia do App Shell?
pergunta do fórum relacionada: https://forums.xamarin.com/discussion/159748/app-shell-pop-to-root-on-tab-tap

Concordo totalmente com @ Im-PJ e não entendo como esses recursos não são fornecidos especificamente. É um dos principais motivos para uma ferramenta como a Shell. Qualquer pessoa pode criar um menu deslizante!

@dotMorten talvez você possa fazer 1 ou 2 por meio de C # extensivo e hacking, mas não há exemplos ou menção de vincular / desabilitar / ocultar / adicionar itens do Shell em tempo de execução que eu possa encontrar. Parece que os recursos dinâmicos teriam sido o principal objetivo desta ferramenta. A criação de uma representação XML, junto com alguns recursos de caminho, é o mínimo, o suficiente para fornecer ao pessoal de marketing, mas não suficiente para realmente usar em um aplicativo móvel real e completo.

@ Im-PJ

você pode expandir um pouco sobre como eles são diferentes?

Adicionar / remover itens de shell dinamicamente com base na função do usuário
Cenário de Login / Logout

Atualmente você pode fazer um Cenário de Login / Logout usando uma TabBar ou ocultando a navegação flyout se você estiver em uma página de login

<TabBar Route="LoggedOut">
<LoginPage>
</TabBar>

<FlyoutItem Route="LoggedIn"></FlyoutItem>
<FlyoutItem></FlyoutItem>
<FlyoutItem></FlyoutItem>
<FlyoutItem></FlyoutItem>

Se você estiver na página de login, a única maneira de sair dele é por meio do código.

Trabalho está sendo feito aqui para expor uma propriedade vinculável IsVisible
https://github.com/xamarin/Xamarin.Forms/tree/shell_isvisible

Só precisa de um pequeno refinamento antes de criar um PR

duas rotas de navegação separadas com base nas condições.

Você pode fornecer exemplos do que você está tentando fazer e não pode fazer atualmente?

hoi1
Estou usando o Xamarin.Form Shell

Amostra de link: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/flyout

Por favor me ajude. Como mostrar a Tabbar na página Sobre?

Eu preciso ter duas páginas de shell ao mesmo tempo.
Um para um menu flayout com a página inicial, configurações, logout, etc.
Um para páginas com guias que devem ser empurradas de casa
Por enquanto eu tenho que usar o 'jeito antigo'

Eu preciso ter duas páginas de shell ao mesmo tempo.
Um para um menu flayout com a página inicial, configurações, logout, etc.
Um para páginas com guias que devem ser empurradas de casa
Por enquanto eu tenho que usar o 'jeito antigo'

Se estiver usando Tabbedpage, não pode mostrar Flyout. Quero mostrar Flyout e Tabbar neste momento.

Eu coloquei todas as páginas nopara que as páginas exibam a Tabbar, mas eu quero ter apenas 4 elementos na tabbar (não quero mostrar a guia Mais). Como fazer?

<shell>
<flyoutitem route="animals" flyoutdisplayoptions="AsMultipleItems">
<shellcontent route="cats"/>
<shellcontent route="dogs"/>
<shellcontent route="monkeys"/>
<shellcontent route="elephants"/>
<shellcontent route="bears"/>
<shellcontent route="about"/>
</flyoutitem>
</shell>

Eu preciso ter duas páginas de shell ao mesmo tempo.
Um para um menu flayout com a página inicial, configurações, logout, etc.
Um para páginas com guias que devem ser empurradas de casa
Por enquanto eu tenho que usar o 'jeito antigo'

Se estiver usando Tabbedpage, não pode mostrar Flyout. Quero mostrar Flyout e Tabbar neste momento.

Coloquei todas as páginas no para que as páginas exibam a Tabbar, mas quero ter apenas 4 elementos na tabbar (não quero mostrar Mais Tab). Como fazer?

<shell>
<flyoutitem route="animals" flyoutdisplayoptions="AsMultipleItems">
<shellcontent route="cats"/>
<shellcontent route="dogs"/>
<shellcontent route="monkeys"/>
<shellcontent route="elephants"/>
<shellcontent route="bears"/>
<shellcontent route="about"/>
</flyoutitem>
</shell>

Infelizmente não posso usar Shell
Eu ainda tenho MasterDetailPage e TabbedPage no mesmo aplicativo (no iOS eu tenho as principais páginas com guias usando o plugin Naxam.TopTabbedPage.Forms)
Este era meu antigo ingresso

Esta página foi útil?
0 / 5 - 0 avaliações