问题
I have a form with TextInputLayout+TextInputEditText and spinners. I want the spinner height wrap text but have large items in the dropdown. The problem is that the spinner's height depends on the dropdown items height (simple_spinner_dropdown_item). I set style="@style/Base.Widget.AppCompat.Spinner.Underlined" in order to add line below spinner.
Any solution?
回答1:
Spinner like edittext
If you want spinner like edittext, it's like AutoCompleteTextView .You can custom your AppCompatAutoCompleteTextView
like that:
public class AutoCompleteDropDown extends AppCompatAutoCompleteTextView {
// implements AdapterView.OnItemClickListener
private static final int MAX_CLICK_DURATION = 200;
private long startClickTime;
private boolean isPopup;
private int mPosition = ListView.INVALID_POSITION;
public AutoCompleteDropDown(Context context) {
super(context);
// setOnItemClickListener(this);
}
public AutoCompleteDropDown(Context arg0, AttributeSet arg1) {
super(arg0, arg1);
// setOnItemClickListener(this);
}
public AutoCompleteDropDown(Context arg0, AttributeSet arg1, int arg2) {
super(arg0, arg1, arg2);
// setOnItemClickListener(this);
}
@Override
public boolean enoughToFilter() {
return true;
}
@Override
protected void onFocusChanged(boolean focused, int direction,
Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
if (focused) {
performFiltering("", 0);
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getWindowToken(), 0);
setKeyListener(null);
dismissDropDown();
} else {
isPopup = false;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP: {
if (isPopup) {
dismissDropDown();
} else {
requestFocus();
showDropDown();
}
break;
}
}
return super.onTouchEvent(event);
}
@Override
public void showDropDown() {
super.showDropDown();
isPopup = true;
}
@Override
public void dismissDropDown() {
super.dismissDropDown();
isPopup = false;
}
@Override
public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top, Drawable right, Drawable bottom) {
Drawable dropdownIcon = ContextCompat.getDrawable(getContext(), R.drawable.ic_expand_more_black_18dp);
if (dropdownIcon != null) {
right = dropdownIcon;
right.mutate().setAlpha(66);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
super.setCompoundDrawablesRelativeWithIntrinsicBounds(left, top, right, bottom);
} else {
super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
}
}
public int getPosition() {
return mPosition;
}
}
And ic_expand_more_black_18dp.png
is a image like that:
Layout:
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:textColorHint="@color/gray_text_hint"
app:hintTextAppearance="@style/TextAppearance.App.TextInputLayout.Dark">
<yourpackage.AutoCompleteDropDown
android:id="@+id/edtBloodType"
style="@style/edt_dark"
android:hint="Blood Type"
android:inputType="textNoSuggestions" />
</android.support.design.widget.TextInputLayout>
Result (You can set adapter for your AutoCompleteTextView)
回答2:
Here is an workaround:
Spinner spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter<String> adapter = new ArrayAdapter<>(context, R.layout.custom_spinner_item, values);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
Here layout android.R.layout.simple_spinner_dropdown_item
is used for dropdown
item and custom layout custom_spinner_item
is used for spinner view
to show only TextView
.
custom_spinner_item.xml:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:maxLines="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee" />
FYI, You can customize this TextView
as per your needs.
Hope this will help~
回答3:
I'm using Support Libraries (AppCompat) and layouts like below. More info here.
<!-- editText -->
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="Hint">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
<!-- spinner with label -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
style="@style/TextAppearance.AppCompat.Caption"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Label"></TextView>
<android.support.v7.widget.AppCompatSpinner
style="@style/Widget.AppCompat.Spinner.Underlined"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:spinnerMode="dialog" />
</LinearLayout>
Update
spinner item layout:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
style="?android:attr/spinnerItemStyle"
android:paddingStart="0dp"
android:paddingLeft="0dp"
android:textSize="18sp"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:textAlignment="inherit"/>
for dropdown view: android.R.layout.simple_spinner_dropdown_item
回答4:
I wanted to take a moment and expand on RoShan Shan's answer, having just spent nearly 2 hours getting his code actually working.
What to do
You will need to create a new class which extends AppCompatAutoCompleteTextView:
public class ComboBox extends AppCompatAutoCompleteTextView implements AdapterView.OnItemClickListener {
private boolean isPopup;
private int mPosition = -1;
public ComboBox(Context context){
super(context);
setAdapter(new ArrayAdapter<>(context, android.R.layout.simple_expandable_list_item_1, new String[0]));
setOnItemClickListener(this);
setKeyListener(null);
}
public ComboBox(Context context, AttributeSet attributes){
super(context, attributes);
setAdapter(new ComboBoxAdapter(context, attributes.getAttributeListValue("http://schemas.android.com/apk/res/android", "entries", new String[0], R.array.default_empty_list)));
setOnItemClickListener(this);
setKeyListener(null);
}
public ComboBox(Context context, AttributeSet attributes, int arg2){
super(context, attributes, arg2);
setAdapter(new ComboBoxAdapter(context, attributes.getAttributeListValue("http://schemas.android.com/apk/res/android", "entries", new String[0], R.array.default_empty_list)));
setOnItemClickListener(this);
setKeyListener(null);
}
public static class ComboBoxAdapter extends ArrayAdapter<String> {
private final String[] list;
public ComboBoxAdapter(Context context, @ArrayRes int array){
super(context, android.R.layout.simple_expandable_list_item_1, context.getResources().getStringArray(array));
list = context.getResources().getStringArray(array);
}
@Override
public Filter getFilter(){
return new Filter(){
@Override
protected FilterResults performFiltering(CharSequence constraint){
FilterResults out = new FilterResults();
out.values = list;
out.count = list.length;
return out;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results){
notifyDataSetChanged();
}
};
}
}
@Override
public boolean enoughToFilter(){
return true;
}
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect){
super.onFocusChanged(focused, direction, previouslyFocusedRect);
if (focused){
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getWindowToken(), 0);
showDropDown();
}
}
@Override
public boolean performClick(){
if (isPopup){
dismissDropDown();
}
else {
showDropDown();
}
return super.performClick();
}
@Override
public void showDropDown(){
super.showDropDown();
isPopup = true;
}
@Override
public void dismissDropDown(){
super.dismissDropDown();
isPopup = false;
}
@Override
public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top, Drawable right, Drawable bottom){
Drawable dropdownIcon = ContextCompat.getDrawable(getContext(), R.drawable.ic_chevron_down);
if (dropdownIcon != null){
right = dropdownIcon;
right.mutate().setAlpha(66);
}
super.setCompoundDrawablesRelativeWithIntrinsicBounds(left, top, right, bottom);
}
public int getPosition(){
return mPosition;
}
public String getCurrentText(){
if (mPosition == -1){
return "";
}
else {
return getText().toString();
}
}
public void registerDataSetObserver(DataSetObserver observer){
getAdapter().registerDataSetObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer){
getAdapter().unregisterDataSetObserver(observer);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
setText(parent.getItemAtPosition(position).toString());
mPosition = position;
}
}
You will need to define an empty list to use as default:
<string-array name="default_empty_list"/>
And add an icon for the drop down. I recommend importing the ic_expand_more vector asset from clip art (File > New > Vector Assest > Clip Art
).
Why this is better
This ComboBox buys you a few things over the original answer:
Works out of the box. Create the three items above and everything will just work.
You can include the ComboBox in any View or layout from the xml (see original answer, it hasn't changed) but now you can also define the list there by supplying
android:entries
with an array resource.Use
registerDataSetObserver()
to add a change listener.Retrieve the current value of the ComboBox using
getPosition()
(index) orgetCurrentText()
(string).
Good luck
回答5:
ANSWER: I was just setting adapter layout (tried both layouts) but there is specific dropdown layout.
ArrayAdapter<String> typeAdapter = new ArrayAdapter<>(getActivity(), android.R.layout.spinner_item, types);
typeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner_item is a custom layout that removes left padding:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
style="?android:attr/spinnerItemStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:paddingEnd="0dp"
android:paddingLeft="0dp"
android:paddingStart="0dp"
android:singleLine="true"
android:textAlignment="inherit" />
Also, add this style to spinner:
style="@style/Widget.AppCompat.Spinner.Underlined"
And
来源:https://stackoverflow.com/questions/43970038/spinner-like-edittext