2017-10-30 4 views
0

안드로이드 프로젝트에서 플랫폼 특정 렌더러를 작성하여 Xamarin Forms 크로스 플랫폼 앱에서 iOS와 유사한 탭 페이지를 만들기 위해 andoid의 BottomNavigationView을 사용하려고합니다. 기본적으로 나는 bottomnavigationview가있는 레이아웃을 추가하고 렌더러에서이 뷰를 루트 액티비티에 추가하고 폼 탭 페이지를 기반으로 메뉴 항목을 만듭니다. 이제 문제는 폼 탭 페이지의 현재 페이지를 안드로이드 레이아웃에 추가/표시하고 막대 항목을 클릭 할 때 어떻게 바꿀 수 있습니까? 렌더러에 RemoveAllViews라고 부르는 것을 발견했습니다. 탭 페이지의 컨텐츠 페이지가 전체 화면을 차지하게되고 하단 바를 덮어 버릴 것입니다. 따라서 탭이 지정된 페이지 중 하나의 내용 페이지가 표시되면 전체 화면을 차지합니다. 또한 안드로이드의 AddView 메소드는 안드로이드 뷰만 허용하고 폼 뷰는 허용하지 않습니다.안드로이드 레이아웃보기에서 페이지를 추가하거나 교체하는 방법

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에서 페이지를 표시하지 않고, 이런 식입니다 tabbedpage, 빨간색의 주요 부분은 rootLayoutFrameLayout이며 목표는 tabbedpage의 현재 페이지를 t에 추가하는 것입니다. 그는 Framelayout을 표시하고 BottomNavigationView의 항목을 클릭하면 FrameLayout을 전환하여 다른 페이지를 표시합니다. 하지만이 화면에서 보이지 않는 모든 페이지를함으로써 만 가능합니다 :

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

android view

false로 설정 보이지 않고, 서브 페이지가 전체 화면을 차지합니다 경우 enter image description here

내 테스트 XF를 탭 페이지 :

<?xml version="1.0" encoding="utf-8" ?> 
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms" 
     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
     xmlns:local="clr-namespace:BottomTabbed" 
     x:Class="BottomTabbed.TabbedPage1" 
     NavigationPage.HasNavigationBar="False"> 
     <ContentPage Title="Tab 1" BackgroundColor="Green" /> 
     <ContentPage Title="Tab 2" BackgroundColor="Blue"/> 
     <ContentPage Title="Tab 3" BackgroundColor="Red"/> 
     <ContentPage Title="Tab 4" BackgroundColor="Gray" /> 
</TabbedPage> 
+0

하나는 https를 구현하는 방법을 보려면 다음 구성 요소를 사용하거나 코드를 보면 /github.com/thrive-now/BottomNavigationBarXF –

+0

나는 그것을 조사했다, 그것은 안드로이드 bottomnavigationview를 사용하고 있지 않다, 그것에서 relativelayout와 버튼을 사용하고있다. – fluter

+0

사용자 정의하려는 렌더러는 무엇입니까? 이후 사용자 정의 렌더러의 모든 코드를 보지 못했지만'TabbedPageRenderer'를 시도하고있는 것처럼 보입니까? –

답변

1

설명에 따르면 나는가 필요하지 않다고 생각합니다.은 파편에 대해 BottomNavigationViewFrameLayout의보기 만 있으면됩니다. 그런 다음 ViewRenderer을 사용자 정의 할 수 있습니다.

첫째, 예를 들어 PCL에 View의 서브 클래스를 만들 :

public class BottomTabbedView:View 
{ 
} 

그런 다음 안드로이드 클라이언트 프로젝트에서의 렌더링을 구현합니다

[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/> 
+0

문제는 ContentPage 형식의 서브 페이지를 framelayout에 추가하여 큰보기의 일부로 표시 할 수있는 방법입니다. 페이지가 안드로이드 뷰가 아니기 때문에 AddView가 작동하지 않습니다. – fluter

+0

@fluter, yeah, 내 제안은 안드로이드 클라이언트 프로젝트의 다른 페이지에 대한 뷰와 함께 로직을 직접 완성했습니다. 그러나 네이티브 안드로이드 메소드'AddView'를 PCL에 노출시키는 방법을 알고 싶다면 나중에 대답을 업데이트 할 것입니다. –

+0

이 방법을 사용하면 iOS 및 UWP 프로젝트에 대한 맞춤 렌더러도 만들어야하지만 나머지 두 플랫폼의 네이티브 컨트롤이 제대로 작동하기 때문에 Android 만 사용자 정의하면됩니다. – fluter