Share via

How do I handle platform-specific UI customization in MAUI without bloating my shared code?

Trung Huynh 0 Reputation points
2026-03-06T07:03:31.1033333+00:00

I have been learning MAUI for a couple months now. I need to apply different styles or behaviors on Android vs. iOS (e.g., font sizes, padding, or custom renderers). I know about OnPlatform in XAML and the Platforms/ folder. What is the correct architectural approach to keep platform-specific code isolated while keeping the shared codebase clean?

Developer technologies | .NET | .NET MAUI
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Nancy Vo (WICLOUD CORPORATION) 880 Reputation points Microsoft External Staff Moderator
    2026-03-06T09:11:58.3333333+00:00

    Hi @Trung Huynh ,

    Thanks for reaching out.

    There isn’t only one correct approach, there are multiple ways. I recommend this order, from simple to complex:

    • For small tweaks like font size, padding, color or margin,... We use OnPlatform directly in XAML. For example:
    <Label FontSize="{OnPlatform Android=18, iOS=20, Default=16}" 
           Padding="{OnPlatform Android=10, iOS=15}" />
    

    This makes zero code pollution, stays declaritive.

    • For repeated styles or app-wide: create platform-specific ResourceDictionary files in Platforms/Android/Resources/Styles.xaml, then merge them conditionally in App.xaml.cs or via MergedDictionaries with #if directives. → Keeps shared XAML clean.
    • For complex logic, behaviors, custom rendering, native APIs,... We defined an interfacte in shared code. For ex: implement it in Platforms/Android/ and Platforms/iOS/ folders → Register via dependency injection in MauiProgram.cs.

    Hope this helps. If you found my response helpful or informative, I would greatly appreciate it if you could follow this guidance provide feedback. Thank you.


  2. Q&A Assist
    2026-03-06T07:03:49.5+00:00
    AI generated content. This question contains an answer created with AI from Q&A Assist. Learn more

    Use MAUI’s built‑in platform abstractions so that platform differences stay in XAML or small, well‑scoped platform files, while the rest of the app remains platform‑agnostic.

    Key patterns from the platform integration docs:

    1. Prefer OnPlatform / On in XAML for simple visual differences
      • For things like padding, margins, colors, sizes, or fonts, use OnPlatform<T> and On rather than #if blocks in code.
      • Example pattern (conceptually) for padding or other Thickness properties:
        • Define OnPlatform<Thickness> with x:TypeArguments="Thickness" and set Default plus per‑platform overrides.
        • Use the Platforms collection with On elements when you need more than just the simple markup extension.
      • This keeps layout and styling differences in XAML, not in shared C# logic.
    2. Use OnPlatform markup extension for concise XAML (when trimming/NativeAOT is not a concern)
      • For small, inline differences (e.g., color, width, height), use the OnPlatform markup extension:
             <BoxView Color="{OnPlatform Yellow, iOS=Red, Android=Green}"
                      WidthRequest="{OnPlatform 250, iOS=200, Android=300}"
                      HeightRequest="{OnPlatform 250, iOS=200, Android=300}" />
        
      • The extension exposes Default, Android, iOS, MacCatalyst, Tizen, and WinUI properties, so the shared XAML stays clean and declarative.
      • For apps using full trimming or NativeAOT, avoid the markup extension and use the OnPlatform<T> class instead to keep things trim‑safe.
    3. Use DeviceInfo.Platform in code‑behind or view models only when necessary
      • For behavior that must be decided in C#, use DeviceInfo.Platform and DevicePlatform to branch logic, but keep it localized:
             label.FontSize = DeviceInfo.Platform == DevicePlatform.iOS ? 20 :
                 DeviceInfo.Platform == DevicePlatform.Android ? 22 : 24;
        
      • Restrict this to UI‑centric code (e.g., view or UI service), not core business logic, so the domain layer remains platform‑agnostic.
    4. Use OnIdiom / OnIdiom<T> for idiom‑specific layout instead of platform checks
      • When differences are about device type (phone vs. desktop/tablet) rather than OS, use OnIdiom<T> or the OnIdiom markup extension.
      • This keeps idiom concerns separate from platform concerns and avoids scattering if (isTablet) logic.
    5. Keep platform‑specific implementation in platform projects or handlers, but expose platform‑neutral APIs
      • For deeper platform features (e.g., iOS‑only behaviors, custom handlers, or platform specifics like iOS Entry font auto‑shrink), encapsulate them behind a shared interface or helper in the shared project, and implement the platform details in the platform projects.
      • MAUI platform‑specifics (like those listed for iOS) are designed so that shared code calls a cross‑platform API, and the platform project provides the actual behavior.
    6. Architectural guideline to avoid bloat
      • Shared UI layer:
        • Use XAML with OnPlatform / OnIdiom and styles for visual differences.
        • Use DeviceInfo.Platform only in thin UI helpers when XAML is insufficient.
      • Platform layer:
        • Implement handlers, renderers, or platform‑specific services.
        • Keep these isolated in platform projects or in clearly named platform folders.
      • Core/business layer:
        • No platform checks; expose platform‑agnostic interfaces and models only.

    By concentrating platform differences in XAML (OnPlatform, OnIdiom) and in small, well‑defined platform services/handlers, the main shared codebase (view models, business logic, and most views) stays clean and platform‑neutral.


    References:

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.