添加一个应该始终对 Xamarin Forms 可见的通用元素 Shell

Add a common Element that should always be visible for Xamarin Forms Shell

我想做这样的布局:

我正在使用 Shell 和 Tab(目前没有弹出窗口),但我不知道如何实现这一点。我尝试创建一个页面,但显然它不起作用:

    <ContentPage.Content>
        <StackLayout>
            <root:AppShell />
            <Label Text="My Content" />
        </StackLayout>
    </ContentPage.Content>

有没有办法用东西包裹 content/Shell?此外,该内容最好位于选项卡上方,但也可以位于下方。

您可以使用 Shell CustomRender 来实现。

在表单项目中创建 TodoTabBar

public class TodoTabBar : TabBar
  {
    public StackLayout BottomLayout { get; set; }
  }

然后在AppShell.xaml中设置:

 <c:TodoTabBar> 
    <c:TodoTabBar.BottomLayout>
      <StackLayout  HorizontalOptions="StartAndExpand" HeightRequest="200">
          <Label Text="I'm bottomview"></Label>
      </StackLayout>
    </c:TodoTabBar.BottomLayout>

    <Tab ..>
        <ShellContent ContentTemplate="..." />
    </Tab>

    <Tab ...>
        <ShellContent ContentTemplate="..." />
    </Tab>
</c:TodoTabBar>

在您的 Android 项目中创建 TodoShellRendererTodoShellItemRenderer

public class TodoShellRenderer : ShellRenderer
{
    public TodoShellRenderer(Context context) : base(context)
    {
    }

    protected override IShellItemRenderer CreateShellItemRenderer(ShellItem shellItem)
    {
        return new TodoShellItemRenderer(this);
    }
}

public class TodoShellItemRenderer : ShellItemRenderer
{
    FrameLayout _shellOverlay;
    BottomNavigationView _bottomView;
    public TodoShellItemRenderer(IShellContext shellContext) : base(shellContext)
    {
    }

    public override Android.Views.View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        var outerlayout = base.OnCreateView(inflater, container, savedInstanceState);
        _bottomView = outerlayout.FindViewById<BottomNavigationView>(Resource.Id.bottomtab_tabbar);
        _shellOverlay = outerlayout.FindViewById<FrameLayout>(Resource.Id.bottomtab_tabbar_container);

        if (ShellItem is TodoTabBar todoTabBar && todoTabBar.BottomLayout != null)
            SetupBottomLayout();

        return outerlayout;
    }

    private async void SetupBottomLayout()
    {
        var todoTabBar = (TodoTabBar)ShellItem;
        var layout = new FrameLayout(Context);

        var stackLayout = todoTabBar.BottomLayout;

        var size = new Rectangle(0, 0, Context.Resources.DisplayMetrics.WidthPixels, stackLayout.HeightRequest);

        var vRenderer = RendererFactory.GetRenderer(stackLayout);
        var viewGroup = vRenderer.ViewGroup;
        vRenderer.Tracker.UpdateLayout();
        var layoutParams = new ViewGroup.LayoutParams((int)size.Width, (int)size.Height);
        viewGroup.LayoutParameters = layoutParams;
        stackLayout.Layout(size);
        viewGroup.Layout(0, 0, (int)stackLayout.WidthRequest, (int)stackLayout.HeightRequest);
        layout.AddView(viewGroup);
        _shellOverlay.RemoveAllViews();
        _shellOverlay.AddView(layout);
    }
 }

BottomTabLayout.xml(这是我们应该替换默认值 xml 的内容,为了使其正常工作,布局中的 ID 必须与 Xamarin Androidn 平台中的 ID 完全匹配布局):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent">

    <LinearLayout
       android:layout_above="@id/bottomtab.tabbar.container"
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
  
    <FrameLayout
       android:id="@+id/bottomtab.navarea"
       android:layout_width="match_parent"
       android:layout_height="0dp"
       android:layout_gravity="fill"
       android:layout_weight="1" />
    
    <com.google.android.material.bottomnavigation.BottomNavigationView
       android:id="@+id/bottomtab.tabbar"
       android:theme="@style/Widget.Design.BottomNavigationView"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"/>

    </LinearLayout>

    <FrameLayout
       android:id="@+id/bottomtab.tabbar.container"
       android:background="#f00"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignParentBottom="true"
     />

</RelativeLayout>

灵感来自 Can I add a static view above the tabbar in Xamarin Forms Shell?.

的 link