【问题标题】:How to limit the height of Spinner drop down view in Android如何在 Android 中限制 Spinner 下拉视图的高度
【发布时间】:2014-01-03 01:21:26
【问题描述】:

请建议我用来创建它的任何方法。

查询:我正在创建 2-Spinner 视图,我必须在其中添加国家/城市列表,所以如果我选择印度,那么我会在下拉视图中获得 50 个项目,问题这是因为它占用了整个页面的高度。

我想要什么:我想创建一个下拉视图,用户只能在其中看到 10 个项目 下拉视图,只要用户滚动下拉视图,就会显示其他项目。


【问题讨论】:

  • 你应该使用自定义的 PopupWindow。
  • 谢谢,@TheLittleNaruto,它有效,解决了我的问题。
  • 借助 shlee1 的回答,我解决了我的问题。不知道确切原因,但这种方法在我的默认微调器中不起作用。我创建了一个自定义微调器和扩展微调器类,并使用了 shlee1 的答案。它对我有用。
  • @TusharPandey:嗨 Tushar,我也面临同样的问题,但您接受的答案不适用于 api 级别 5.0...您对此有什么解决方案吗?
  • 使用我在底部添加的答案。

标签: android android-layout android-spinner


【解决方案1】:

您可以使用反射。

    Spinner spinner = (Spinner) findViewById(R.id.spinner);
    try {
        Field popup = Spinner.class.getDeclaredField("mPopup");
        popup.setAccessible(true);

        // Get private mPopup member variable and try cast to ListPopupWindow
        android.widget.ListPopupWindow popupWindow = (android.widget.ListPopupWindow) popup.get(spinner);

        // Set popupWindow height to 500px
        popupWindow.setHeight(500);
    }
    catch (NoClassDefFoundError | ClassCastException | NoSuchFieldException | IllegalAccessException e) {
        // silently fail...
    }

【讨论】:

  • 请同时解释源代码的重要部分,以改进您的答案并使其更有用。
  • 抛出异常 java.lang.ClassCastException: android.widget.Spinner$DropdownPopup 无法转换为 android.support.v7.widget.ListPopupWindow
  • 对我不起作用,虽然代码调试和运行没有异常,但弹出高度没有改变
  • 这对我不起作用,因为它会引发静默异常....这里的其他人请帮助我...
  • 是的,这只适用于java项目,不适用于kotlin。我被困了3天,有人可以给我一个正确的答案
【解决方案2】:

您还可以通过继承Spinner 并覆盖android.widget.PopupWindow 用于计算的getWindowVisibleDisplayFrame(Rect outRect) 来影响下拉视图的位置和大小。只需设置outRect 以限制可以显示下拉视图的区域。

这种方法当然不适合所有场景,因为有时您希望放置下拉视图,以免遮挡另一个视图或仅在“实例外部”已知的其他条件。

就我而言,我需要将FLAG_LAYOUT_NO_LIMITS 标志应用于我的活动窗口,这导致outRect 很大,因此有时下拉视图的一部分隐藏在导航栏后面。为了恢复原始行为,我使用了以下覆盖:

@Override
public void getWindowVisibleDisplayFrame(Rect outRect) {
    WindowManager wm = (WindowManager) getContext.getSystemService(Context.WINDOW_SERVICE);
    Display d = wm.getDefaultDisplay();
    d.getRectSize(outRect);
    outRect.set(outRect.left, <STATUS BAR HEIGHT>, outRect.right, outRect.bottom);
}

【讨论】:

  • 你解决了我的问题,伙计。我还必须使状态栏完全透明
  • 几乎可以在所有设备上运行,但我无法让它在 Galaxy S3 4.4.4 Kitkat 上运行。 Kitkat 完全忽略了 getWindowVisibleDisplayFrame 的结果。也试过上面的反射解决方案,也没有用。有人有解释/解决方案吗?
  • 它在嵌套滚动视图中单击微调器时上升
  • getWindowVisibleDisplayFrame 方法没有被调用。
【解决方案3】:

截至 2021 年,我将使用:Exposed Dropdown Menus 并在 AutoCompleteTextView 内部使用以下内容:

android:dropDownHeight="300dp"

如果您不知道这一切是什么,请开始探索:Menu-Display & Menu-Documentation

【讨论】:

  • 它说限制微调器的高度。这适用于 AutoCompleteTextview 但不适用于微调器。
  • 谢谢。我从来不知道Exposed Dropdown Menus
【解决方案4】:

为此,我按照@theLittleNaruto 的建议在评论部分创建了自己的 PopUpWindow。

ma​​in.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content"> 

    <Button 
        android:layout_marginTop="80dp"
        android:id="@+id/btn"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"
        android:text="Country"
        android:layout_gravity="center_vertical|center_horizontal"/>
</LinearLayout>

popup_example.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="10dip" >

    <ListView 
        android:id="@+id/lstview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

</LinearLayout>

showpopup_1.java

package com.example.spinnerworking;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.PopupWindow.OnDismissListener;
import android.widget.Toast;

public class showpopup_1 extends Activity {

    boolean click = true ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);
        final LayoutInflater inflater = (LayoutInflater) this
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        final Button b = (Button) findViewById(R.id.btn);
        final View pview = inflater.inflate(R.layout.popup_example,
                (ViewGroup) findViewById(R.layout.main));
        final PopupWindow pw = new PopupWindow(pview);
        Log.i("hello", "hello") ;

        b.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                if (click) {
                    // if onclick written here, it gives null pointer exception.
                    // if onclick is written here it gives runtime exception.
                    pw.showAtLocation(v, Gravity.CENTER_HORIZONTAL, 0, 0);
                    pw.update(8, 0, 150, 200);
                    String[] array = new String[] { "tushar", "pandey",
                            "almora" };

                    ListView lst = (ListView) pview.findViewById(R.id.lstview);
                    adapterHello adapter = new adapterHello(showpopup_1.this);
                    lst.setAdapter(adapter);
                    lst.setOnItemClickListener(new OnItemClickListener() {
                        @Override
                        public void onItemClick(AdapterView<?> arg0, View arg1,
                                int arg2, long arg3) {
                            Toast.makeText(showpopup_1.this, "pandey",
                                    Toast.LENGTH_SHORT).show();
                        }

                    });
                    click = false ;
                }
                else
                {
                    pw.dismiss();
                    click = true;
                }

            }
        });
    }
}

class adapterHello extends BaseAdapter {
    String array[] = new String[] { "tushar", "pandey", "almora", "hello",
            "tushar", "pandey", "almora", "hello", "tushar", "pandey",
            "almora", "hello" };

    showpopup_1 context;

    public adapterHello(showpopup_1 context) {
        this.context = context;
    }

    public int getCount() {
        // TODO Auto-generated method stub
        return array.length;
    }

    @Override
    public Object getItem(int arg0) {
        // TODO Auto-generated method stub
        return arg0;
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        TextView text = new TextView(context);
        text.setHeight(30);
        text.setPadding(10, 8, 0, 0);
        text.setTextColor(Color.BLACK);
        text.setText(array[position]);
        text.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Log.i("clicked", "tushar");
            }
        });
        return text;
    }

}

【讨论】:

    【解决方案5】:
    1. android:popupBackground="#00000000" 添加到微调器
    2. 在适配器中

    getDropDownView();
    parentParams = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, (int) Utils.convertDpToPx(350));
    parentParams.gravity = Gravity.BOTTOM;
    parent.setLayoutParams(parentParams);
    
    1. 您可以通过添加android:dropDownVerticalOffset="60dp" 来移动弹出窗口

    【讨论】:

    • 什么是“getDropDownView”,什么是“父”?
    • 谁能更详细地解释上面的代码...??
    【解决方案6】:

    您可以使用这个很棒的库MaterialSpinner,它将为您完成所有艰苦的工作。

    下载: implementation 'com.jaredrummler:material-spinner:1.3.1'

    文件名.xml

    <com.jaredrummler.materialspinner.MaterialSpinner
    android:id="@+id/spinner"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:ms_dropdown_max_height="400dp"/>
    

    使用app:ms_dropdown_max_height="400dp"设置高度

    【讨论】:

    • 它也不适合我。在 Redmi 设备上测试。
    【解决方案7】:

    我认为问题是 Spinner is not scrolling 。 就我而言: 由于在我的活动窗口中使用了 FLAG_LAYOUT_NO_LIMITS 标志,微调器无法正常工作。为了恢复原始行为,我使用了相同的解决方案

    @Override public void getWindowVisibleDisplayFrame(Rect outRect) { WindowManager wm = (WindowManager) getContext.getSystemService(Context.WINDOW_SERVICE); Display d = wm.getDefaultDisplay(); d.getRectSize(outRect); outRect.set(outRect.left, &lt;STATUS BAR HEIGHT&gt;, outRect.right, outRect.bottom); }

    如果您仍然遇到无法滚动微调器项目的问题。 使用最佳解决方案的材料微调器,您可以自定义微调器高度。

    在您的 build.gradle 文件中插入: 实现 'com.jaredrummler:material-spinner:1.3.1'

    在你的 xml 中:

    `       <com.jaredrummler.materialspinner.MaterialSpinner
            android:id="@+id/spinner"
            android:layout_width="145dp"
            android:background="@drawable/button_next"
            android:layout_height="wrap_content"
            android:layout_marginLeft="150dp"
            app:ms_text_color="@color/black"
            appms_padding_left="100dp"
            android:layout_marginTop="-40dp"
            app:ms_dropdown_max_height="300dp"
            tools:ignore="MissingConstraints" />`
    

    `在java中 final MaterialSpinner spinner = (MaterialSpinner) findViewById(R.id.spinner);

    【讨论】:

      猜你喜欢
      • 2010-12-27
      • 2017-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-11
      • 2015-07-28
      相关资源
      最近更新 更多