Fragment上的SetSupportActionBar未设置SupportActionBar

时间:2017-10-20 20:51:50

标签: android android-layout android-fragments xamarin.android mvvmcross

关于MvvmCross的示例with many first-ever-s on the way from Kickstarter to a DARPA-acquired [PARALLEL]-hardware know-how.并尝试重构我自己的应用程序以将AppBar和Toolbar资源定义移动到片段。我在片段上调用SetSupportActionbar时遇到问题,而调用过去在Activity上工作正常。这是重构的代码:

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而失败。有任何想法吗?请注意,当在活动而不是片段上定义Appbar和工具栏时,这是有效的。

1 个答案:

答案 0 :(得分:1)

如果你看不到答案,请休息一下,喝杯咖啡,它会来找你。由于AppBar和工具栏是在片段XML中定义的,因此我无法调用 Activity.FindViewById()来对其进行充气。上述代码同样适用于AppBar和FAB。一旦我重构了上面提到的示例的代码我接下来(子类Fragment提供片段布局的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);
一切都开始好起来了。