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

如何设置AutoCompleteTextView下拉框高度为距屏幕底部60dp?

Hey there! Let's tackle that AutoCompleteTextView dropdown height compatibility issue once and for all. Your current code works on the Huawei P9 Lite (Android 7.0) but breaks on other devices for a few key reasons: you're mixing up dp and pixel values, not accounting for system UI elements like status/navigation bars, and not waiting for the view to fully layout before calculating dimensions. Here's a robust, cross-device solution:

First, Fix the DP-to-Pixel Conversion

The setDropDownHeight() method expects a pixel value, but your original code calculates a dp value and passes it directly—this is a critical mistake. Let's start with a helper method to safely convert dp to pixels:

private int dpToPx(int dp) {
    return Math.round(dp * getResources().getDisplayMetrics().density);
}

Get the Real Available Screen Height

To avoid issues with status bars, navigation bars, or different Android versions, we need to calculate the actual usable screen space the app can access:

private int getAvailableScreenHeight() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        // Android 11+ uses WindowMetrics for accurate window bounds
        WindowMetrics windowMetrics = getWindowManager().getCurrentWindowMetrics();
        Insets insets = windowMetrics.getWindowInsets()
                .getInsetsIgnoringVisibility(WindowInsets.Type.systemBars());
        return windowMetrics.getBounds().height() - insets.top - insets.bottom;
    } else {
        // Legacy method for older Android versions
        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        return displayMetrics.heightPixels - getStatusBarHeight() - getNavigationBarHeight();
    }
}

// Helper to get status bar height
private int getStatusBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

// Helper to get navigation bar height (only if it exists)
private int getNavigationBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
    if (resourceId > 0 && hasNavigationBar()) {
        result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

// Check if navigation bar is present on the device
private boolean hasNavigationBar() {
    boolean hasNavBar = false;
    Resources res = getResources();
    int configId = res.getIdentifier("config_showNavigationBar", "bool", "android");
    if (configId > 0) {
        hasNavBar = res.getBoolean(configId);
    }
    // Override for emulator scenarios
    try {
        Class<?> systemProps = Class.forName("android.os.SystemProperties");
        Method getProp = systemProps.getMethod("get", String.class);
        String navOverride = (String) getProp.invoke(systemProps, "qemu.hw.mainkeys");
        if ("1".equals(navOverride)) hasNavBar = false;
        else if ("0".equals(navOverride)) hasNavBar = true;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return hasNavBar;
}

Set Dropdown Height Properly

If you want the dropdown's bottom edge to be 60dp above the screen bottom (regardless of where the AutoCompleteTextView is placed), use this:

int availableHeight = getAvailableScreenHeight();
int bottomMarginPx = dpToPx(60);
int dropdownHeight = availableHeight - bottomMarginPx;
edtSeach.setDropDownHeight(dropdownHeight);

Even Better: Account for the AutoCompleteTextView's Position

If you want the dropdown to expand from the bottom of the input field to 60dp above the screen bottom (the more common use case), use a ViewTreeObserver to wait for the view to finish layout before calculating:

edtSeach.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        // Remove the listener to avoid repeated calls
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            edtSeach.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        } else {
            edtSeach.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        }

        // Get the bottom position of the AutoCompleteTextView on screen
        int[] viewLocation = new int[2];
        edtSeach.getLocationOnScreen(viewLocation);
        int viewBottomY = viewLocation[1] + edtSeach.getHeight();

        // Get the screen's bottom edge (minus navigation bar)
        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        int screenBottomY = displayMetrics.heightPixels - getNavigationBarHeight();

        // Calculate maximum dropdown height
        int bottomMarginPx = dpToPx(60);
        int dropdownHeight = screenBottomY - viewBottomY - bottomMarginPx;

        // Ensure we don't set a negative height
        if (dropdownHeight > 0) {
            edtSeach.setDropDownHeight(dropdownHeight);
        }
    }
});

Why This Works Across All Devices

  • Correct unit conversion: No more mixing dp and pixels—every dimension is properly scaled for the device's screen density.
  • System UI awareness: We subtract status and navigation bar heights so the dropdown doesn't get hidden or overflow off-screen.
  • Layout safety: Using ViewTreeObserver ensures we only calculate dimensions after the view has fully rendered, avoiding incorrect values.
  • Version compatibility: We use modern APIs for Android 11+ and fallback to reliable legacy methods for older devices.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:32:24