如何在android布局视图中添加或替换页面

时间:2017-10-30 05:01:21

标签: c# android xamarin xamarin.forms bottomnavigationview

我正在尝试使用andoid的BottomNavigationView在Xamarin Forms跨平台应用程序中制作类似iOS的标签页,方法是在android项目中制作一个特定于平台的渲染器。基本上我添加了一个带有bottomnavigationview的布局,并在渲染器中将此视图添加到根活动,并基于窗体选项卡页面创建菜单项。现在问题是如何将表单选项卡页面的当前页面添加/显示到android布局,并在单击条形图项时替换它。我发现即使我在渲染器中调用RemoveAllViews,选项卡页面中的内容页面也会占据整个屏幕,它甚至会覆盖底部栏。因此,如果选项卡页面的任何一个内容页面可见,它将占据整个屏幕。 android的AddView方法也只接受android视图,它不接受表单视图。

BottomNav布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"
android:layout_above="@+id/bottom_navigation"
android:orientation="vertical">
</FrameLayout>

<android.support.design.widget.BottomNavigationView
  android:id="@+id/bottom_navigation"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_alignParentBottom="true"
  app:itemBackground="@color/colorPrimary"
  android:background="@color/colorPrimary"
  app:itemIconTint="@color/white"
  app:itemTextColor="@color/white"
  app:menu="@menu/bottom_navigation_main" />

</RelativeLayout>

渲染器OnElementChanged:

        base.OnElementChanged(e);
        TabbedPage oe = e.OldElement;
        TabbedPage ne = e.NewElement;
        int id = 1000;
        foreach(Page p in ne.Children)
        {
            items.Add(new Item
            {
                text = p.Title,
                icon = p.Icon,
                page = p,
                id = id++,
            });
            p.IsVisible = false; // without this, page show full screen and covers the bottom bar
        }

        RemoveAllViews();
        Activity activity = this.Context as Activity;
        view = activity.LayoutInflater.Inflate(Resource.Layout.BottomNav, this, false);
        AddView(view);
        layout = view.FindViewById<FrameLayout>(Resource.Id.rootLayout);
        // add current page to layout, or replace layout with page? and How?
        //
        //

        BottomNavigationView bottomNavigationView = (BottomNavigationView)
            FindViewById(Resource.Id.bottom_navigation);
        bottomNavigationView.NavigationItemSelected += BottomNavigationView_NavigationItemSelected;

        Android.Support.V7.View.Menu.MenuBuilder menu = bottomNavigationView.Menu as Android.Support.V7.View.Menu.MenuBuilder;
        menu.Clear();

        foreach(Item i in items)
        {
            IMenuItem mi = menu.Add(0, i.id, 0, i.text);
            mi.SetIcon(Resource.Drawable.icon);
        }

编辑:添加更多代码和屏幕截图

我的预期布局是这样的,没有显示XF标签页中的页面,红色的主要部分是标识为FrameLayout的{​​{1}},目标是添加标签页的当前页面到Framelayout并显示它,当点击BottomNavigationView中的项目时,切换FrameLayout以显示其他页面。但是这个屏幕只能通过以下方式使所有页面不可见:

rootLayout

android view

如果没有将设置显示为false,则子页面将占据整个屏幕: enter image description here

我的测试XF标签页:

        foreach (Page p in e.NewElement.Children)
        {
            p.IsVisible = false;
        }

1 个答案:

答案 0 :(得分:1)

根据您的说明,我认为您根本不需要TabbedPage,您只需要BottomNavigationViewFrameLayout视图片段。然后,您可以为此自定义ViewRenderer

首先,在PCL中创建View的子类,例如:

public class BottomTabbedView:View
{
}

然后在android客户端项目中实现其渲染器:

[assembly:ExportRenderer(typeof(BottomTabbedView),typeof(BottomTabbedViewRenderer))]
namespace PackageNameSpace.Droid
{
    public class BottomTabbedViewRenderer:ViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
        {
            base.OnElementChanged(e);
            if (Control == null)
            {
                // Instantiate the native control and assign it to the Control property with
                // the SetNativeControl method
                var context = Xamarin.Forms.Forms.Context;
                LayoutInflater inflater = context.GetSystemService(Context.LayoutInflaterService) as LayoutInflater;
                var bottomnav_view = inflater.Inflate(Resource.Layout.bottomnav_view, this, false);
                var frame = bottomnav_view.FindViewById<FrameLayout>(Resource.Id.rootLayout);
                var navi = bottomnav_view.FindViewById<BottomNavigationView>(Resource.Id.bottom_navigation);
                SetNativeControl(bottomnav_view);
            }

            if (e.OldElement != null)
            {
                // Unsubscribe from event handlers and cleanup any resources
            }

            if (e.NewElement != null)
            {
                // Configure the control and subscribe to event handlers
            }
        }
    }
}

我没有完成BottomNavigationViewFrameLayout逻辑的所有代码,您应该能够在ViewRenderer内实现逻辑。代码应该类似于Xamarin.Android的代码。

然后你可以将这个视图用作XF ContentPage内的普通视图控件,例如:

<local:BottomTabbedView/>