使用带有文本和图像的自定义适配器在列表视图中搜索

Posted

技术标签:

【中文标题】使用带有文本和图像的自定义适配器在列表视图中搜索【英文标题】:Searching in a listview using a Custom Adapter with text and images 【发布时间】:2018-06-14 20:15:39 【问题描述】:

我正在我的应用程序中配置资源以使用自定义适配器在列表视图中搜索。我在 addTextChangedListener 事件中使用 EditText 键入字符串并将文本传递给适配器,但它不起作用。

我使用“implements Filterable”配置适配器并使用“.setTextFilterEnabled(true)”启用Listview,但不起作用。

我看到我必须实现“public Filter getFilter()”,但我不知道该怎么做。

当我在 EditText 中键入一些单词时,例如“cel”或“12”,过滤器会起作用,但结果始终相同:Listview 中的前两项,无论 Listview 中的内容是什么(内容listview 是随机的)。

在我的 Fragment Activity 的 sn-p 下方:

public class VideosFragment extends Fragment 

private ListView listView;
private ArrayList<String> idVideo = new ArrayList<>();
private ArrayList<String> titleVideo = new ArrayList<>();
private ArrayList<String> descVideo = new ArrayList<>();
private ArrayList<String> urlVideo = new ArrayList<>();
private ArrayList<String> channelTitle = new ArrayList<>();
private ArrayList<String> canalTitle = new ArrayList<>();
private ArrayList<String> canalId = new ArrayList<>();
private CustomFiltraCanaisAdapter customFiltraCanaisAdapter;
private EditText editText;

CustomVideoAdapter customVideoAdapter;

public VideosFragment() 
    // Required empty public constructor



@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) 

    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_videos, container, false);


    // Configure Listview
    listView = (ListView)view.findViewById(R.id.listView_videos);

    //Create search parameters
    editText = (EditText) view.findViewById(R.id.searchList);
    listView.setTextFilterEnabled(true);
    editText.addTextChangedListener(new TextWatcher() 
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) 

        

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) 
            String text = editText.getText().toString().toLowerCase(Locale.getDefault());
            VideosFragment.this.customVideoAdapter.getFilter().filter(text);
        

        @Override
        public void afterTextChanged(Editable editable) 

        
    );

在我的 CustomAdapter 下方:

public class CustomVideoAdapter extends ArrayAdapter<String> implements Filterable 

private final Activity context;
private final ArrayList<String> videoTitle;
private final ArrayList<String> videoDesc;
private final ArrayList<String> videoId;
private final ArrayList<String> channelTitle;
private final ArrayList<String> imgurl;

public CustomVideoAdapter(Activity context, ArrayList<String> videoTitle,
                                            ArrayList<String> videoId,
                                            ArrayList<String> channelTitle,
                                            ArrayList<String> imgurl,
                                            ArrayList<String> videoDesc) 
    super(context, R.layout.custom_lista_videos, videoTitle);
    // TODO Auto-generated constructor stub

    this.context = context;
    this.videoTitle = videoTitle;
    this.videoDesc = videoDesc;
    this.videoId = videoId;
    this.channelTitle = channelTitle;
    this.imgurl = imgurl;

public View getView(int position,View view,ViewGroup parent) 
    LayoutInflater inflater=context.getLayoutInflater();
    View rowView=inflater.inflate(R.layout.custom_lista_videos, null,true);

    TextView txtTitle = (TextView) rowView.findViewById(R.id.txtVideoTitle);
    ImageView imgPhoto = (ImageView) rowView.findViewById(R.id.imgPhoto);
    TextView txtChannelTitle = (TextView) rowView.findViewById(R.id.txtChannelTitle);
    TextView txtVideoId = (TextView) rowView.findViewById(R.id.txtVideoId);
    TextView txtVideoDesc = (TextView) rowView.findViewById(R.id.txtVideoDesc);

    txtTitle.setText(videoTitle.get(position));
    Picasso.with(context).load(imgurl.get(position)).into(imgPhoto);
    txtChannelTitle.setText(channelTitle.get(position));
    txtVideoId.setText(videoId.get(position));
    txtVideoDesc.setText(videoDesc.get(position));
    return rowView;

;

缺少什么?

经过一些帮助后,我尝试创建(和使用)一个模型类,但我仍然没有任何进展,因为我不知道如何必须更改“CustomAdapter”上的代码才能正确使用此代码。

我的模型类如下:

公共类 FilteredVideoAdapter

private ArrayList<String> storedVideoTitle = null;
private ArrayList<String> storedVideoDesc = null;
private ArrayList<String> storedVideoId = null;
private ArrayList<String> storedChannelTitle = null;
private ArrayList<String> storedImgurl = null;

public FilteredVideoAdapter()



public ArrayList<String> getStoredVideoTitle() 
    return storedVideoTitle;


public void setStoredVideoTitle(ArrayList<String> storedVideoTitle) 
    this.storedVideoTitle = storedVideoTitle;


public ArrayList<String> getStoredVideoDesc() 
    return storedVideoDesc;


public void setStoredVideoDesc(ArrayList<String> storedVideoDesc) 
    this.storedVideoDesc = storedVideoDesc;


public ArrayList<String> getStoredVideoId() 
    return storedVideoId;


public void setStoredVideoId(ArrayList<String> storedVideoId) 
    this.storedVideoId = storedVideoId;


public ArrayList<String> getStoredChannelTitle() 
    return storedChannelTitle;


public void setStoredChannelTitle(ArrayList<String> storedChannelTitle) 
    this.storedChannelTitle = storedChannelTitle;


public ArrayList<String> getStoredImgurl() 
    return storedImgurl;


public void setStoredImgurl(ArrayList<String> storedImgurl) 
    this.storedImgurl = storedImgurl;


public FilteredVideoAdapter withFilteredVideoAdapter(
        ArrayList<String> storedVideoTitle,
        ArrayList<String> storedVideoDesc,
        ArrayList<String> storedVideoId,
        ArrayList<String> storedChannelTitle,
        ArrayList<String> storedImgurl)

    this.storedVideoTitle = storedVideoTitle;
    this.storedVideoDesc = storedVideoDesc;
    this.storedVideoId = storedVideoId;
    this.storedChannelTitle = storedChannelTitle;
    this.storedImgurl = storedImgurl;

    return this;

【问题讨论】:

您到底想在 listView 中搜索什么?是视频标题吗 @RahulChandrabhan,是的!但我需要在 VideoTitle 上进行过滤,但有关过滤视频的其他信息必须与之相关联。 lib4 发布的解决方案适用于 VideoTitle,但缺少 Listview 上的信息,如 VideoID、VideoDesc 等。 您必须为您的视频信息创建一个pojo,以便所有数据相互绑定并且易于使用,不要为每个信息创建单独的arraylist 【参考方案1】:

这是您必须在适配器内部执行的操作,您可能需要进行一些调整:-

 @Override
    public Filter getFilter() 
        return new Filter() 
            @Override
            protected FilterResults performFiltering(CharSequence constraint) 
                FilterResults results = new FilterResults();



                // If the constraint (search string/pattern) is null
                // or its length is 0, i.e., its empty then
                // we just set the `values` property to the
                // original contacts list which contains all of them
                if (constraint == null || constraint.length() == 0) 
                    results.values =   videoTitle;;
                    results.count = videoTitle.size();
                
                else 
                    // Some search copnstraint has been passed
                    // so let's filter accordingly
                    ArrayList<String> filteredTitle = new ArrayList<String>();

                    // We'll go through all the title and see
                    // if they contain the supplied string
                    for (String c : string) 
                        if (string.toUpperCase().contains( constraint.toString().toUpperCase() )) 
                            // if `contains` == true then add it
                            // to our filtered list
                            filteredTitle.add(c);
                        
                    

                    // Finally set the filtered values and size/count
                    results.values = filteredTitle;
                    results.count = filteredTitle.size();
                

                // Return our FilterResults object
                return results;
            
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) 
                mList = (ArrayList<String>) results.values;
                notifyDataSetChanged();
            
        ;
    

希望这会对你有所帮助。

【讨论】:

虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review @zapping 编辑了我的答案,添加了如何做的示例。欢迎投票。 @lib4,我做了一些调整:: " for (String c : videoTitle) if (c.toLowerCase().contains( constraint.toString().toLowerCase() ))" 并添加“ArrayList mList” 到 publishResults 方法和过滤器现在正在工作。我在设置 Log.i 时可以看到这一点,但适配器没有更新,所以过滤器工作正常,但没有在适配器中应用结果。 您在 publishResults() 中做什么,请您发布代码。发布结果我们必须通知数据集。确保我的答案中的 mList 应该是您的适配器列表。需要确保您的列表视图是从新更新的 mList 中读取的。 @安德烈 @lib4,按照我的 publishResults() ` @Override protected void publishResults(CharSequence 约束,FilterResults 结果) ArrayList mList = (ArrayList) results.values; for (String list: mList) videoTitle.add(list); //Log.i("filtro", "结果:" +list); notifyDataSetChanged(); ; `【参考方案2】:

你可以在不使用过滤器的情况下做到这一点,试试这个代码

您的活动代码

vendorSearchEt.addTextChangedListener(new TextWatcher() 
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) 

        

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) 

        

        @Override
        public void afterTextChanged(Editable s) 
            if (vendorSearchEt.getText().toString().length() == 0) 
                if (vendorsListAdapter != null) 
                    vendorsListAdapter.filter("");
                
             else 
                String text = vendorSearchEt.getText().toString().toLowerCase(Locale.getDefault());
                if (vendorsListAdapter != null) 
                    vendorsListAdapter.filter(text);
                
            

        
    );

适配器类

public class VendorsListAdapter extends BaseAdapter 

// Declare Variables \\
Context mContext;
LayoutInflater inflater;
private List<VendorsList> vendorsLists = null;
private ArrayList<VendorsList> arrayListVendorsList = null;
AppCompatActivity act;

public VendorsListAdapter(Context context,
                          List<VendorsList> vendorsLists) 
    mContext = context;
    this.vendorsLists = vendorsLists;
    arrayListVendorsList = new ArrayList<>(vendorsLists);
    inflater = LayoutInflater.from(mContext);
    act = (AppCompatActivity) context;



public class ViewHolder 

    TextView vendorNameTv;


@Override
public int getCount() 
    return vendorsLists.size();


@Override
public VendorsList getItem(int position) 
    return vendorsLists.get(position);


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


public View getView(final int position, View view, ViewGroup parent) 
    final ViewHolder holder;
    if (view == null) 
        holder = new ViewHolder();
        view = inflater.inflate(R.layout.lv_items_vendors_list, null);

        holder.vendorNameTv = view.findViewById(R.id.lv_items_vendors_name_tv);
        holder.vendorNameTv.setTypeface(StaticMethods.customFont(act, "Quicksand-Regular.otf"));

        view.setTag(holder);
     else 
        holder = (ViewHolder) view.getTag();
    

    holder.vendorNameTv.setText(vendorsLists.get(position).getVendorName());

    return view;


/**
 * Filter Class for item searching
 *
 * @param charText Text to be searched
 */
public void filter(String charText) 
    charText = charText.toLowerCase(Locale.getDefault());
    vendorsLists.clear();

    if (charText.length() == 0) 
        vendorsLists.addAll(arrayListVendorsList);
     else 
        for (VendorsList vendorsList : arrayListVendorsList) 
            if (vendorsList.getVendorName().toLowerCase(Locale.getDefault())
                    .contains(charText)) 
                vendorsLists.add(vendorsList);
            
        
    
    notifyDataSetChanged();

【讨论】:

以上是关于使用带有文本和图像的自定义适配器在列表视图中搜索的主要内容,如果未能解决你的问题,请参考以下文章

从编辑文本中过滤列表视图

如何使用 glide* 使用数组列表中的自定义适配器将图像设置为列表视图

如何为列表视图创建自定义光标适配器以用于图像和文本?

带有过滤器 Android 的自定义 Listview 适配器

使用自定义适配器的自定义对象

如何覆盖 ArrayAdapter add 方法来添加图像和文本视图?我有自定义数组适配器类