简体   繁体   English

我可以在 Xamarin Forms Shell 的标签栏上方添加静态视图吗?

[英]Can I add a static view above the tabbar in Xamarin Forms Shell?

I want to add a custom view above the tabbar in Xamarin Forms Shell (iOS and Android) to implement an audio player that is always visible.我想在 Xamarin Forms Shell(iOS 和 Android)中的选项卡栏上方添加一个自定义视图,以实现始终可见的音频播放器。

For Android I looked into this blog post about customizing the tabbar on Android ( https://www.andrewhoefling.com/Blog/Post/xamarin-forms-shell-customizing-the-tabbar-android ), and added an extra layout with id '@+id/bottomtab.view' to my customized BottomTabLayout.axml.对于 Android,我查看了这篇关于在 Android 上自定义标签栏的博客文章( https://www.andrewhoefling.com/Blog/Post/xamarin-forms-shell-customizing-the-tabbar-android ),并添加了一个额外的布局id '@+id/bottomtab.view' 到我自定义的 BottomTabLayout.axml。

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        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" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <LinearLayout
                android:orientation="horizontal"
                android:id="@+id/bottomtab.view"
                android:layout_width="match_parent"
                android:background="@drawable/abc_action_bar_item_background_material"
                android:layout_height="70dp" />

            <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>
    </LinearLayout>

    <FrameLayout
        android:id="@+id/bottomtab.tabbar.container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal|bottom" />

</FrameLayout>

In my custom ShellItemRenderer of my TabBar subclass I want to add the xaml to the layout, but that doesn't work.在我的 TabBar 子类的自定义 ShellItemRenderer 中,我想将 xaml 添加到布局中,但这不起作用。

using Xamarin.Forms;

namespace TodosSample.Controls
{
    public class TodoTabBar : TabBar
    {
        public Tab LargeTab { get; set; }

        public View View { get; set; }
    }
}

XAML XAML

<c:TodoTabBar.View>
    <Grid BackgroundColor="#232026" Padding="10">
    <Grid BackgroundColor="PaleVioletRed">
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <Grid BackgroundColor="#092C33" Grid.Row="0">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="60" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="60" />
        </Grid.ColumnDefinitions>

        <Button BackgroundColor="IndianRed" Text="Click me" Clicked="Button_Clicked"/>

            <Grid Grid.Column="1" BackgroundColor="Yellow">
                <Label Text="Guy en Marinda" />
            </Grid>

            <Grid Grid.Column="2" WidthRequest="50" HeightRequest="50" BackgroundColor="Aqua" />


    </Grid>

</c:TodoTabBar.View>

For some reason the background of the outer grid is applied, like you can see in the screenshot, but the contents are not shown.出于某种原因,应用了外部网格的背景,就像您在屏幕截图中看到的那样,但未显示内容。 I don't know how to apply the correct dimensions to make the grid and the children take the full width of the screen.我不知道如何应用正确的尺寸来使网格和孩子们占据屏幕的整个宽度。

Screenshot截屏

// Rendering part in the custom TodoShellItemRenderer. This code is being called
private void SetupView()
{
    var todoTabBar = (TodoTabBar)ShellItem;

    var renderer = Platform.CreateRendererWithContext(todoTabBar.View, Context);
    renderer.Tracker.UpdateLayout();
    var nativeView = renderer.View;
    nativeView.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
    
    
    int width = ViewGroup.LayoutParams.MatchParent;
    int height = 70;
    todoTabBar.View.Layout(new Xamarin.Forms.Rectangle(0, 0, width, height));
    
    nativeView.Layout(0, 0, width, height);

    _view.RemoveAllViews();
    _view.AddView(nativeView);

    nativeView.ForceLayout();
}

I like the idea to define the contents of the view in xaml to be able to setup the bindings and such.我喜欢在 xaml 中定义视图内容的想法,以便能够设置绑定等。 How can I render the view correctly in the layout?如何在布局中正确呈现视图?

=============== ================

Update 2020-11-12更新 2020-11-12

I have changed my code to implement Leo's suggestion, but changed it to use the bottomtab.view layout in the android xml.我已经更改了代码以实现 Leo 的建议,但将其更改为使用 android xml 中的 bottomtab.view 布局。 (I use the framelayout bottomtab.tabbar.container for a kind of floating button, that works fine). (我使用 framelayout bottomtab.tabbar.container 作为一种浮动按钮,效果很好)。

However, it looks like the width of the view above the tab bar is incorrect.但是,标签栏上方的视图宽度似乎不正确。 In the screenshot you see that the Pink BoxView doesn't have a right side, it looks like the inner gridview (white background) is too wide.在屏幕截图中,您看到 Pink BoxView 没有右侧,看起来内部 gridview(白色背景)太宽了。 The bottom black border of the screenshot is the tabbar that I redacted.屏幕截图的底部黑色边框是我编辑的标签栏。

Screenshot截屏

This is my definition of the extra view in xaml:这是我在 xaml 中对额外视图的定义:

<Grid BackgroundColor="HotPink">

    <BoxView BackgroundColor="Pink"  />
    <Grid BackgroundColor="White" Margin="5">

    </Grid>                
                
</Grid>

This is the adapted SetupView method这是改编的 SetupView 方法

private void SetupTopView()
{
    var todoTabBar = (SearchTabBar)ShellItem;
    var height = 70;
    var width = (int)Resources.DisplayMetrics.WidthPixels;
    Rectangle size = new Rectangle(0, 0, width, height);
    todoTabBar.ExtraView.Layout(size);
    var renderer = Platform.CreateRendererWithContext(todoTabBar.ExtraView, Context);
    renderer.Tracker.UpdateLayout();
    var nativeView = renderer.View;

    var layout = new FrameLayout(Context);
    layout.AddView(nativeView);
    var lp = new FrameLayout.LayoutParams(width, height * (int)Resources.DisplayMetrics.Density);
    _bottomView.Measure((int)MeasureSpecMode.Unspecified, (int)MeasureSpecMode.Unspecified);
    lp.BottomMargin = _bottomView.MeasuredHeight;

    layout.LayoutParameters = lp;
    _extraViewContainer.RemoveAllViews();
    _extraViewContainer.AddView(layout);
}

Any suggestion to let it use the correct width?有什么建议让它使用正确的宽度吗? Or is my xaml definition incorrect?还是我的 xaml 定义不正确?

You could try the below:你可以试试下面的:

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.LargeTab != null)
            SetupView();

        return outerlayout;
    }

private void SetupView()
 {
        var todoTabBar = (TodoTabBar)ShellItem;
        var height = 70;
        var width = (int)Resources.DisplayMetrics.WidthPixels;
        Rectangle size = new Rectangle(0, 0, width, height);
        todoTabBar.View.Layout(size);
        var renderer = Platform.CreateRendererWithContext(todoTabBar.View, Context);
        renderer.Tracker.UpdateLayout();
        var nativeView = renderer.View;
 
        var layout = new FrameLayout(Context);
        layout.AddView(nativeView);
        var lp = new FrameLayout.LayoutParams(width, height* (int)Resources.DisplayMetrics.Density);
        _bottomView.Measure((int)MeasureSpecMode.Unspecified, (int)MeasureSpecMode.Unspecified);
        lp.BottomMargin = _bottomView.MeasuredHeight;

        layout.LayoutParameters = lp;
        _shellOverlay.RemoveAllViews();
        _shellOverlay.AddView(layout);
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM