I have found some threads about this issue, but no solution works in my case. I just want to set the height of the spinner popup e.g. to 200dp, or to limit the displayed items in dropdown popup and make it scrollable.
mainactivity.xml:
<FrameLayout
android:id="#+id/frame1"
android:layout_below="#+id/contact_form_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="#drawable/custom_spn_background">
<Spinner
android:id="#+id/spinner1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:dropDownSelector="#color/colorAccent"
android:popupBackground="#drawable/custombg"
style="#style/Myspinner"
android:layout_margin="5dp"
android:gravity="center_vertical"
android:spinnerMode="dropdown"/>
</FrameLayout>
my_spinnerlist.xml
<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:singleLine="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:gravity="start"
android:textColor="#000000"
android:paddingTop="2dip"
android:paddingBottom="2dip"
android:ellipsize="marquee"/>
spinner_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:gravity="center_vertical"
android:textColor="#000000"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:paddingTop="2dp"
android:paddingBottom="4dp"
android:textStyle="normal"
/>
MainActivity.java:
final Spinner sp1 = findViewById(R.id.spinner1);
String[] arrayItems = myList.categories;
ArrayAdapter<String> adp1 = new ArrayAdapter<>(this, R.layout.spinner_item, arrayItems);
adp1.setDropDownViewResource(R.layout.my_spinnerlist);
sp1.setAdapter(adp1);
sp1.setSelected(false);
sp1.setSelection(0, true);
sp1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int position, long id) {
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
I tried to set 200dp height in all spinner related XML layout files, but it affects only the item height, not the whole popup. I also tried a suggested solution from here with Reflection, example:
Spinner spinner = (Spinner) findViewById(R.id.spinner);
try {
Field popup = Spinner.class.getDeclaredField("mPopup");
popup.setAccessible(true);
android.widget.ListPopupWindow popupWindow = (android.widget.ListPopupWindow) popup.get(spinner);
popupWindow.setHeight(200);
}
catch (NoClassDefFoundError | ClassCastException | NoSuchFieldException | IllegalAccessException e) {
}
but this did not change the height of the dropdown list and also I have a warning : Reflective access to mPopup, which is not part of the public SDK and therefore likely to change in future Android releases.
I also tried to set <item name="android:dropDownHeight">200dp</item> in Myspinner style in styles file, but it did not affect the height.
I really don't have any solution for this. I have a list of 50 items in my dropdown and it overlaps the whole display area of my device.
Ok, the only solution that works for me is to use third party MaterialSpinner library. Maybe it will be useful also for others as there is no native way to change the dropdown height.
Just to implement: implementation 'com.jaredrummler:material-spinner:1.3.1'
The spinner.xml:
<com.jaredrummler.materialspinner.MaterialSpinner
android:id="#+id/spinner1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:ms_dropdown_max_height="200dp"
android:dropDownSelector="#color/colorAccent"
android:popupBackground="#drawable/custombg"
style="#style/Myspinner"
android:layout_margin="5dp"
android:gravity="center_vertical"
android:spinnerMode="dropdown"/>
Java code:
final MaterialSpinner sp1 = (MaterialSpinner) findViewById(R.id.spinner1);
String[] arrayItems = myList.categories;
ArrayAdapter<String> adp1 = new ArrayAdapter<>(this, R.layout.spinner_item, arrayItems);
adp1.setDropDownViewResource(R.layout.my_spinnerlist);
sp1.setAdapter(adp1);
sp1.setSelected(false);
sp1.setOnItemSelectedListener(new MaterialSpinner.OnItemSelectedListener() {
#Override
public void onItemSelected(MaterialSpinner view, int position, long id, Object item) {
}
} );
Works like a charm, see the app:ms_dropdown_max_height="200dp" in XML file.
Related
I am making a dropdown menu (spinner) inside a fragment. I also need that page to have a Recyclerview that extends and scrolls with the page, so I use the nested scroll view. Java Code:
Spinner dropdown = root.findViewById(R.id.dropdown);
ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(),android.R.layout.simple_spinner_dropdown_item,arrayList);
adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item );
dropdown.setAdapter(adapter);
dropdown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(getContext(),parent.getItemAtPosition(position).toString(),Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
Xml Code:
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:paddingBottom="65dp"
tools:context=".ui.dashboard.ShelvesFragment">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Spinner
android:id="#+id/dropdown"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#color/honeyBright"
android:textColor="#545454"
android:spinnerMode="dropdown"
android:layout_margin="15dp"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/shelves"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.core.widget.NestedScrollView>
When I run this code it just shows this as the drowpdown: Dropdown Spinner Image
It did work when I used the R.array value and the CharSequence Adapter, but I need it to be an array list and I'm not sure the exact code I used then.
Edit:
I figured out that the ArrayList actually didn't have any items in it, that was why it wasn't showing up. So I just fixed that and it worked fine.
I'm trying to integrate a Spinner into my Layout (it was working well before AndroidX migration).
here is the code:
Spinner spinner_nationalite;
String[] data_nationalite = {"","Française","Suisse","Belge","Allemande"};
#Override
public void onCreate(Bundle savedInstanceState) {
....
spinner_nationalite = (Spinner) findViewById(R.id.update_spinner_nationalite);
ArrayAdapter adapter_nationalite = new ArrayAdapter<String>(this, R.layout.spinner_dropdown_item, data_nationalite);
adapter_nationalite.setDropDownViewResource(R.layout.spinner_dropdown_item);
spinner_nationalite.setAdapter(adapter_nationalite);
spinner_nationalite.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
Log.d("KAIROSAPP","Nationalite selected: "+data_nationalite[i]);
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
Here is the spinner_dropdown_item.xml
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
style="?android:attr/spinnerDropDownItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:ellipsize="marquee"
android:fontFamily="sans-serif-thin"
android:textSize="17sp"
android:textStyle="bold"
android:background="#FFFFFF"
android:textColor="#000000"/>
And finally the Layout XML
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Spinner
android:id="#+id/update_spinner_nationalite"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_marginStart="20dp"
android:layout_marginTop="10dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView55"/>
I can see the Spinner but there are no data listed and no dropdown visible on click.
I also tried to use AppCompatSpinner from androidx.appcompat.widget.AppCompatSpinner and also use android.R.layout.simple_spinner_dropdown_item instead of the custom one but I have the same result.
For sure I'm missing something....
There is no problem on my side. I ran your code successfully on AndroidX project.
I have fetched data from the server from the category class.The getcategories method return the List of String containing spinner items. When I click on the spinner item. Nothing happens. Is there any mistake in my code. Please help.
This is my java code.
public void fetchPropertyType(){
category = new Category(); //Spinner Item model
//categories is a array list of String which contains the items of spinner
categories = category.getCategories(AddPropertyActivity.this);
//Property Type Spinner Adapter
propertyTypeSpinner = (Spinner) findViewById(R.id.property_type_spinner);
Log.e("Test", "Just a test message");
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, categories);
// Drop down layout style - list view with radio button
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// attaching data adapter to spinner
propertyTypeSpinner.setAdapter(dataAdapter);
propertyTypeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(parent.getContext(),
"OnItemSelectedListener : " + parent.getItemAtPosition(position).toString(),
Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
Log.e("Test", "Nothing selected on spinner activity");
}
});
}
This is my layout
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="5dp"
android:layout_weight="1">
<TextView
android:id="#+id/spinner_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginRight="50dp"
android:gravity="center"
android:text="Property Type"
android:textAlignment="textEnd"/>
<Spinner
android:id="#+id/property_type_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:spinnerMode="dropdown"/>
</RelativeLayout>
You just should do this.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="5dp"
android:layout_weight="1"
android:background="#drawable/border">
<TextView
android:id="#+id/spinner_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginRight="50dp"
android:gravity="center"
android:text="Property Type"
android:textAlignment="textEnd"/>
<Spinner
android:id="#+id/property_type_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:spinnerMode="dropdown"/>
</RelativeLayout>
In the Spinner
Change
android:layout_height="match_parent"
To
android:layout_height="wrap_content"
Because you use android:layout_height="match_parent",so you can't see your list item.And nothing happens.
As you are using
<Spinner
android:id="#+id/property_type_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:spinnerMode="dropdown"/>
Which wraps the height of spinner so try to give custom height to it so that i t will be clickable
I did this
<Spinner
android:id="#+id/property_type_spinner"
android:layout_width="match_parent"
android:layout_height="50dp"
android:spinnerMode="dropdown"/>
and keep your text view height wrap_content as
<TextView
android:id="#+id/spinner_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="50dp"
android:gravity="center"
android:text="Property Type"/>
I'm using a Spinner below a title (TextView). It is initially set to View.GONE and when the title is clicked, Spinner is set to View.VISIBLE and the popup window is shown using performClick() below the title, which is what I want.
But I asynchronously update the BaseAdapter to add more items to the Spinner when it is still VISIBLE. After the update the Spinner is moved upwards and is overlaying on the title. How can I fix this?
I have used android:dropDownVerticalOffset, but shows the same behaviour after update.
My layout :
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/some_other_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
<android.support.v7.widget.AppCompatSpinner
android:id="#+id/spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:background="#null"
android:overlapAnchor="true"
android:spinnerMode="dropdown"
android:visibility="gone"></android.support.v7.widget.AppCompatSpinner>
</FrameLayout>
</LinearLayout>
Ok.
I Tried running you problem with some slight adjustments on my mobile, and I find no issues.
To simulate your asynchronous addition of items, I added a button.It's OnClick will add items to the adapter.
Next, Instead of extending BaseAdapter, I just used an ArrayAdapter.
And, I just added weights to the LinearLayout to help me with the layout look.
Here Is The Layout :
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Title"
android:textSize="20dp"
android:gravity="center"
android:textColor="#android:color/black"
/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
>
<LinearLayout
android:id="#+id/some_other_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
<android.support.v7.widget.AppCompatSpinner
android:id="#+id/spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:background="#null"
android:overlapAnchor="true"
android:spinnerMode="dropdown"></android.support.v7.widget.AppCompatSpinner>
</FrameLayout>
<Button
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="Load Adapter"
android:id="#+id/button"
/>
</LinearLayout>
And Here Is the Code for the Activity :
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
}
Spinner spinner;
Button button;
#Override
protected void onResume() {
super.onResume();
spinner = (Spinner) findViewById(R.id.spinner);
button = (Button) findViewById(R.id.button);
List<String> list = new ArrayList<>();
list.add(getRandomStringInRange('A','Z',5));
ArrayAdapter<String> adapter= new ArrayAdapter(MainActivity.this,android.R.layout.simple_spinner_item,list);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ArrayAdapter<String> adapter = (ArrayAdapter<String>) spinner.getAdapter();
adapter.add(getRandomStringInRange('A','Z',5));
}
});
}
public int getRandomNumberInRange(int lower,int higher){
int range = higher-lower;
range=(int)(range*Math.random());
return lower + range;
}
public String getRandomStringInRange(char lower,char higher,int length){
String str ="";
for(int i=0;i<length;i++)
str+=(char)(getRandomNumberInRange(lower,higher));
return str;
}
}
I did not find the spinner overlapping the title or it moving at all.
It's working fine.
If you want,I'll send you screenshots.
Please tell me if you are facing any other issues
I couldn't really find a solution for this. But solved by setting fixed height for the spinner as mentioned in this solution.
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...
}
I am trying to use two spinners with a custom dropdown yet, only the bottom one is showing with the custom layout when pulled down. I have been trying on my own to figure out why but I cannot.
public class setup extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.setuplayout);
Spinner spinner1 = (Spinner) findViewById(R.id.Spinner01);
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.numberPlayers, R.layout.spinner_item);
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Apply the adapter to the spinner
spinner1.setAdapter(adapter);
Spinner spinner2 = (Spinner) findViewById(R.id.Spinner02);
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> adapter2 = ArrayAdapter.createFromResource(this,
R.array.gameDifficulty, R.layout.spinner_item);
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Apply the adapter to the spinner
spinner2.setAdapter(adapter2);
}
}
This is the xml code for spinner_item mentioned above.
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:textColor="#F9B12F"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:gravity="left"
android:padding="5dip"
android:popupBackground="#000000"
android:background="#000000"
/>
This is the setuplayout xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView android:id="#+id/mainSetupImage"
android:src="#drawable/setup"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ImageView>
<ImageView
android:id="#+id/players"
android:clickable="true"
android:src="#drawable/players"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_centerVertical="true">
</ImageView>
<Spinner
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:drawSelectorOnTop="true"
android:id="#+id/Spinner01"
android:textColor="#F9B12F"
android:layout_toRightOf="#+id/players"
android:layout_marginLeft="25dp"
android:layout_centerVertical="true"
android:background="#drawable/spinner"/>
<Spinner
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:drawSelectorOnTop="true"
android:id="#+id/Spinner02"
android:textColor="#F9B12F"
android:layout_below="#+id/Spinner01"
android:layout_toRightOf="#+id/difficulty"
android:layout_marginTop="25dp"
android:background="#drawable/spinner"/>
<ImageView
android:id="#+id/difficulty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignTop="#+id/Spinner02"
android:clickable="true"
android:src="#drawable/difficulty" />
</RelativeLayout>
in 2nd spinner u used adapter rather than adapter2. so use adapter2 and run your code hope it will run. :)
I figured it out with your help. I had used the code "adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)" which was overriding my custom layout. Thanks for highlighting where the two codes were different. That was a huge help. I deleted the quoted lines and it now works.
I'd like to share a little code that will make all people's code much cleaner when making ArrayAdapters.
Just define a static method in a class of your preference (even MainActivity...) to give you the Array adapter without dirting so much your code:
public static ArrayAdapter<CharSequence>
getArrayAdapter( Context c, int arrayId, int idLayout1, int idLayout2){
ArrayAdapter<CharSequence> aa;
aa = ArrayAdapter.createFromResource( c, arrayId , idLayout1);
aa.setDropDownViewResource( idLayout2);
return aa;
}
Then in your code you just need to do it:
myspinner.addAdapter(
this, ThatClass.getArrayAdapter(
R.array.myid, R.layout.id1, R.layout.id2 );
myspinner.setOnItemSelectedListener(this);
/* Remember that the default Android Spinner layout can be get passing these specific layout ids:
android.R.layout.simple_spinner_item as layout1
android.R.layout.simple_spinner_dropdown_item as layout2
*/