在Android的GridView中实现搜索功能

7
我一直在成功地跟随这个教程 Android 搜索过滤 ListView 图片和文本教程。我正在尝试在我的活动中实现它并从服务器获取数据。
当我在搜索字段中输入时,网格视图变为空。就像自定义适配器中的列表变成了 null。
我的活动类:
package com.danz.tensai.catalog;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;

import android.support.v4.widget.SwipeRefreshLayout;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.danz.tensai.catalog.app.MyApplication;
import com.danz.tensai.catalog.helper.Product;
import com.danz.tensai.catalog.helper.SwipeListAdapter;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class MainActivity extends ActionBarActivity {

    private String TAG = MainActivity.class.getSimpleName();

    private String URL_TOP_250 = "http://danztensai.hostoi.com/imdb_top_250.php?offset=";

    private SwipeRefreshLayout swipeRefreshLayout;
    //private ListView listView;
    private GridView gridView;
    private SwipeListAdapter adapter;
    private List<Product> productList;
    private ProgressBar spinner;
    EditText editsearch;

    private int offSet = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        gridView = (GridView)findViewById(R.id.gridViewListProduct);


        productList = new ArrayList<>();
        fetchProduct();
        adapter = new SwipeListAdapter(this, productList);
        gridView.setAdapter(adapter);

        editsearch = (EditText)findViewById(R.id.search);

        editsearch.addTextChangedListener(new TextWatcher() {

            @Override
            public void afterTextChanged(Editable arg0) {
                // TODO Auto-generated method stub
                String text = editsearch.getText().toString().toLowerCase(Locale.getDefault());
                Log.d(TAG,"Text To Search : "+text);
                adapter.filter(text);
            }

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

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


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @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_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private void fetchProduct() {

        spinner = (ProgressBar)findViewById(R.id.progressBar1);
        // appending offset to url
        String url = URL_TOP_250 + offSet;

        // Volley's json array request object
        JsonArrayRequest req = new JsonArrayRequest(url,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        Log.d(TAG, response.toString());

                        if (response.length() > 0) {

                            // looping through json and adding to movies list
                            for (int i = 0; i < response.length(); i++) {
                                try {
                                     JSONObject movieObj = response.getJSONObject(i);

                                    int rank = movieObj.getInt("rank");
                                    String title = movieObj.getString("title");
                                    String imageURL = movieObj.getString("imageURL");
                                    Product m = new Product(rank, title,imageURL);

                                    productList.add(0, m);

                                    // updating offset value to highest value
                                    if (rank >= offSet)
                                        offSet = rank;

                                } catch (JSONException e) {
                                    Log.e(TAG, "JSON Parsing error: " + e.getMessage());
                                }
                            }

                           // adapter.notifyDataSetChanged();
                        }

                        // stopping swipe refresh
                       // swipeRefreshLayout.setRefreshing(false);
                        spinner.setVisibility(View.GONE);

                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "Server Error: " + error.getMessage());

                Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show();

                // stopping swipe refresh
            //    swipeRefreshLayout.setRefreshing(false);
                spinner.setVisibility(View.GONE);
            }
        });

        // Adding request to request queue
        Log.e(TAG,req.toString() );
        MyApplication.getInstance().addToRequestQueue(req);
    }
}

以及我的自定义适配器

public class SwipeListAdapter extends BaseAdapter {
    private Activity activity;
     LayoutInflater inflater;
    Context mContext;
    private List<Product> productList;
    private ArrayList<Product> arraylist;
    private String TAG = SwipeListAdapter.class.getSimpleName();

    //private String[] bgColors;

    public SwipeListAdapter(Context context, List<Product> productList) {
        //this.activity = activity;
        mContext = context;
        this.productList = productList;
        inflater = LayoutInflater.from(mContext);
        this.arraylist = new ArrayList<Product>();
        this.arraylist.addAll(productList);
      //  bgColors = activity.getApplicationContext().getResources().getStringArray(R.array.movie_serial_bg);
    }

    public class ViewHolder{
        ImageView productImage;
    }

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

    @Override
    public Object getItem(int location) {
        return productList.get(location);
    }

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


    public View getView(final int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;
        if(convertView==null)
        {
            holder = new ViewHolder();
            convertView = inflater.inflate(R.layout.list_row,null);
            holder.productImage = (ImageView) convertView.findViewById(R.id.productImage);
            convertView.setTag(holder);
        }else
        {
            holder
                     = (ViewHolder) convertView.getTag();
        }
        new DownloadImageTask((holder.productImage))
                .execute(productList.get(position).imageURL);
        return convertView;
    }

    public void filter(String charText) {
        charText = charText.toLowerCase(Locale.getDefault());
        productList.clear();
        if (charText.length() == 0) {
            productList.addAll(arraylist);
        } else {
            for (Product wp : arraylist) {
                if (wp.getTitle().toLowerCase(Locale.getDefault())
                        .contains(charText)) {
                    productList.add(wp);
                }
            }
        }
        notifyDataSetChanged();
    }
}

Search Function


onResponse中,你既没有通知适配器,也没有设置适配器,所以列表显然会始终为空。如果你取消注释"notify"那一行,它可能会奏效。 - Amrut Bidri
即使我取消注释通知行,ID仍然不受影响,问题仍然存在。 - dmh
请按照http://www.tutorialsbuzz.com/2014/08/filter-custom-listviewbaseadapter.html的步骤将您的BaseAdapter变为可过滤类型。希望这能对您有所帮助。 - Chitrang
@chitrang 仍然没有运气 :( - dmh
尝试一下:https://dev59.com/IWoy5IYBdhLWcg3wPbyd#8678198 - Lalit Poptani
1个回答

2
当您创建适配器时,在其构造函数中,将productList的内容添加到arraylist列表中。此时(适配器构造函数),由于获取json的http请求尚未完成,因此productList很可能为空。因此,您最终得到一个空的arraylist,当您对适配器进行任何过滤时,您将看不到任何内容,因为没有东西可以进行过滤。
不要忘记在onResponse()回调中更新适配器中的arraylist,以便您有一个引用可用于过滤。
我建议您遵循其他教程。
编辑:
向适配器添加一个“add”方法以插入新项目:
//In the SwipeListAdapter class add
public void add(Product p) {
    productList.add(0, p);
    arraylist.add(0, p);
    notifyDataSetChyanged();
}

那么在你的活动中,不要使用:

productList.add(0, m);

呼叫:

adapter.add(m);

那你有什么建议?实际上,当我开始时它会显示列表...唯一的问题是当我使用搜索栏时,适配器内部的列表变为空/零。 - dmh
@dmh 你至少观察了适配器中的两个列表(arraylist和productlist)在进行过滤时吗?在过滤方法的开头放置一些日志语句,检查这两个列表的大小,然后看看当您开始输入EditText中的字符时这些大小如何变化。 - user
记录过滤器开始时的日志: 07-07 15:04:10.232: D/MainActivity(30583): 要搜索的文本:p 07-07 15:04:10.234: D/SwipeListAdapter(30583): ProductList 的大小为 10 07-07 15:04:10.234: D/SwipeListAdapter(30583): ArrayList 的大小为 0 它显示适配器仍然有 10 个产品列表, 但当输入另一个单词时,产品列表变为 0(零)。07-07 15:04:10.328: D/MainActivity(30583): 要搜索的文本:pr 07-07 15:04:10.328: D/SwipeListAdapter(30583): ProductList 的大小为 0 07-07 15:04:10.328: D/SwipeListAdapter(30583): ArrayList 的大小为 0 - dmh
@dmh,即使您使用我上面发布的代码,仍会发生您所述的情况吗? - user
1
@Luckprog 我之前还包含了productList.add(0,m);,所以导致结果重复了,现在我已经移除了productList.add(0,m);。谢谢 :) 现在可以正常工作了。 - dmh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接