ActionBar

时间:2018-02-16 21:19:59

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

我正在尝试实现从抽屉菜单调用的设置视图。

使用从MvxPreferenceFragmentCompat继承的Fragment实现设置视图。代码如下:

[MvxFragmentPresentation(typeof(MainViewModel), Resource.Id.main_content_frame)]
[Register(nameof(SettingsFragment))]
public class SettingsFragment : MvxPreferenceFragmentCompat<SettingsViewModel> 
{
    public override void OnCreatePreferences(Bundle savedInstanceState, string rootKey)
    {
        SetPreferencesFromResource(Resource.Xml.preferences, rootKey);
    }
}

我的preferences.xml如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory
        android:title="@string/pref_debug_info_title"
        android:key="pref_key_debug_info">
        <CheckBoxPreference
            android:key="pref_key_provide_debug_info"
            android:title="@string/pref_title_provide_debug_info"
            android:summary="@string/pref_summary_provide_debug_info"
            android:defaultValue="false" />
        <CheckBoxPreference
            android:key="pref_key_provide_debug_info_over_wifi"
            android:title="@string/pref_title_debug_info_over_wifi"
            android:summary="@string/pref_summary_debug_info_over_wifi"
            android:defaultValue="true" />
    </PreferenceCategory>
</PreferenceScreen>

片段布局如下:

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

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

    <fragment
        android:name="SettingsFragment"
        android:id="@+id/settings_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

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

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

最后,主要活动XML在这里:

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

    <FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/main_content_frame"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true" />

    <FrameLayout
      android:id="@+id/navigation_frame"
      android:layout_height="match_parent"
      android:layout_width="wrap_content"
      android:layout_gravity="left|start" />

</android.support.v4.widget.DrawerLayout>

我的偏好显示正常,但我没有看到带有标题的AppBar(我可以设置),并且没有箭头导航回活动。当我按下后面的&#34;硬件按钮&#34;一旦,没有任何反应。当我第二次按它时,应用程序&#34;最小化&#34;当我把它带回来时,我又回到了主要的活动中。

我已经使用&#34;常规&#34;片段继承自MvxFragment但似乎我无法使用MvxPreferenceFragmentCompat这样做。

更新1

根据Trevor的输入,我更新了fragment_settings.xml和SettingsFragment.cs,如下所示:

fragment_settings.xml

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

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

    <!-- Required ViewGroup for PreferenceFragmentCompat -->
    <FrameLayout
        android:id="@android:id/list_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        local:layout_behavior="@string/appbar_scrolling_view_behavior"/>

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

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

SettingsFragment.cs

[MvxFragmentPresentation(typeof(MainViewModel), Resource.Id.main_content_frame)]
[Register(nameof(SettingsFragment))]
public class SettingsFragment : MvxPreferenceFragmentCompat<SettingsViewModel>, View.IOnClickListener
{
    #region properties

    protected Toolbar Toolbar { get; set; }
    protected AppCompatActivity ParentActivity { get; set; }

    #endregion

    #region Fragment lifecycle overrides

    public override void OnCreatePreferences(Bundle savedInstanceState, string rootKey)
    {
        AddPreferencesFromResource(Resource.Xml.preferences);
    }

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

        ParentActivity = ((MainActivity)Activity);

        Toolbar = view.FindViewById<Toolbar>(Resource.Id.main_tool_bar);
        ParentActivity.SetSupportActionBar(Toolbar);
        ParentActivity.SupportActionBar.SetDisplayHomeAsUpEnabled(true);
        ParentActivity.SupportActionBar.SetDisplayShowHomeEnabled(true);

        ...

        // TODO: Pull it from a resource
        Toolbar.Title = Resources.GetText(Resource.String.settings_view_title);

        return view;
    }

    #endregion

    #region View.IOnClickListener implementation

    public void OnClick(View v)
    {
        ParentActivity.OnBackPressed(); 
    }

    #endregion
}

但是我仍然在线获取ParentActivity.SupportActionBar.SetDisplayHomeAsUpEnabled(true),因为我的SupportActionBar为空(但工具栏不是)。怎么样?

更新2

好的,我进一步了。我拿回了AppBar和箭头,外观和感觉就像我预料的那样。还有一个问题,但下面还有更多。

有什么帮助? This post

简而言之,我需要为我的偏好声明一个自定义样式,并在其中引用我的首选项视图的布局。这是一点:

Styles.xml

<style name="AppTheme.Base" parent="Theme.AppCompat.Light.NoActionBar">
    ...
    <item name="preferenceTheme">@style/AppTheme.Preference</item>
</style>

<!-- Custom Preference Theme -->
<style name="AppTheme.Preference"
       parent="@style/PreferenceThemeOverlay.v14.Material">
    <item name="preferenceFragmentCompatStyle">
        @style/AppPreferenceFragmentCompatStyle
    </item>
</style>

<!-- Custom Style for PreferenceFragmentCompat -->
<style name="AppPreferenceFragmentCompatStyle"
        parent="@style/PreferenceFragment.Material">
    <item name="android:layout">@layout/fragment_settings</item>
</style>

对我来说,这是SettingsFragment中的视图声明和布局资源之间缺少的链接。

剩下的唯一问题是能够从此片段返回到主要活动。来自&#34;常规&#34; MvxFragment(从抽屉调用),我使用IOnClickListener的OnClick方法来调用ParentActivity.OnBackPressed()。

SettingsFragment.cs

public class SettingsFragment : MvxPreferenceFragmentCompat<SettingsViewModel>, View.IOnClickListener
{
    ...
    public void OnClick(View v)
    {            
        ParentActivity.OnBackPressed(); 
    }
}

但这不适用于此MvxPreferenceFragmentCompat。仍在寻找答案。

更新3

最后一个难题是该类顶部的AddToBackStack声明,如下所示。一旦到位,OnBackPressed()就能正常工作。

SettingsFragment.cs

[MvxFragmentPresentation(typeof(MainViewModel), Resource.Id.main_content_frame, AddToBackStack = true)]
[Register(nameof(SettingsFragment))]
public class SettingsFragment : MvxPreferenceFragmentCompat<SettingsViewModel>, View.IOnClickListener

1 个答案:

答案 0 :(得分:0)

您缺少一些设置AppCompatActivity.SupportActionBar的代码,就像您在其他任何片段中一样。以下是我解决问题的方法:

以下是SettingsFragment布局:

<?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"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/coordinator"
  android:layout_height="match_parent"
  android:layout_width="match_parent"
  android:fitsSystemWindows="true"
  tools:context=".Activities.MainActivity">
  <include
    layout="@layout/toolbar_actionbar" />
  <!-- Required ViewGroup for PreferenceFragmentCompat -->
  <FrameLayout
    android:id="@android:id/list_container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>

以下是SettingsFragment实施:

public class SettingsFragment : MvxPreferenceFragmentCompat<SettingsViewModel>,
    View.IOnClickListener
{
    private Toolbar _toolbar;
    private View _view;

    private MainActivity MainActivity => (MainActivity)Activity;

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        // Since the view is created in PreferenceFragmentCompat's OnCreateView we don't use BindingInflate like a typical MvxFragment.
        _view = base.OnCreateView(inflater, container, savedInstanceState);

        // TODO: Setup MvvmCross Databinding manually since we didn't use BindingInflate like a typical MvxFragment.

        _toolbar = _view.FindViewById<Toolbar>(Resource.Id.toolbar);
        if (_toolbar != null)
        {
            MainActivity.SetSupportActionBar(_toolbar);
            MainActivity.SupportActionBar.SetDisplayHomeAsUpEnabled(true);
            MainActivity.SupportActionBar.SetDisplayShowHomeEnabled(true);
            _toolbar.SetNavigationOnClickListener(this);

            // TODO: Bind the Toolbar.Title
        }
        return _view;
    }

    public override void OnCreatePreferences(Bundle savedInstanceState, string rootKey)
    {
        AddPreferencesFromResource(Resource.Xml.preferences);
    }

    public async void OnClick(View v)
    {
        // Toolbar was clicked
        await ViewModel.CloseCommand.ExecuteAsync().ConfigureAwait(false);
    }
}