You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin Android中如何通过继承复用DrawerLayout与NavigationView逻辑

How to Reuse DrawerLayout/NavigationView Logic in Xamarin.Android via Inheritance

Great question—redundant code is a pain, and inheritance is perfect here to centralize all that drawer navigation logic. Here's a step-by-step approach to clean up your code:

Step 1: Create an Abstract Base Drawer Activity

First, we'll build a base class that handles all the common DrawerLayout and NavigationView setup, navigation clicks, and toggle behavior. This class will be abstract since it's meant to be inherited, not instantiated directly.

using Android.App;
using Android.OS;
using Android.Support.Design.Widget;
using Android.Support.V4.Widget;
using Android.Support.V7.App;
using Android.Views;

public abstract class BaseDrawerActivity : AppCompatActivity
{
    private DrawerLayout _drawerLayout;
    private NavigationView _navigationView;
    private ActionBarDrawerToggle _drawerToggle;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        // Child activities will set their own content view first
    }

    // Call this method in child activities AFTER setting the content view
    protected void SetupDrawer()
    {
        // Reference views from the child activity's layout (ensure IDs match across all layouts!)
        _drawerLayout = FindViewById<DrawerLayout>(Resource.Id.drawer_layout);
        _navigationView = FindViewById<NavigationView>(Resource.Id.nav_view);

        // Setup the drawer toggle for the action bar
        _drawerToggle = new ActionBarDrawerToggle(
            this, 
            _drawerLayout, 
            Resource.String.drawer_open, // Add these strings to your Resources/values/strings.xml
            Resource.String.drawer_close
        );

        _drawerLayout.AddDrawerListener(_drawerToggle);
        _drawerToggle.SyncState();

        // Enable the hamburger menu icon in the action bar
        SupportActionBar.SetDisplayHomeAsUpEnabled(true);
        SupportActionBar.SetHomeButtonEnabled(true);

        // Attach the navigation item click listener
        _navigationView.NavigationItemSelected += OnNavigationItemSelected;

        // Let the child activity highlight the correct menu item
        HighlightCurrentMenuItem();
    }

    private void OnNavigationItemSelected(object sender, NavigationView.NavigationItemSelectedEventArgs e)
    {
        // Handle navigation clicks centrally
        switch (e.MenuItem.ItemId)
        {
            case Resource.Id.nav_main:
                if (!(this is MainActivity))
                {
                    StartActivity(new Intent(this, typeof(MainActivity)));
                    Finish(); // Prevent stacking multiple instances of the same activity
                }
                break;
            case Resource.Id.nav_settings:
                if (!(this is SettingsActivity))
                {
                    StartActivity(new Intent(this, typeof(SettingsActivity)));
                    Finish();
                }
                break;
            // Add more menu items here as your app grows
        }

        // Close the drawer after selection
        _drawerLayout.CloseDrawers();
    }

    // Abstract method: child activities must implement this to highlight their corresponding menu item
    protected abstract void HighlightCurrentMenuItem();

    // Handle the hamburger menu click
    public override bool OnOptionsItemSelected(IMenuItem item)
    {
        if (_drawerToggle.OnOptionsItemSelected(item))
        {
            return true;
        }
        return base.OnOptionsItemSelected(item);
    }

    // Sync the toggle state after configuration changes (e.g., screen rotation)
    protected override void OnPostCreate(Bundle savedInstanceState)
    {
        base.OnPostCreate(savedInstanceState);
        _drawerToggle.SyncState();
    }

    public override void OnConfigurationChanged(Android.Content.Res.Configuration newConfig)
    {
        base.OnConfigurationChanged(newConfig);
        _drawerToggle.OnConfigurationChanged(newConfig);
    }
}

Step 2: Update Your Child Activities

Now, modify MainActivity and SettingsActivity to inherit from BaseDrawerActivity instead of AppCompatActivity. They'll only need to handle their own layout and highlight the correct menu item:

MainActivity.cs

public class MainActivity : BaseDrawerActivity
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.Main); // Your existing Main layout

        // Initialize the drawer using the base class method
        SetupDrawer();

        // Add your MainActivity-specific logic here (e.g., binding data, setting up views)
    }

    protected override void HighlightCurrentMenuItem()
    {
        // Mark the "Main" menu item as selected
        _navigationView.Menu.FindItem(Resource.Id.nav_main).SetChecked(true);
    }
}

SettingsActivity.cs

public class SettingsActivity : BaseDrawerActivity
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.Settings); // Your existing Settings layout

        SetupDrawer();

        // Add your SettingsActivity-specific logic here
    }

    protected override void HighlightCurrentMenuItem()
    {
        // Mark the "Settings" menu item as selected
        _navigationView.Menu.FindItem(Resource.Id.nav_settings).SetChecked(true);
    }
}

Step 3: Ensure Consistent IDs Across Layouts

For this to work, make sure both your Main.axml and Settings.axml layouts use the same IDs for the DrawerLayout and NavigationView:

<!-- In both Main.axml and Settings.axml -->
<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_width="match_parent"
    android:layout_height="match_parent">

    <!-- Your main content layout here -->

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/nav_menu" /> <!-- Make sure this menu has the correct item IDs -->
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>

Also, your nav_menu.xml (in Resources/menu) should have items with the IDs we referenced in the base class:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/nav_main"
        android:title="Main" />
    <item
        android:id="@+id/nav_settings"
        android:title="Settings" />
</menu>

Key Notes

  • Abstract Method: The HighlightCurrentMenuItem abstract method ensures each child activity handles its own menu selection state, keeping the base class clean.
  • Prevent Duplicate Activities: The if (!(this is XActivity)) check avoids starting a new instance of the activity the user is already in.
  • Configuration Changes: The base class handles syncing the drawer toggle state after screen rotations, so you don't have to repeat that code.
  • Extensibility: If you add more activities later, you just add a new case to the base class's OnNavigationItemSelected method and create a new child activity inheriting from BaseDrawerActivity.

This approach eliminates all redundant drawer logic and keeps your code DRY (Don't Repeat Yourself).

内容的提问来源于stack exchange,提问作者lostsky25

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 14:32:53