【问题标题】:Issue in searchable spinner adapter android可搜索微调器适配器android中的问题
【发布时间】:2017-07-19 07:50:03
【问题描述】:

我正在我的应用程序中集成可搜索微调器。下面是我的代码

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;
}
}

【问题讨论】:

  • 我遇到了同样的问题,我唯一可以补充的是 DropDownView 并没有真正考虑在内,而是你的班级的 .toString() 。我不知道为什么,但似乎 SpinnerSearchable 没有正确使用适配器。或者我们可能遗漏了一些东西。希望有人能提供帮助。干杯
  • 如何解决这个问题?我也遇到同样的问题?
  • @harshal 你是怎么解决这个问题的?

标签: android spinner android-arrayadapter android-spinner


【解决方案1】:

有一个解决方案,但它是糟糕的LoL。 如果您查看 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”通用对象结构的好处。)。

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

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

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

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);
    }

}

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

通过做来扩展:

public class MyClassSearchableSpinnerAdapter extends BaseSearchableSpinnerAdapter<MyObject>;

而不是做:

YourObject myobj = mSpinner.getSelectedItem();

你必须这样做:

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

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

【讨论】:

    【解决方案2】:

    您可以像这样覆盖模型 (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;
        }
    }
    

    【讨论】:

      【解决方案3】:

      您获得此列表是因为您的 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 方法中添加这些行,您将获得正确的下拉菜单。

      【讨论】:

      • 其实我有自定义列表,所以我必须设计自定义适配器。任何解决方案? @B.shruti
      【解决方案4】:

      你可以尝试改变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;
      

      【讨论】:

      • onur:我尝试使用您的代码,但我仍然面临同样的问题
      • onur:检查我的编辑部分,我按照您的建议尝试,但我仍然面临同样的问题
      • 请分享您定义了 setId、setName 和 getName 方法的 GetCountry 类?
      • B.shruti:查看我的编辑问题我添加了 getcountry 类
      • onur: 我在哪里尝试这个 return list.get(position).getName();?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多