Fragment上的SetSupportActionBar未设置SupportActionBar

问题描述:

对于MvvmCross,下面的示例为Android-Support/Fragments,并试图重构我自己的应用程序以将AppBar和Toolbar资源定义移动到片段。我在调用SetSupportActionbar的时候遇到了问题,而这个调用在Activity上正常工作。下面是重构代码:Fragment上的SetSupportActionBar未设置SupportActionBar

activity_main.axml

<?xml version="1.0" encoding="utf-8"?> 
<android.support.design.widget.CoordinatorLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:id="@+id/main_coordinator_layout" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:fitsSystemWindows="true"> 

    <!-- Actual content of the screen --> 
    <FrameLayout 
     android:id="@+id/main_content_frame" 
     android:layout_width="match_parent" 
     android:layout_height="fill_parent" 
     android:layout_centerInParent="true" 
     android:layout_below="@+id/toolbar" 
     app:layout_behavior="@string/appbar_scrolling_view_behavior" /> 

</android.support.design.widget.CoordinatorLayout> 

MainActivity.cs

using Android.App; 
using Android.OS; 
using Android.Content.PM; 
using MvvmCross.Droid.Support.V7.AppCompat; 
using Mobile.Core.ViewModels; 

namespace Mobile.Droid.Activities 
{ 
    [Activity(
     Label = "@string/applicationName", 
     Icon = "@drawable/ic_icon", 
     Theme = "@style/AppTheme.Default", 
     LaunchMode = LaunchMode.SingleTop, 
     ScreenOrientation = ScreenOrientation.Portrait, 
     Name = "droid.mobile.activities.MainActivity")] 
    public class MainActivity : MvxAppCompatActivity<MainViewModel> 
    { 
     ...  
     protected override void OnCreate(Bundle savedInstanceState) 
     { 
      base.OnCreate(savedInstanceState); 

      SetContentView(Resource.Layout.activity_main); 

      ViewModel.ShowLists(); 
     } 
     .... 
    } 
} 

fragment_lists.axml

<?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:id="@+id/list_frame" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    app:layout_behavior="@string/appbar_scrolling_view_behavior"> 

    <android.support.design.widget.AppBarLayout 
     android:id="@+id/main_app_bar" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:theme="@style/AppTheme.ActionBar"> 

     <android.support.v7.widget.Toolbar 
      android:id="@+id/main_tool_bar" 
      android:layout_width="match_parent" 
      android:layout_height="?attr/actionBarSize" 
      android:background="?attr/colorPrimary" 
      app:popupTheme="@style/AppTheme.ToolBar" 
      app:layout_scrollFlags="scroll|enterAlways" /> 

    </android.support.design.widget.AppBarLayout> 

    <MvvmCross.Droid.Support.V4.MvxSwipeRefreshLayout 
     android:id="@+id/listsRefresher" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     app:layout_behavior="@string/appbar_scrolling_view_behavior" 
     app:MvxBind="Refreshing IsLoading; RefreshCommand ReloadCommand"> 

     <MvvmCross.Droid.Support.V7.RecyclerView.MvxRecyclerView 
      android:id="@+id/listsRecyclerView" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      app:layout_behavior="@string/appbar_scrolling_view_behavior" 
      app:MvxItemTemplate="@layout/item_list" 
      app:MvxBind="ItemsSource Lists; ItemClick ShowListItemsCommand" /> 

    </MvvmCross.Droid.Support.V4.MvxSwipeRefreshLayout> 

    <android.support.design.widget.FloatingActionButton 
     android:id="@+id/fab" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_gravity="bottom|right" 
     android:layout_margin="@dimen/margin_medium" 
     android:src="@drawable/ic_add_white_24dp" 
     android:visibility="invisible" 
     app:layout_behavior="@string/appbar_scrolling_view_behavior" 
     app:layout_anchor="@id/main_content_frame" 
     app:layout_anchorGravity="bottom|right|end" /> 

</RelativeLayout> 

ListsFragment.cs

using Android.OS; 
using Android.Views; 
using MvvmCross.Droid.Support.V4; 
using MvvmCross.Binding.Droid.BindingContext; 
using Android.Runtime; 
using List.Mobile.Droid.Common; 
using MvvmCross.Binding.BindingContext; 
using Android.Support.V4.View; 
using Android.Widget; 
using List.Mobile.Core.ViewModels; 
using MvvmCross.Droid.Support.V7.RecyclerView; 
using Android.Support.V7.Widget; 
using MvvmCross.Droid.Views.Attributes; 

namespace List.Mobile.Droid.Views 
{ 
    [MvxFragmentPresentation(typeof(MainViewModel), Resource.Id.main_content_frame, true)] 
    [Register("list.mobile.droid.views.ListsFragment")] 
    public class ListsFragment : BaseFragment<ListsViewModel>, ActionMode.ICallback 
    { 
     ...  
     public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
     { 
      base.OnCreateView(inflater, container, savedInstanceState); 
      ... 
     } 
    } 
} 

BaseFragment.cs

using MvvmCross.Droid.Support.V4; 
using List.Mobile.Droid.Common; 
using MvvmCross.Core.ViewModels; 
using Android.OS; 
using Android.Views; 
using Android.Support.Design.Widget; 
using Android.Support.V7.Widget; 
using Android.Support.V7.App; 

namespace List.Mobile.Droid.Views 
{ 
    public abstract class BaseFragment<T> : MvxFragment<T> where T : MvxViewModel 
    {  
     protected AppBarLayout AppBar { get; set; } 
     protected FloatingActionButton FAB { get; set; } 
     protected Toolbar Toolbar { get; set; } 

     public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
     { 
      var view = base.OnCreateView(inflater, container, savedInstanceState); 

      AppBar = Activity.FindViewById<AppBarLayout>(Resource.Id.main_app_bar); 
      FAB = Activity.FindViewById<FloatingActionButton>(Resource.Id.fab); 
      Toolbar = Activity.FindViewById<Toolbar>(Resource.Id.main_tool_bar); 
      AppCompatActivity parentActivity = ((AppCompatActivity)Activity); 
      parentActivity.SetSupportActionBar(Toolbar); 
      parentActivity.SupportActionBar.SetDisplayHomeAsUpEnabled(false); 
      parentActivity.SupportActionBar.SetHomeButtonEnabled(false); 

      return view; 
     } 
    } 
} 

问题是与线:

parentActivity.SetSupportActionBar(Toolbar); 

由于它似乎并没有操作栏和后续调用设置为parentActivity.SupportActionBar失败的NullReferenceException。有任何想法吗?请不要在AppBand和工具栏在Activity上而不是在Fragment上定义时工作。

如果你看不到答案,请休息一下,喝一杯咖啡,它会来找你。由于AppBar和工具栏是在XML片段中定义的,因此我无法调用Activity.FindViewById()来夸大它。上述代码同样适用于AppBar和FAB。一旦我重构的代码更靠近上述实施例I下面的(子级片段提供了片段布局的RESOURCEID和基类膨胀的话),我能够改变呼叫:

AppBar = Activity.FindViewById<AppBarLayout>(Resource.Id.main_app_bar); 
Fab = Activity.FindViewById<FloatingActionButton>(Resource.Id.fab); 
Toolbar = Activity.FindViewById<Toolbar>(Resource.Id.main_tool_bar); 

到:

AppBar = FragmentView.FindViewById<AppBarLayout>(Resource.Id.main_app_bar); 
Fab = FragmentView.FindViewById<FloatingActionButton>(Resource.Id.fab); 
Toolbar = FragmentView.FindViewById<Toolbar>(Resource.Id.main_tool_bar); 

其中:

FragmentView = this.BindingInflate(FragmentResourceId, null); 

一切开始工作得很好。