将微调器宽度设置为当前项目宽度

Posted

技术标签:

【中文标题】将微调器宽度设置为当前项目宽度【英文标题】:Set spinner width to current item width 【发布时间】:2017-02-21 22:12:58 【问题描述】:

默认情况下,微调器宽度设置为适合下拉列表中最大的项目,但我希望它与所选项目的宽度相同。

<android.widget.Spinner
    android:id="@+id/tab_spinner"
    android:layout_
    android:layout_
    android:entries="@array/countries" />

正如您在右侧图片中看到的那样,微调器太长了,因为列表中的项目很长。

如何将其调整为所选项目的宽度?

【问题讨论】:

【参考方案1】:

默认情况下,Spinner 将尝试测量您的一些下拉视图并使用找到的最大宽度。这发生在Spinner#measureContentWidth() 中,Spinnerprotected 方法在Spinner#onMeasure() 中调用。

解决此问题的一种方法是确保您的 SpinnerAdapter#getView() 方法始终使用 Spinner#getSelectedItemPosition() 作为其 position 参数。

我能想到两种可能的解决方案:

    使用包装适配器创建自定义微调器(我更喜欢这种解决方案) 或调整您的自定义适配器

1.使用包装适配器创建自定义微调器

确保在您的 xml 布局中使用它,而不是普通的 &lt;Spinner&gt;

注意DynamicWidthSpinner#getAdapter() 将返回WrapperSpinnerAdapter;使用其getBaseAdapter() 方法访问您的适配器。

public class DynamicWidthSpinner extends Spinner 

    public DynamicWidthSpinner(Context context) 
        super(context);
    

    public DynamicWidthSpinner(Context context, AttributeSet attrs) 
        super(context, attrs);
    

    public DynamicWidthSpinner(Context context, AttributeSet attrs, int defStyleAttr) 
        super(context, attrs, defStyleAttr);
    


    public void setAdapter(SpinnerAdapter adapter) 
        super.setAdapter(adapter != null ? new WrapperSpinnerAdapter(adapter) : null);
    


    public final class WrapperSpinnerAdapter implements SpinnerAdapter 

        private final SpinnerAdapter mBaseAdapter;


        public WrapperSpinnerAdapter(SpinnerAdapter baseAdapter) 
            mBaseAdapter = baseAdapter;
        


        public View getView(int position, View convertView, ViewGroup parent) 
            return mBaseAdapter.getView(getSelectedItemPosition(), convertView, parent);
        

        public final SpinnerAdapter getBaseAdapter() 
            return mBaseAdapter;
        

        public int getCount() 
            return mBaseAdapter.getCount();
        

        public View getDropDownView(int position, View convertView, ViewGroup parent) 
            return mBaseAdapter.getDropDownView(position, convertView, parent);
        

        public Object getItem(int position) 
            return mBaseAdapter.getItem(position);
        

        public long getItemId(int position) 
            return mBaseAdapter.getItemId(position);
        

        public int getItemViewType(int position) 
            return mBaseAdapter.getItemViewType(position);
        

        public int getViewTypeCount() 
            return mBaseAdapter.getViewTypeCount();
        

        public boolean hasStableIds() 
            return mBaseAdapter.hasStableIds();
        

        public boolean isEmpty() 
            return mBaseAdapter.isEmpty();
        

        public void registerDataSetObserver(DataSetObserver observer) 
            mBaseAdapter.registerDataSetObserver(observer);
        

        public void unregisterDataSetObserver(DataSetObserver observer) 
            mBaseAdapter.unregisterDataSetObserver(observer);
        
    

2.调整您的自定义适配器

注意getView() 中的parent 可能并不总是Spinner

private class SimpleSpinnerAdapter extends BaseAdapter 

    private LayoutInflater mInflater;
    private int mResource;


    public SimpleSpinnerAdapter(Context context, int resource) 
        mInflater = LayoutInflater.from(context);
        mResource = resource;
    


    @Override
    public View getView(int position, View convertView, ViewGroup parent) 
        return createViewFromResource(
                mInflater,
                ((Spinner) parent).getSelectedItemPosition(),
                convertView,
                parent,
                mResource);
    

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) 
        return createViewFromResource(
                mInflater,
                position,
                convertView,
                parent,
                mResource);
    

    protected View createViewFromResource(LayoutInflater inflater, int position, 
                                          View convertView, ViewGroup parent,
                                          int resource) 
        View view;
        if (convertView == null) 
            view = inflater.inflate(resource, parent, false);
         else 
            view = convertView;
        

        bindView(position, view);

        return view;
    

    protected void bindView(int position, View view) 
        // Bind your view.
    

    // getCount(), getItem(), and getItemId() methods.

【讨论】:

第一个选项是最灵活的一个 第一个选项对我不起作用。当我实现它时(我不得不针对 kotlin 和 getView 函数中的缺失代码对其进行调整)微调器不响应点击事件并且下拉箭头消失了。我将把我当前的代码放在下面的回复中。我正在使用自定义 TextView 作为微调器项 @jpmcosta 我把我的代码放在一个新的 SO 问题中:***.com/questions/56998198/…【参考方案2】:
  ViewGroup.LayoutParams spinnerLayoutParams = spinner.getLayoutParams();
    spinnerLayoutParams.width -= 1;
   spinner.setLayoutParams(spinnerLayoutParams);

在所选项目上执行此操作

【讨论】:

值“-1”是 MATCH_PARENT 。为什么会有帮助?【参考方案3】:

将微调器 XML 设置为:

android:layout_

为我工作。

【讨论】:

抱歉忘记发布我的代码,但它已经是这样了,对我没有任何改变......

以上是关于将微调器宽度设置为当前项目宽度的主要内容,如果未能解决你的问题,请参考以下文章

Android:减小微调器下拉框的宽度

在Android中动态改变微调器的宽度

将项目的高度设置为等于项目的宽度

操作栏列表导航宽度 - 换行内容

如何设置editView最小宽度? (安卓 2.2)

以编程方式设置微调器的选定项