【问题标题】:After searching for ListView items in Android, always open first item of ListView (Issue)在Android中搜索ListView项目后,总是打开ListView的第一项(问题)
【发布时间】:2014-05-09 14:14:12
【问题描述】:

当我打开搜索项时,它打开的是 ListView 的第一项而不是搜索项。即使搜索并找到项目成功。

让我举个例子:

  • 如果我搜索Arrow,我可以得到Arrow,但是当点击Arrow 时,它会转到Almost HumanAlmost Human 是我的ListView 的第一项
  • 如果我搜索American,我会得到The Americans (first)American Horror Story (second)(两个结果) 搜索过程是成功的,但是如果点击The Americans (second one)它会转到ListView的第二项。

我错过了什么?

我的搜索码:

    search.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
            // When user changed the Text
            MainActivity.this.adapter.getFilter().filter(cs);   
        }

        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                int arg3) {
            // TODO Auto-generated method stub

        }

        @Override
        public void afterTextChanged(Editable arg0) {
            // TODO Auto-generated method stub                          
        }
    });
}

这里是 CustomListViewAdapter.java

    public class CustomListViewAdapter extends ArrayAdapter<RowItem> {
Context context;

public CustomListViewAdapter(Context context, int resourceId,
        List<RowItem> items) {
    super(context, resourceId, items);
    this.context = context;
}

/* private view holder class */
private class ViewHolder {
    ImageView imageView;
    TextView txtTitle;
    TextView txtDesc;
}

public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder = null;
    RowItem rowItem = getItem(position);    

    LayoutInflater mInflater = (LayoutInflater) context
            .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.list_item, null);
        holder = new ViewHolder();
        holder.txtDesc = (TextView) convertView.findViewById(R.id.desc);
        holder.txtTitle = (TextView) convertView.findViewById(R.id.title);
        holder.imageView = (ImageView) convertView.findViewById(R.id.icon);
        convertView.setTag(holder);
    } else
        holder = (ViewHolder) convertView.getTag();

    holder.txtDesc.setText(rowItem.getDesc());
    holder.txtTitle.setText(rowItem.getTitle());
    // holder.imageView.setImageBitmap(rowItem.getImageId());

    ImageView img = (ImageView) convertView.findViewById(R.id.icon);
    ImageView gif = (ImageView) convertView.findViewById(R.id.icon);
    // UrlImageViewHelper.loadUrlDrawable(context, rowItem.getImageId());

    Ion.with(gif).load("http://www.example.com/wp-content/uploads/2014/03/android-icon/loading.gif");
    Drawable drawable=gif.getDrawable();
    UrlImageViewHelper.setUrlDrawable(img, rowItem.getImageId(),drawable,
            600000);
    return convertView;
}
    }

RowItem.java

        public class RowItem<T> {
        private String imageId;
        private String title;
        private String desc;

        public RowItem(String imageId, String title, String desc) {
            this.imageId = imageId;
            this.title = title;
            this.desc = desc;
        }
        public String getImageId() {
            return imageId;
        }
        public void setImageId(String imageId) {
            this.imageId = imageId;
        }
        public String getDesc() {
            return desc;
        }
        public void setDesc(String desc) {
            this.desc = desc;
        }
        public String getTitle() {
            return title;
        }
        public void setTitle(String title) {
            this.title = title;
        }
        @Override
        public String toString() {
            return title + "\n" + desc;
        }
    }   

MainActiviy.java

            protected void onCreate(Bundle onSaveInstanceState ) {
    super.onCreate(onSaveInstanceState );
    setContentView(R.layout.activity_main);
        listView.setOnItemClickListener(new OnItemClickListener() {

        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {

            // When clicked, Open the Next Screen
            Intent r = new Intent(MainActivity.this, KategoriActivity.class);
            r.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            r.putExtra("cat_img", asd[2][position]);
            r.putExtra("cat_id", asd[1][position]);
            r.putExtra("cat_id2", asd[1][position]);
            r.putExtra("cat_name",asd[0][position]);
            // r.putExtra("cat_img", bit[1][position]);
            startActivityForResult(r, position);


        }

    }); 


    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        try {

            JSONArray jsonResponse = new JSONArray(result);
            asd = new String[3][jsonResponse.length()];
            rowItems = new ArrayList<RowItem>();

            for (int i = 0; i < jsonResponse.length(); i++) {
                JSONObject js = jsonResponse.getJSONObject(i);
                asd[0][i] = js.getString("Category_Name");
                asd[2][i] = js.getString("Image");
                asd[1][i] = js.getString("Term_ID");

                RowItem item = new RowItem(asd[2][i], asd[0][i], "");
                rowItems.add(item);
            }

            adapter = new CustomListViewAdapter(MainActivity.this,
                    R.layout.list_item, rowItems);

            listView.setAdapter(adapter);


        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

希望你能帮助我..

【问题讨论】:

  • 你的 ListView 有标题吗?令人讨厌的是,标题被计为第一项,可能会导致这样的错误
  • 不,我没有标题。谢谢你的照顾。
  • 是否可以在您的代码中搜索后或选择搜索结果前通知datasetchanged?
  • 谢谢你 francesco 我会试试的。即使 github 的例子可以工作,我仍然对我的问题很好奇。不,我不这么认为。

标签: android listview android-listview android-search


【解决方案1】:

通常,如果您有一个像RowItem 这样的自定义类型的 ArrayAdapter,它不会自动为您处理过滤。毕竟,它怎么知道要过滤RowItem 的哪个属性呢?您应该覆盖getFilter 方法,并将过滤后的列表与适配器中的整体列表分开存储。像这样的:

public class CustomListViewAdapter extends ArrayAdapter<RowItem>
{
    private final ArrayList<RowItem>  mItems;
    private       ArrayList<RowItem>  mFilteredItems;
    private final Comparator<Object> mComparator;

    public CustomListViewAdapter(Context context, int textViewResourceId, List<RowItem> items)
    {
        super(context, textViewResourceId);

        mItems = new ArrayList<RowItem>(items);
        mFilteredItems = new ArrayList<RowItem>(items);
        mComparator = new Comparator<Object>()
        {
            @Override
            public int compare(Object o1, Object o2)
            {
                String s1 = ((RowItem)o1).getTitle();
                String s2 = ((RowItem)o2).getTitle();
                return s1.toLowerCase(Locale.getDefault()).compareTo(s2.toLowerCase());
            }
        };

        Collections.sort(mItems, mComparator);
        Collections.sort(mFilteredItems, mComparator);
    }

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

    @Override
    public RowItem getItem(int position)
    {
        return mFilteredItems.get(position);
    }

    @Override
    public int getPosition(RowItem item)
    {
        return mFilteredItems.indexOf(item);
    }

    @Override
    public Filter getFilter()
    {
        return new Filter()
        {
            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results)
            {
                mFilteredItems = (ArrayList<RowItem>)results.values;
                if (results.count > 0)
                {
                    notifyDataSetChanged();
                }
                else
                {
                    notifyDataSetInvalidated();
                }
            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint)
            {
                List<RowItem> filteredResults = new ArrayList<RowItem>();
                for (RowItem item : mItems)
                {
                    if (item.getTitle().toLowerCase(Locale.getDefault()).contains(constraint.toString().toLowerCase(Locale.getDefault())))
                    {
                        filteredResults.add(item);
                    }
                }

                Collections.sort(filteredResults, mComparator);
                FilterResults results = new FilterResults();
                results.values = filteredResults;
                results.count = filteredResults.size();

                return results;
            }
        };
    }
}

在 MainActivity 中:

        RowItem item = adapter.getItem(position)
        r.putExtra("cat_img", item.getImageId());
        r.putExtra("cat_id", item.getTermId());
        r.putExtra("cat_id2", item.getTermId());
        r.putExtra("cat_name", item.getTitle());

您还必须向 RowItem 添加一个 termid 字段,因为它在您的 JSON 响应中...

【讨论】:

  • 我什么都试过了,但还是不行。我无法修复并找到此错误的替代方法:java.lang.ClassException: RowItem can not cast to java
  • 我很困惑。 o1.gettitle() 没有方法。
  • 您只需要将其转换为 RowItem...我再次编辑了答案。
  • 它没有给出任何错误但同时它没有影响任何东西。这怎么可能?还是同样的立场问题?我在哪里失踪?希望你能帮助我..
  • 你不能像asd[2][position]这样引用另一个数组...这使得适配器无用。我编辑了答案。确保将 termid 添加到 RowItem。
【解决方案2】:

从您传入的列表中获取 listView 项目 ID //您的适配器类。

here例如,如果您的适配器类是##

 class CustomAdapetr(Context context,ArrayList<RowItem>list_item){}
    //mainactivity
 myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

       // HERE IS YOUR ITEM ID:):)
          int clickedItem=list_item.indexOf(parent.getAdapter().getItem(position));

            }
        });

干杯!!!!快乐编码

【讨论】:

    【解决方案3】:

    ArrayAdapter 内部有两个列表:包含所有项目的原始列表,以及适配器将为其创建视图的当前项目列表。一开始,这两个列表具有相同的项目。当您在适配器上进行过滤时,原始列表将继续保存所有项目,但用于显示的列表将因过滤器而改变。删除过滤器后,当前项目列表将再次更改以反映原始列表。

    假设您有五个项目。过滤后,列表只显示最后一项。那么这些列表的状态是

    currentItems: { item5 }
    originalItems: { item1 , item2 , item3 , item4 , item5 }
    

    当您单击此项目时,ListView 会报告该位置 0 已单击。这是因为显示的列表只有一项。如果您随后在当前列表中的位置 0 处查找项目,您将获得 item5。但是,如果您在 原始列表的位置 0 查找项目,您会得到item1,这不是被点击项目的数据。 p>

    我怀疑您引用了原始列表并使用它来获取项目数据,即使列表已被过滤。而是使用adapter.getItem(position),它应该会给你正确的项目。

    【讨论】:

    • 谢谢您,我不知道位置的情况下如何获得该项目?有什么想法吗?
    • 我想你可以打开 stable ids
    • 你能举个例子吗,我不知道如何在我的适配器上使用 getItemId ?
    【解决方案4】:

    我正在使用这样的东西,它对我来说很好用。我在我的列表 onsitemclick 中使用字符串值来搜索和显示所需的活动

    list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
          @Override
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {
    
    
          String  itemValue    = (String) list.getItemAtPosition(position);
          if (itemValue == "INDIA") {
              Intent intent = new Intent(MainActivity.this, india.class);
              startActivity(intent);}
          else if (itemValue == "CHINA") {
              Intent intent = new Intent(MainActivity.this, china.class);
              startActivity(intent);}
    
              else if (itemValue == "IRAQ") {
                  Intent intent = new Intent(MainActivity.this, usa.class);
                  startActivity(intent);
         }
    
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多