【问题标题】:Android Spinner -- how to size to currently selected item?Android Spinner - 如何调整当前选定项目的大小?
【发布时间】:2022-02-09 19:07:24
【问题描述】:

似乎微调器的大小与其适配器中给定的最长项目一致。在大多数情况下,这是一种很好的行为,但在我的特定情况下是不可取的。

这可以关闭吗?通过查看源代码中的 Spinner.onMeasure(),我的猜测是否定的,但我想我会问。

【问题讨论】:

    标签: android android-spinner


    【解决方案1】:

    我现在通过子类化 Spinner 实现了这一点:

    public class SpinnerWrapContent extends IcsSpinner {
        private boolean inOnMeasure;
    
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {       
             inOnMeasure = true;
             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
             inOnMeasure = false;
        }
    
        public boolean isInOnMeasure() {
            return inOnMeasure;
        }
    }
    

    然后在我的 SpinnerAdapter 的 getView() 中,如果我从 onMeasure() 调用,我使用当前选择的位置:

        public View getView(int position, View convertView, ViewGroup parent) {
            View view;
    
            if (convertView != null)
                view = convertView;
            else {
                int fixedPosition = (spinner.isInOnMeasure() ? spinner.getSelectedItemPosition() : position);
    
                // Here create view for fixedPosition
            }
    
            return view;
        }
    

    【讨论】:

      【解决方案2】:

      这对我有用。重要的部分是这个。把上面的代码放在你的适配器上,并使用 selectedItemPosition 从对象数组中选择文本。

      int selectedItemPosition = position;
          if (parent instanceof AdapterView) {
              selectedItemPosition = ((AdapterView) parent)
                      .getSelectedItemPosition();
          }
      

      示例如下。

      public View getView(int position, View convertView, ViewGroup parent) {
          LayoutInflater inflater = getLayoutInflater();
          final View spinnerCell;
          if (convertView == null) {
              // if it's not recycled, inflate it from layout
              spinnerCell = inflater.inflate(R.layout.layout_spinner_cell, parent, false);
          } else {
              spinnerCell = convertView;
          }
          int selectedItemPosition = position;
          if (parent instanceof AdapterView) {
              selectedItemPosition = ((AdapterView) parent)
                      .getSelectedItemPosition();
          }
      
          TextView title = (TextView) spinnerCell.findViewById(R.id.spinnerTitle);
          title.setText(titles[selectedItemPosition]);
          return spinnerCell;
      }
      

      如果您需要解释,请点击此链接:http://coding-thoughts.blogspot.in/2013/11/help-my-spinner-is-too-wide.html

      【讨论】:

        【解决方案3】:

        如果有人正在寻找 Kotlin 答案,请按照以下方法进行。

        class DynamicSizeSpinner : androidx.appcompat.widget.AppCompatSpinner {
        
            var inOnMeasure = false
                private set
        
            constructor(context: Context) : super(context)
            constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
            constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
        
            override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
                inOnMeasure = true
                super.onMeasure(widthMeasureSpec, heightMeasureSpec)
                inOnMeasure = false
            }
        }
        
        class SpinnerArrayAdapter(context: Context,@LayoutRes layout: Int, val entries: List<String>) : ArrayAdapter<String>(context, layout, entries) {
        
            override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
                val selectedItemPosition = when (parent) {
                    is AdapterView<*> -> parent.selectedItemPosition
                    is DynamicSizeSpinner -> parent.selectedItemPosition
                    else -> position
                }
                return makeLayout(selectedItemPosition, convertView, parent, R.layout.simple_spinner_dropdown_item_custom)
            }
        
            override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
                return makeLayout(position, convertView, parent, R.layout.simple_spinner_dropdown_item_custom)
            }
        
            private fun makeLayout(position: Int, convertView: View?, parent: ViewGroup, layout: Int): View {
                val view = convertView ?: LayoutInflater.from(context).inflate(layout, parent, false)
                if (position != -1) {
                    (view as? TextView)?.text = entries[position]
                }
                return view
            }
        }
        

        使用 DynamicSizeSpinner,就像在 XML/JAVA/Kotlin 代码中使用默认的 Spinner

        P.S 不要忘记阅读original article

        【讨论】:

        • 你的DynamicSizeSpinner中不需要引入inOnMeasure,该字段不被SpinnerArrayAdapter使用
        【解决方案4】:

        如果您只想让 Spinner 更短,这很容易解决。

        通常你可以通过给它一个权重,或者设置它的 layout_width 和 layout_height 来改变任何视图的高度和宽度:

        <Spinner
            android:id="@+id/shortenedSpinner"
            android:layout_width="100dp"
            android:layout_height="50dp" />
        

        这将迫使微调器变短

        如果您希望下拉视图更短,那就不同了。 在这种情况下,我想您可以在微调器适配器的 getDropDownView() 方法中提供一个自定义行,该方法具有与上述相同的更改。

        【讨论】:

        • 您好,感谢您的回答,但我不想将微调器设为固定宽度。我希望它根据所选视图更改其大小,即 WRAP_CONTENT 效果。目前,onMeasure() 中的代码将其调整为适配器返回的最大 View。
        • 好的,每次选择时重置固定宽度怎么样。根据所选文本的宽度设置宽度。这可以通过使用stackoverflow.com/questions/7712712/… 中所述的画布字体测量来估计
        • 谢谢,我在下面回答了我自己的问题。
        【解决方案5】:

        这是更优雅的几乎单线解决方案:

        class ResizingArrayAdapter<T>(context: Context, @LayoutRes layoutResId: Int, @IdRes textViewResourceId: Int, objects: List<T>) :
            ArrayAdapter<T>(context, layoutResId, textViewResourceId, objects) {
        
            override fun getView(position: Int, convertView: View?, parent: ViewGroup): View =
                super.getView(if (parent is AdapterView<*>) parent.selectedItemPosition else position, convertView, parent)
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-08-14
          • 2011-07-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多