可搜索的微调器适配器android中的问题

时间:2017-02-28 11:08:07

标签: android spinner android-arrayadapter android-spinner

我在我的应用中集成了可搜索的微调器。以下是我的代码

gradle文件

    compile 'com.toptoche.searchablespinner:searchablespinnerlibrary:1.3.1'

Xml文件

 <com.toptoche.searchablespinnerlibrary.SearchableSpinner
    android:id="@+id/spinner"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:hintText="Select Country"/>

Man.java

public class MainActivity extends AppCompatActivity {

SearchableSpinner mSearchableSpinner;
ArrayList<GetCountry> mGetCountries;
PriorityAdapter mPriorityAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mSearchableSpinner = (SearchableSpinner) findViewById(R.id.spinner);

    mGetCountries = new ArrayList<>();
    GetCountry mGetCountry = new GetCountry();
    mGetCountry.setId("1");
    mGetCountry.setName("India");
    mGetCountries.add(mGetCountry);

    GetCountry mGetCountry2 = new GetCountry();
    mGetCountry2.setId("2");
    mGetCountry2.setName("USA");
    mGetCountries.add(mGetCountry2);


    GetCountry mGetCountry3 = new GetCountry();
    mGetCountry3.setId("3");
    mGetCountry3.setName("UK");
    mGetCountries.add(mGetCountry3);

    GetCountry mGetCountry4 = new GetCountry();
    mGetCountry4.setId("4");
    mGetCountry4.setName("CHINE");
    mGetCountries.add(mGetCountry4);

    GetCountry mGetCountry5 = new GetCountry();
    mGetCountry5.setId("5");
    mGetCountry5.setName("MALASIYA");
    mGetCountries.add(mGetCountry5);

    mPriorityAdapter=new PriorityAdapter(mGetCountries);
    mSearchableSpinner.setAdapter(mPriorityAdapter);
}


public class PriorityAdapter extends ArrayAdapter<GetCountry> {

    ArrayList<GetCountry> list;

    public PriorityAdapter(ArrayList<GetCountry> list) {
        super(MainActivity.this, R.layout.spin_layout, list);
        this.list = list;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) { // Ordinary


        return initView(position, convertView, parent);
    }

    @Override
    public View getDropDownView(int position, View convertView,
                                ViewGroup parent) { // This view starts when we click the
        // spinner.
        return initView(position, convertView, parent);
    }

    public View initView(int position, View convertView, ViewGroup parent) {

        LayoutInflater inflator = getLayoutInflater();
        convertView = inflator.inflate(R.layout.spin_layout, null);
        TextView mTextView = (TextView) convertView
                .findViewById(android.R.id.text1);
        mTextView.setText(list.get(position).getName());
        return convertView;
    }

}

}

当我运行上面的代码时,我得到如下图像的输出。自定义arraylist数据不显示它是java每个项目的打印垃圾值 Spinner Output

我知道如何解决这个问题?

修改

    public class PriorityAdapter extends ArrayAdapter<GetCountry> {

    ArrayList<GetCountry> list;

    public PriorityAdapter(ArrayList<GetCountry> list) {
        super(MainActivity.this, R.layout.spin_layout, list);
        this.list = list;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) { // Ordinary


        return initView(position, convertView, parent);
    }

    @Nullable
    @Override
    public GetCountry getItem(int position) {
        return super.getItem(position);
    }



    @Override
    public View getDropDownView(int position, View convertView,
                                ViewGroup parent) { // This view starts when we click the

        View view = convertView;
        LayoutInflater layoutInflater = LayoutInflater.from(getContext());
        view = layoutInflater.inflate(R.layout.spin_layout_1, parent, false);

        TextView tv= (TextView) view.findViewById(R.id.text1);
        tv.setText(list.get(position).getName());
        return view;

    }

    public View initView(int position, View convertView, ViewGroup parent) {


        View view = convertView;
        LayoutInflater layoutInflater = LayoutInflater.from(getContext());
        view = layoutInflater.inflate(R.layout.spin_layout_1, parent, false);

        TextView tv= (TextView) view.findViewById(R.id.text1);
        tv.setText(list.get(position).getName());
        return view;
    }

}

GetCountry.java

public class GetCountry {
String name;
String id;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}
}

4 个答案:

答案 0 :(得分:1)

您可以尝试更改getView和getDropDownView返回值

像这样;

View view = convertView;
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
view = layoutInflater.inflate(R.layout.spinneradapter, parent, false);

TextView tv= (TextView) view.findViewById(R.id.tvEkipCantasiEkipman);
tvAdet.setText(arrayListItem);
return view;

答案 1 :(得分:1)

您可以像这样重写模型(GetCountry)的toString()函数:

GetCountry.java

public class GetCountry {
    String name;
    String id;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return name;
    }
}

答案 2 :(得分:0)

您收到此列表是因为您的getView和PriorityAdapter中声明的任何其他方法根本没有调用。 那么为什么要使用自定义适配器,而只需使用下面的简单数组适配器 -

 String[] names = new String[]{"India","CHINA","UK","US","MALYSIA"};
        ArrayAdapter arrayAdapter = new ArrayAdapter(SearchActivity.this,android.R.layout.simple_spinner_dropdown_item,names);
        mSearchableSpinner.setAdapter(arrayAdapter);

在onCreate活动方法中添加这些行,您将获得正确的下拉列表。

答案 3 :(得分:0)

有一个解决方案,但是这很糟糕。 如果查看searchableSpinner库,它将调用ArrayAdapter基类,而不是您设置的ArrayAdapter类。 所以..

或者您重新实现该库,然后使用“扩展ArrayAdapter类的通用对象”,以便它将使用您的getDropDownView。

或者,如果您查看ArrayAdapter基类,则可以找到以下代码,该代码用于显示适配器中项目的“ toString”:

private @NonNull View createViewFromResource(@NonNull LayoutInflater inflater, int position,
            @Nullable View convertView, @NonNull ViewGroup parent, int resource) {
        final View view;
        final TextView text;

        if (convertView == null) {
            view = inflater.inflate(resource, parent, false);
        } else {
            view = convertView;
        }

        try {
            if (mFieldId == 0) {
                //  If no custom field is assigned, assume the whole resource is a TextView
                text = (TextView) view;
            } else {
                //  Otherwise, find the TextView field within the layout
                text = view.findViewById(mFieldId);

                if (text == null) {
                    throw new RuntimeException("Failed to find view with ID "
                            + mContext.getResources().getResourceName(mFieldId)
                            + " in item layout");
                }
            }
        } catch (ClassCastException e) {
            Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
            throw new IllegalStateException(
                    "ArrayAdapter requires the resource ID to be a TextView", e);
        }

        final T item = getItem(position);
        if (item instanceof CharSequence) {
            text.setText((CharSequence) item);
        } else {
            text.setText(item.toString());
        }

        return view;
    }

如您在最后几行所见:

final T item = getItem(position);
            if (item instanceof CharSequence) {
                text.setText((CharSequence) item);
            } else {
                text.setText(item.toString());
            }

因此,如果不是CharSequence,它将调用onString方法。 然后:或者您重写对象的onString方法(我不喜欢这种解决方案,因为我经常在调试器上使用onString进行调试),或者在自定义适配器中实现2个数组:

1个CharSequences数组,其中包含要显示的值

1个包含对象的数组

您ArrayAdapter将是一个简单的“ ArrayAdapter ”,而不是“ ArrayAdapter ”(这就是为什么它不是最佳解决方案:您将失去所有“ ArrayAdapter”通用对象结构的好处。)。 / p>

您的“ getItem”方法将返回“字符串列表”中的对象,然后您将使用该位置从适配器中存储的另一个数组中检索项目。

这将需要适配器内部的另一步和公共方法。因此,当您使用“ getSelectedItem”时,它将返回标签而不是对象,因此,要获取真实的“ selectedObject”,应调用“ getSelectedItemPosition”,并将其传递给使用该位置返回真实对象的方法。

您可以在自定义适配器重写的addAll方法(而不是在构造函数中)中传递自定义项目列表。在其中,您将创建CharSequences(或Strings)列表,该列表仅用于可视化目的。我的意思是这样的:

public void addAll(List<YourObject> myObjects){
   mItems.clear()     // mItems => List<YourObject>
   mLabels.clear()    // mLabels => List<String> (so labels visualized)
   if(myObjects != null && myObjects.size > 0x0{
      mItems.addAll(myObjects);
      for(YourObject obj : myObjects){
          mLabels.add(obj.getMyLabel());
      }
   }
   notifyDataSetChanged()
}

(我在这里用stackoverflow即时编写了所有代码,如果有任何错误,抱歉!)

这是我发现的更快的解决方案,无需更改对象的“ onString”方法,更好的方法是重新实现可搜索的微调器库(如果有时间的话)以使用自定义ArrayAdapter而不是基类ArrayAdapter

总结:

  • 更快的解决方案:就像@AJS所说的那样覆盖“ toString”方法
  • 快速解决方案,如果您不想覆盖“ toString”->解决方案 以上
  • 最佳解决方案->重新实现该库以使用通用自定义适配器 它扩展了ArrayAdapter,因为仅SearchableSpinnerLibrary 使用基本的ArrayAdapter类(我不知道为什么)

gg,编码愉快!

我使用上面的逻辑做了一个BaseSearchableSpinnerAdapter类,这里是代码:

public abstract class BaseSearchableSpinnerAdapter<T extends Object> extends ArrayAdapter<String> {

    protected Context mContext;
    protected List<String> mLabels;
    protected List<T> mItems;

    public BaseSearchableSpinnerAdapter(@NonNull Context context, int resource) {
        super(context, resource);
        mContext = context;
        mItems = new ArrayList<>();
        mLabels = new ArrayList<>();
    }

    /** Abstract Methods **/
    public abstract String getLabel(int pos); //used to get the label to view

    /** Override ArrayAdapter Methods **/
    @NonNull
    @Override
    public View getView(int position, View convertView, @NonNull ViewGroup parent) {
        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.spinner_default, parent, false);
        }
        TextView tv = convertView.findViewById(R.id.text1);
        if(tv != null){
            tv.setText(getLabel(position));
        }
        return convertView;
    }

    @Override
    public int getCount(){
        return mLabels.size();
    }

    @Override
    public String getItem(int position){
        return mLabels.get(position);
    }

    @Override
    public long getItemId(int position){
        return position;
    }

    /** Public Methods **/
    public void clear(){
        mLabels.clear();
        mItems.clear();
    }

    public void addAll(List<T> objs){
        mLabels.clear();
        mItems.clear();
        if(objs != null && objs.size() > 0x0){
            mItems.addAll(objs);
            for(int i=0x0; i<objs.size(); i++){
                mLabels.add(getLabel(i));
            }
        }
        notifyDataSetChanged();
    }

    public T getMyItem(int pos){
        return mItems.get(pos);
    }

}

我使用了通用对象(),因为检索对象时不需要强制转换。您还可以使用“ Object”或“”(不检查最后一个)之类的基类,但是在这种情况下,您需要对其进行强制转换。

通过以下方式扩展:

public class MyClassSearchableSpinnerAdapter extends BaseSearchableSpinnerAdapter<MyObject>;

代替:

YourObject myobj = mSpinner.getSelectedItem();

您必须这样做:

YourObject myObj = ((MyClassSearchableSpinnerAdapter) mSpinner.getAdapter()).getMyItem(mSpinner.getSelectedItemPosition());

希望这很有帮助,bb的编码不错。 在可搜索的微调器视图(下拉菜单和选定视图)中,您将看到在“ getLabel()”方法中返回的内容。