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

Xamarin Android自定义可滚动Spinner:限制下拉项显示数量求助

嘿,我来帮你搞定这个Xamarin Android自定义Spinner的需求!要实现下拉框最多显示3-4个选项、其余通过滚动查看的效果,核心是控制Spinner内部下拉弹出窗口的高度。下面是一套完整的实现方案,适配你的CompoundCodeView类:

自定义Spinner实现代码
using Android.Content;
using Android.Runtime;
using Android.Widget;
using Android.Util;
using System.Reflection;

namespace YourNamespace // 替换成你的命名空间
{
    public class CompoundCodeView : Spinner
    {
        private ListPopupWindow _popupWindow;
        // 可以在这里修改最多显示的选项数量,比如3或4
        private int _maxVisibleItems = 4;

        public CompoundCodeView(Context context) : base(context)
        {
            Initialize();
        }

        public CompoundCodeView(Context context, IAttributeSet attrs) : base(context, attrs)
        {
            Initialize();
        }

        public CompoundCodeView(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
        {
            Initialize();
        }

        public CompoundCodeView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
        {
            Initialize();
        }

        private void Initialize()
        {
            // 这里可以添加你的初始化逻辑,比如设置默认样式等
        }

        public override void OnAttachedToWindow()
        {
            base.OnAttachedToWindow();
            // 通过反射获取Spinner内部的ListPopupWindow(原生Android控件的内部字段)
            var popupField = typeof(Spinner).GetField("mPopup", BindingFlags.NonPublic | BindingFlags.Instance);
            _popupWindow = popupField?.GetValue(this) as ListPopupWindow;
            
            if (_popupWindow != null)
            {
                // 计算并设置弹出窗口的高度
                _popupWindow.SetHeight(CalculatePopupHeight());
            }
        }

        /// <summary>
        /// 计算下拉弹出窗口的高度:最多显示_maxVisibleItems个选项
        /// </summary>
        private int CalculatePopupHeight()
        {
            if (Adapter == null || Adapter.Count == 0)
                return MeasuredHeight;

            // 获取单个选项的高度(以第一个item为基准,建议所有item高度一致)
            var itemView = Adapter.GetView(0, null, this);
            itemView.Measure(
                MeasureSpec.MakeMeasureSpec(Width, MeasureSpecMode.Exactly),
                MeasureSpec.MakeMeasureSpec(0, MeasureSpecMode.Unspecified)
            );
            int singleItemHeight = itemView.MeasuredHeight;

            // 计算分隔线高度(默认1dp,转换为像素)
            int dividerHeight = (int)TypedValue.ApplyDimension(
                ComplexUnitType.Dip, 
                1, 
                Context.Resources.DisplayMetrics
            );

            // 计算总高度:如果选项总数少于最大显示数,用实际数量计算
            int itemCount = Adapter.Count < _maxVisibleItems ? Adapter.Count : _maxVisibleItems;
            int totalHeight = itemCount * singleItemHeight + (itemCount - 1) * dividerHeight;

            return totalHeight;
        }

        /// <summary>
        /// 当Adapter更新时,重新计算弹出窗口高度
        /// </summary>
        public override void SetAdapter(ISpinnerAdapter adapter)
        {
            base.SetAdapter(adapter);
            if (_popupWindow != null)
            {
                _popupWindow.SetHeight(CalculatePopupHeight());
            }
        }
    }
}
关键逻辑说明
  • 获取内部PopupWindow:通过反射拿到Spinner原生控件里的mPopup字段(这是Android系统用来展示下拉选项的ListPopupWindow实例),因为Xamarin没有公开这个API,所以用反射是最直接的方式。
  • 计算弹出高度:先获取单个选项的高度,再根据你设置的_maxVisibleItems计算总高度,同时考虑分隔线的高度。如果选项总数少于最大显示数,自动适配实际数量。
  • 动态更新高度:在SetAdapter方法里重新计算高度,确保当选项列表变化时,弹出窗口的高度也会同步更新。
使用方式
  1. 在你的布局XML中直接引用自定义Spinner:
<yournamespace.CompoundCodeView
    android:id="@+id/compoundCodeSpinner"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
  1. 在代码中设置Adapter(和普通Spinner用法一样):
var spinner = FindViewById<CompoundCodeView>(Resource.Id.compoundCodeSpinner);
var options = new List<string> { "选项1", "选项2", "选项3", "选项4", "选项5", "选项6", "选项7", "选项8", "选项9", "选项10" };
var adapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleSpinnerDropDownItem, options);
spinner.Adapter = adapter;
注意事项
  • 如果你的选项item布局高度不一致,CalculatePopupHeight里用第一个item的高度可能会有偏差,建议统一所有item的高度,或者遍历几个item取平均高度。
  • 反射的mPopup字段是Android原生Spinner的内部字段,目前在主流Android版本中都是稳定的,若后续系统版本有变动,可能需要调整字段名(不过这种情况很少见)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:59:42