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

.NET MAUI中如何绝对定位屏幕元素以实现自动完成控件

Great question! You're right that writing custom handlers for each platform is overkill for this scenario—luckily, .NET MAUI has a much simpler solution using Popups combined with element position calculations, no deprecated AbsoluteLayout required. Here's a step-by-step implementation that fits your Shell app needs:

Core Approach

We'll use MAUI's built-in Popup control (which floats above all other UI elements) and calculate its position relative to your input field, adjusting to screen space and keyboard state automatically. The popup will host your TableView for suggestions.

Step 1: Create a Custom Suggestion Popup

First, build a reusable popup that contains your TableView and handles selection events:

<?xml version="1.0" encoding="utf-8" ?>
<Popup xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       x:Class="YourApp.Views.AutoCompletePopup"
       Size="300, 200"
       BackgroundColor="White"
       CornerRadius="8"
       HasShadow="True">
    <TableView Intent="Menu">
        <TableRoot>
            <TableSection x:Name="SuggestionsSection" />
        </TableRoot>
    </TableView>
</Popup>

Code-behind for the popup:

public partial class AutoCompletePopup : Popup
{
    public event EventHandler<string> SuggestionSelected;

    public AutoCompletePopup(List<string> suggestions)
    {
        InitializeComponent();
        LoadSuggestions(suggestions);
    }

    private void LoadSuggestions(List<string> suggestions)
    {
        SuggestionsSection.Clear();
        foreach (var suggestion in suggestions)
        {
            var cell = new TextCell { Text = suggestion, TextColor = Colors.DarkSlateGray };
            cell.Tapped += (s, e) =>
            {
                SuggestionSelected?.Invoke(this, suggestion);
                Close();
            };
            SuggestionsSection.Add(cell);
        }
    }
}

Step 2: Add Input Field and Position Logic to Your Page

In your Shell page, add an Entry and handle its text change event to show/hide the popup and calculate the correct position:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:views="clr-namespace:YourApp.Views"
             x:Class="YourApp.Views.MainPage">
    <StackLayout Padding="20" Spacing="15">
        <Entry x:Name="AutoCompleteEntry" 
               Placeholder="Type to search..."
               TextChanged="AutoCompleteEntry_TextChanged"/>
        <!-- Rest of your page content -->
    </StackLayout>
</ContentPage>

Code-behind for position calculation and popup management:

private async void AutoCompleteEntry_TextChanged(object sender, TextChangedEventArgs e)
{
    var entry = sender as Entry;
    if (string.IsNullOrWhiteSpace(e.NewTextValue))
    {
        await CloseActivePopup();
        return;
    }

    // Replace with your actual suggestion fetch logic
    var suggestions = GetFilteredSuggestions(e.NewTextValue);
    if (!suggestions.Any())
    {
        await CloseActivePopup();
        return;
    }

    // Get the input field's screen coordinates
    var entryScreenRect = await entry.GetScreenCoordinatesAsync();
    var popup = new AutoCompletePopup(suggestions);
    
    // Handle selection to populate the input field
    popup.SuggestionSelected += (s, selectedText) => entry.Text = selectedText;

    // Calculate if there's enough space below the input field
    var screenHeight = DeviceDisplay.MainDisplayInfo.Height / DeviceDisplay.MainDisplayInfo.Density;
    var popupHeight = 200; // Match the popup's Size property
    var spaceBelow = screenHeight - entryScreenRect.Bottom;

    // Adjust for keyboard state (hide popup below keyboard if needed)
    bool showAboveEntry = spaceBelow < popupHeight || IsKeyboardOpen();

    // Show popup relative to the input field
    if (showAboveEntry)
    {
        // Align popup bottom with input field top
        await popup.ShowAsync(entry, PopupPosition.Top, new Point(0, -popupHeight));
    }
    else
    {
        // Align popup top with input field bottom
        await popup.ShowAsync(entry, PopupPosition.Bottom, new Point(0, 0));
    }
}

private List<string> GetFilteredSuggestions(string input)
{
    // Mock data - replace with your actual data source
    var allItems = new List<string> { "Apple", "Banana", "Cherry", "Date", "Elderberry", "Fig" };
    return allItems.Where(item => item.StartsWith(input, StringComparison.OrdinalIgnoreCase)).ToList();
}

private async Task CloseActivePopup()
{
    if (Application.Current.MainPage?.PopupNavigation.PopupStack.Any() ?? false)
    {
        await Application.Current.MainPage.PopupNavigation.PopAsync();
    }
}

// Helper to check if keyboard is open (platform-specific)
private bool IsKeyboardOpen()
{
#if ANDROID
    var imm = Android.App.Application.Context.GetSystemService(Android.Content.Context.InputMethodService) as Android.Views.InputMethods.InputMethodManager;
    return imm.IsAcceptingText;
#elif IOS
    return UIKit.UIKeyboard.FrameEnd.Height > 0;
#else
    return false;
#endif
}

Key Notes

  1. Popup Positioning: The ShowAsync method accepts an anchor element (your Entry) and position parameters, so you don't need to calculate absolute screen coordinates manually.
  2. Keyboard Adjustment: The IsKeyboardOpen helper ensures the popup doesn't get blocked by the on-screen keyboard. For cleaner code, you could wrap this in a dependency service instead of using platform-specific directives.
  3. Responsive Width: To make the popup match your input field's width, adjust the Popup.Size dynamically based on the entry's width, or tweak the X offset in ShowAsync.
  4. Shell Compatibility: MAUI Popups work seamlessly with Shell apps—they'll float above Shell navigation bars and content without layout conflicts.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 17:01:49