添加一个应该始终对 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 项目中创建 TodoShellRenderer
和 TodoShellItemRenderer
:
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
我想做这样的布局:
我正在使用 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 项目中创建 TodoShellRenderer
和 TodoShellItemRenderer
:
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