根据列表视图中未显示的字段过滤列表视图

Filtering a listview based on fields not displayed in listview

我目前有一个应用程序可以从互联网上抓取一个 json 文件,对其进行解析并从中创建项目对象。项目具有以下字段:类型(图像、文本)和数据(如果项目类型为图像,则为 url;如果项目类型为文本,则为文本字符串)

当应用首次加载时,列表显示所有项目的混合类型,包括文本和图像。如果项目是图像,则仅图像显示在列表视图的列表项中,如果是文本,则显示文本。

我需要它做的(并且遇到问题)是我需要它以便当用户从菜单 select 中选择时 "Image Only" 它只会显示具有的对象列表视图中的类型 "image" 并隐藏类型为 "text" 的项目,如果它们是 select "Text Only",则它会过滤掉所有图像列表项目并仅显示项目类型 "text"。如果他们 select "All" 它应该显示默认值,就像应用程序首次加载时一样。

我没有在列表视图的任何地方显示此对象的类型字段,只显示对象的数据字段,它可以是从 url 加载的图像或文本。似乎我遇到的每个过滤示例都是当有人键入文本时它会过滤列表但是该文本显示在列表中并且在列表中可见我需要过滤的内容在列表中不可见..我不是很确定如何完成我需要的。有人有什么想法吗?希望我解释得足够好

编辑:这是我目前所拥有的。现在,当我 select 菜单中的图像有效时,当我 select 菜单中的文本有效时,当我切换回全部时它是空白的并且 mitems.size 为零,即使我从来没有从中删除任何内容。

创建时:

 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    tvNoInet=(TextView)findViewById(android.R.id.empty);
    setSupportActionBar(toolbar);
    if (isNetworkAvailable()) {
        getData theJsonData = new getData();
        theJsonData.execute();
    }

    myListView = (ListView) findViewById(R.id.listViewID);
    customAdapter = new ListAdapter(MainActivity.this, R.layout.list,mItems);
    myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            if (mItems.get(position).getmType().toString().equals("text")){
                if (isNetworkAvailable()) {
                    Intent in = new Intent(MainActivity.this, MyWebView.class);
                    startActivity(in);
                }
                else{
                    Toast.makeText(getApplicationContext(), "No internet connection, try again later", Toast.LENGTH_SHORT).show();
                }

            }
            if (mItems.get(position).getmType().toString().equals("image")){
                Intent in = new Intent(MainActivity.this,FullImage.class);
                in.putExtra("imageURL",mItems.get(position).getmData().toString());
                startActivity(in);
            }
        }
    });


}

我的选项菜单,其中 select 选项之一(全部、图像、文本)

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_about) {
        Intent intent = new Intent(this, About.class);
        startActivity(intent);
        return true;
    }

    if (id == R.id.all) {
        item.setChecked(true);
        customAdapter.clear();
        customAdapter.addAll(mItems);
        return true;

    }
    if (id == R.id.images) {
        item.setChecked(true);
        customAdapter.clear();
        customAdapter.addAll(mImageItems);
        return true;

    }
    if (id == R.id.text) {
        item.setChecked(true);
        customAdapter.clear();
        customAdapter.addAll(mTextItems);
        return true;
    }

    return super.onOptionsItemSelected(item);
}

我的任务是抓取 json,解析它,创建对象,然后将它添加到 mItems,如果类型是图像,也会将它添加到 mImageItems,如果类型是文本,则会将它添加到 mTextItems。

public class getData extends AsyncTask<String, Void, String> {
    String jsonStr = null;
    ProgressDialog progress = new ProgressDialog(MainActivity.this);
    @Override
    protected String doInBackground(String... params) {
        HttpURLConnection urlConnection = null;
        BufferedReader reader = null;

        try {
            URL url = new URL("http://host/data.json");
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.connect();
            InputStream inputStream = urlConnection.getInputStream();
            StringBuffer buffer = new StringBuffer();
            if (inputStream == null) {
                return null;
            }
            reader = new BufferedReader(new InputStreamReader(inputStream));

            String line;
            while ((line = reader.readLine()) != null) {
                buffer.append(line + "\n");
            }

            if (buffer.length() == 0) {
                return null;
            }
            jsonStr = buffer.toString();
        } catch (IOException e) {
            Log.e("MAIN", "Error ", e);
            return null;
        } finally{
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (final IOException e) {
                    Log.e("PlaceholderFragment", "Error closing stream", e);
                }
            }
        }
        try {

            JSONArray itemsArray = new JSONArray(jsonStr);

            String itemID=null;
            String itemType=null;
            String itemDate=null;
            String itemData=null;
            for (int i = 0; i < itemsArray.length(); i++) {
                JSONObject jsonItem=itemsArray.getJSONObject(i);
                if (jsonItem.has("id")){
                    itemID=jsonItem.getString("id");
                }
                if (jsonItem.has("type")){
                    itemType=jsonItem.getString("type");
                }
                if (jsonItem.has("date")){
                    itemDate=jsonItem.getString("date");
                }
                if (jsonItem.has("data")){
                    itemData=jsonItem.getString("data");
                }
                Item myItem=new Item(itemID,itemType,itemDate,itemData);
                mItems.add(myItem);
                if (itemType.equals("image")){
                    mImageItems.add(myItem);
                }
                else if (itemType.equals("text")){
                    mTextItems.add(myItem);
                }




            }
            Log.e("ALL SIZE: ", String.valueOf(mItems.size()));
            Log.e("TEXT SIZE: ", String.valueOf(mTextItems.size()));
            Log.e("IMAGE SIZE: ", String.valueOf(mImageItems.size()));
        } catch (JSONException jsone) {
            jsone.printStackTrace();
            Log.e(LOG_TAG, "Error processing Json Data");
        }

最后是我的适配器:

class ListAdapter extends ArrayAdapter<Item>  {
   private List<Item> items;

    public ListAdapter(Context context, int textViewResourceId) {
        super(context, textViewResourceId);

    }

    public ListAdapter(Context context, int resource, List<Item> items) {

        super(context, resource, items);

        this.items = items;

    }

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

        View v = null;
        TextView tn = null;
        ImageView img = null;

        if (convertView == null) {
            LayoutInflater vi;
            vi = LayoutInflater.from(getContext());
            v = vi.inflate(R.layout.list, null);
        }
        else {
            v=convertView;
        }

        Item p = items.get(position);
        tn = (TextView) v.findViewById(R.id.tvText);
        img = (ImageView) v.findViewById(R.id.thumbnail);
            if (p.getmType().equals("image")) {
                img.setVisibility(View.VISIBLE);
                Picasso.with(getContext()).load(p.getmData()).error((R.drawable.placeholder_error)).placeholder(R.drawable.placeholder).resize(90,0).into(img);
                tn.setText("ID: " + p.getmID()+"\nTYPE: " + p.getmType() +"\nDate: " + p.getmDate()+ "\nDATA: " +  p.getmData());
            } else {
                img.setVisibility(View.INVISIBLE);
                tn.setText("ID: " + p.getmID()+"\nTYPE: " + p.getmType() +"\nDate: " + p.getmDate()+ "\nDATA: " +  p.getmData());
            }
        return v;
    }
}

现在当应用程序加载混合列表时显示所有项目,如果我从菜单 select "Images" 则只有图像类型显示在列表中,如果我 select "Text" 仅显示文本项目,我可以在图像和文本之间来回切换。但是,当我再次 select "All" 时,列表是空白的并且 mItems.size 是 0。我对这个感到头疼。哈哈 我发现的一种方法是当我将 Item 对象添加到列表时,我有一个名为 mAllItems 的第四个列表,它基本上设置为与 mItems 完全相同所以我在哪里 mItems.add(myItem);下一行是 mAllItems.add(myItem),在菜单 selection 中,我只是将 All 设置为 mAllItems。我知道我可能做错了,但你必须以某种方式学习对吗?

我觉得你很亲近。

您已经有三个列表。由于适配器是 ListView 的模型,因此在适配器中包含这些列表会更有意义。

public class ListAdapter extends BaseAdapter {

    public enum ListMode {
        IMAGES_AND_TEXT,
        IMAGES_ONLY,
        TEXT_ONLY
    }

    private ListMode mListMode = ListMode.IMAGES_AND_TEXT;

    private List<Item> mItems;

    private List<Item> mImages;

    private List<Item> mTexts;

    @Override
    public int getCount() {
        switch (mListMode) {
            case IMAGES_AND_TEXT:
                return mItems == null ? 0 : mItems.size();
            case IMAGES_ONLY:
                return mImages == null ? 0 : mImages.size();
            case TEXT_ONLY:
                return mTexts == null ? 0 : mTexts.size();
        }
        return 0;
    }

    @Override
    public Object getItem(int position) {
        switch (mListMode) {
            case IMAGES_AND_TEXT:
                return mItems == null ? null : mItems.get(position);
            case IMAGES_ONLY:
                return mImages == null ? null : mImages.get(position);
            case TEXT_ONLY:
                return mTexts == null ? null : mTexts.get(position);
        }
        return null;
    }

    @Override
    public long getItemId(int position) {
        return position;    // not really used
    }

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

        View v = null;
        TextView tn = null;
        ImageView img = null;

        if (convertView == null) {
            LayoutInflater vi;
            vi = LayoutInflater.from(getContext());
            v = vi.inflate(R.layout.list, null);
        } else {
            v=convertView;
        }

        Item p = items.get(position);
        tn = (TextView) v.findViewById(R.id.tvText);
        img = (ImageView) v.findViewById(R.id.thumbnail);
        if (p.getmType().equals("image")) {
            img.setVisibility(View.VISIBLE);
            Picasso.with(getContext()).load(p.getmData()).error((R.drawable.placeholder_error)).placeholder(R.drawable.placeholder).resize(90,0).into(img);
            tn.setText("ID: " + p.getmID()+"\nTYPE: " + p.getmType() +"\nDate: " + p.getmDate()+ "\nDATA: " +  p.getmData());
        } else {
            img.setVisibility(View.INVISIBLE);
            tn.setText("ID: " + p.getmID()+"\nTYPE: " + p.getmType() +"\nDate: " + p.getmDate()+ "\nDATA: " +  p.getmData());
        }
        return v;
    }

    /**
     * Call this when the filter is selected, e.g.
     * <code>mAdapter.setListMode(ListMode.IMAGES_AND_TEXT);</code>
     * @param listMode
     */
    public void setListMode(ListMode listMode) {
        mListMode = listMode;
        notifyDataSetChanged();
    }

    /**
     * After you receive the JSON, call this method to add the items to the adapter.
     * @param items
     */
    public void setItems(JSONArray jsonArray) {

        mItems = new ArrayList<>();
        mImages = new ArrayList<>();
        mTexts = new ArrayList<>();
        for (int i = 0; i < jsonArray.length(); i++) {
            Item item = new Item(jsonArray.get(i));
            mItems.add(item);
            if (item.isImage()) {
                mImages.add(item);
            }
            if (item.isText()) {
                mTexts.add(item);
            }
        }

        notifyDataSetChanged();
    }

}

像这样实例化您的适配器:

    .
    .
    .
    myListView = (ListView) findViewById(R.id.listViewID);
    customAdapter = new ListAdapter();
    myListView.setAdapter(customAdapter);
    .
    .
    .

当您的 AsyncTask 运行时,在您的适配器上设置项目:

        .
        .
        .
        JSONArray itemsArray = new JSONArray(jsonStr);
        customAdapter.setItems(itemsArray);
        .
        .
        .

像这样从菜单更改您的视图:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
        case R.id.action_about:
            Intent intent = new Intent(this, About.class);
            startActivity(intent);
            return true;

        case R.id.all:
            item.setChecked(true);
            customAdapter.setListMode(ListMode.IMAGES_AND_TEXT);
            return true;

        case R.id.images:
            item.setChecked(true);
            customAdapter.setListMode(ListMode.IMAGES_ONLY);
            return true;

        case R.id.text:
            item.setChecked(true);
            customAdapter.setListMode(ListMode.TEXT_ONLY);
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

此外,我会在您的 Item class 中添加一个构造函数,它需要一个 JSONObject:

    public Item(JSONObject jsonItem) {

        String itemID=null;
        String itemType=null;
        String itemDate=null;
        String itemData=null;

        if (jsonItem.has("id")) {
            itemID=jsonItem.getString("id");
        }
        if (jsonItem.has("type")) {
            itemType=jsonItem.getString("type");
        }
        if (jsonItem.has("date")){
            itemDate=jsonItem.getString("date");
        }
        if (jsonItem.has("data")){
            itemData=jsonItem.getString("data");
        }
        this(itemID,itemType,itemDate,itemData);
    }