片段中的ActionBar和工具栏

时间:2017-10-22 16:25:40

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

我正在努力获取片段子视图,以便在显示时考虑ActionBar / Toolbar。

我已经关注了来自here的示例,该示例非常精心地将布局划分为活动布局和包含AppBar / Toolbar的包含标签的片段,在我的例子中,还有浮动操作按钮(fab)。我重构了我已经运行的代码,在活动布局上使用AppBar / Toolbar和fab,只是片段在一个单独的布局中。但是在片段中包含AppBar / Toolbar和fab的方法使我能够拥有一个干净的活动,可以容纳任何片段,有或没有AppBar / Toolbar或fab(或任何其他UI元素)。下面是我的基本布局设置。我正在解决的问题是我的RecyclerView在Appbar / Toolbar上被隐藏了。

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="match_parent"
        android:layout_centerInParent="true" />

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

fragment_list.axml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    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" >

    <include
        layout="@layout/include_toolbar_actionbar" />

    <MvvmCross.Droid.Support.V4.MvxSwipeRefreshLayout
        android:id="@+id/listsRefresher"
        android:layout_width="match_parent"
        android:layout_height="match_parent"    
        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:MvxItemTemplate="@layout/item_list"
            app:MvxBind="ItemsSource Lists; ItemClick ShowListItemsCommand" />

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

    <include
        layout="@layout/include_floatingactionbutton" />

</FrameLayout>

include_toolbar_actionbar.axml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.AppBarLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    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>

include_floatingactionbutton.axml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.FloatingActionButton
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    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"        
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    app:layout_anchor="@id/main_content_frame"
    app:layout_anchorGravity="bottom|right|end" />

MainActivity.cs

namespace List.Mobile.Droid.Activities
{
    [Activity(
        Label = "@string/applicationName",
        Icon = "@drawable/ic_icon", 
        Theme = "@style/AppTheme.Default",
        LaunchMode = LaunchMode.SingleTop,
        ScreenOrientation = ScreenOrientation.Portrait,
        Name = "list.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();
        }
    }
}

ListsFragment.cs

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);

            var swipeToRefresh = FragmentView.FindViewById<MvxSwipeRefreshLayout>(Resource.Id.refresher);
            if (AppBar != null)
                AppBar.OffsetChanged += (sender, args) => swipeToRefresh.Enabled = args.VerticalOffset == 0;

            var listsRecyclerView = FragmentView.FindViewById<MvxRecyclerView>(Resource.Id.listsRecyclerView);
            ...    
            return FragmentView;
        }
   }
}

BaseFragment.cs

namespace List.Mobile.Droid.Views
{
    public abstract class BaseFragment<T> : MvxFragment<T> where T : MvxViewModel
    {    
        protected abstract int FragmentResourceId { get; }
        protected View FragmentView { get; set; }
        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);

            FragmentView = this.BindingInflate(FragmentResourceId, null);

            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);
            AppCompatActivity parentActivity = ((AppCompatActivity)Activity);
            parentActivity.SetSupportActionBar(Toolbar);
            parentActivity.SupportActionBar.SetDisplayHomeAsUpEnabled(false);
            parentActivity.SupportActionBar.SetHomeButtonEnabled(false);

            return view;
        }
    }
}

Obstructing AppBar/Toolbar

1 个答案:

答案 0 :(得分:0)

如果你结合了活动+片段+包含的布局结构,你会看到类似这样的东西:

CoordinatorLayout
--FrameLayout -> id=main_content_frame
----FrameLayout -> id=list_frame
------AppBarLayout
--------Toolbar
------SwipeRefresh
--------Recycler
------Fab

这意味着,你在FrameLayout中有工具栏和刷卡/回收器,而这一个在另一个之上就是预期的行为。

要解决此问题,您应该将AppBar + Swipe + Fab作为CoordinatorLayout的子项(这是正确处理工具栏/ Fab /滚动内容之间交互的布局。因此,将您的活动更改为{{{ 1}}并将片段重新排序为:

FrameLayout

并且不要忘记将CoordinatorLayout --AppBarLayout ----Toolbar --SwipeRefresh ----RecyclerView --Fab 添加到app:layout_behavior="@string/appbar_scrolling_view_behavior",以便协调员正确定位它。

相关问题