65.9K
CodeProject 正在变化。 阅读更多。
Home

图片列表视图过滤器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.78/5 (15投票s)

2013年8月11日

CPOL

3分钟阅读

viewsIcon

34224

downloadIcon

1454

如何在图像列表视图中进行过滤,请加入

引言

在智能手机中,很容易找到一个在列表视图中具有过滤功能的应用程序。 过滤功能将帮助用户轻松找到他想要查看的记录。 但是我们该怎么做呢?

我将提供一个简单的示例来帮助您清除它。

  • 显示足球运动员的列表。 每个玩家都将拥有
    • 玩家缩略图。
    • 玩家姓名。
  • 一个编辑文本框,用户可以在其中输入玩家姓名开头的字符。 根据输入的文本,列表将按玩家姓名过滤并显示。
    • 例如:如果用户想要查看 Ronaldo,他可以输入 R,然后是 o,...

希望您喜欢它:)

使用代码

准备显示列表视图数据

请参考以下代码来显示列表玩家数据。

public class MainActivity extends Activity {

    public ArrayList<FootballPlayer> listDatas = new ArrayList<MainActivity.FootballPlayer>();
    public FootballPlayerAdapter adapter;

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

        // Create dummy data
        String[] userNames = new String[] { "Ronaldo", "Zidance", "Cong Vinh",
                "Huynh Duc", "Gerrard", "Nagatomo", "Messi", "Minh Phuong",
                "neymar" };
        int[] playerDrawableResourceIds = new int[] { R.drawable.ronaldo,
                R.drawable.zindance, R.drawable.congvinh, R.drawable.huynhduc,
                R.drawable.gerrard, R.drawable.nagatomo, R.drawable.messi,
                R.drawable.minhphuong, R.drawable.neymar };

        // Prepare dummy data
        for (int i = 0; i < playerDrawableResourceIds.length; i++) {
            FootballPlayer footballPlayer = new FootballPlayer();
            footballPlayer.name = userNames[i];
            footballPlayer.imageResourceId = playerDrawableResourceIds[i];
            listDatas.add(footballPlayer);
        }

        ListView lv = (ListView) findViewById(R.id.lv);
        adapter = new FootballPlayerAdapter();
        lv.setAdapter(adapter);
    }

    private class FootballPlayerAdapter extends BaseAdapter {
        @Override
        public int getCount() {
            return listDatas.size();
        }

        @Override
        public FootballPlayer getItem(int position) {
            return listDatas.get(position);
        }

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            PlayerViewHolder holder;
            if (convertView == null) {
                convertView = (ViewGroup) LayoutInflater.from(
                        getApplicationContext()).inflate(
                        R.layout.football_player_item, null);
                holder = new PlayerViewHolder();
                holder.name = (TextView) convertView
                        .findViewById(R.id.player_name);
                holder.thumb = (ImageView) convertView
                        .findViewById(R.id.player_thumbnail);
                convertView.setTag(holder);
            } else {
                holder = (PlayerViewHolder) convertView.getTag();
            }
            holder.name.setText(getItem(position).name);
            holder.thumb.setImageResource(getItem(position).imageResourceId);
            return convertView;
        }
    }

    private static class PlayerViewHolder {
        public ImageView thumb;
        public TextView name;
    }

    public class FootballPlayer {
        /** Keep the id of resource file which is player's thumbnail. */
        public int imageResourceId;
        /** Player name. */
        public String name;
    }
} 

每个玩家项目的布局football_player_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="35dp"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/player_thumbnail"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="5dp" />

    <TextView
        android:id="@+id/player_name"
        android:textColor="@android:color/black"
        android:layout_width="match_parent"
        android:layout_height="35dp"
        android:layout_marginLeft="10dp"
        android:layout_weight="1"
        android:ellipsize="end"
        android:gravity="center_vertical"
        android:maxLines="1"
        android:orientation="vertical"
        android:singleLine="true"
        android:textSize="16sp" />

</LinearLayout>

上面的代码有一些虚拟数据,实际上您必须创建它并保存到可绘制资源文件夹。 对于我来说,没有比从网络下载更容易的方法了:D

int[] playerDrawableResourceIds = new int[] { R.drawable.ronaldo,
R.drawable.zindance, R.drawable.congvinh, R.drawable.huynhduc,
R.drawable.gerrard, R.drawable.nagatomo, R.drawable.messi,
R.drawable.minhphuong, R.drawable.neymar };  

这是结果

添加编辑文本以按玩家姓名过滤列表数据

  • 当输入文本到编辑文本时,它将自动过滤当前的列表数据。
  • 如果编辑文本为空,则显示完整列表

要过滤列表,除了  ArrayList<FootballPlayer> listDatas 用作适配器数据之外,创建一个备份数据列表 ArrayList<FootballPlayer> listBackupDatas

// Prepare dummy data
for (int i = 0; i < playerDrawableResourceIds.length; i++) {
    FootballPlayer footballPlayer = new FootballPlayer();
    footballPlayer.name = userNames[i];
    footballPlayer.imageResourceId = playerDrawableResourceIds[i];
    listDatas.add(footballPlayer);
    listBackupDatas.add(footballPlayer);
}  

将编辑文本添加到主布局,输入过滤文本将在其中。

EditText filterText  = (EditText) findViewById(R.id.filter_text);
filterText .addTextChangedListener(new TextWatcher() {
    @Override
    public void onTextChanged(CharSequence s, int arg1, int arg2,
            int arg3) {
        adapter.getFilter().filter(s.toString());
    }
    @Override
    public void beforeTextChanged(CharSequence arg0, int arg1,
            int arg2, int arg3) {
    }
    @Override
    public void afterTextChanged(Editable arg0) {
    }
}); 

上面的代码意味着,我们将控制filter编辑文本何时更改。 如果发生更改,我们将在player adapter中调用filter函数。

adapter.getFilter().filter(s.toString()); 

PlayerFilter类将按如下方式实现

private class PlayerFilter extends Filter {
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        FilterResults results = new FilterResults();
        // We implement here the filter logic
        ArrayList<FootballPlayer> filters = new ArrayList<FootballPlayer>();
        if (constraint == null || constraint.length() == 0) {
            // No filter implemented we return all the list
            for (FootballPlayer player : listBackupDatas) {
                filters.add(player);
            }
            results.values = filters;
            results.count = filters.size();
        } else {
            // We perform filtering operation
            for (FootballPlayer row : listBackupDatas) {
                if (((FootballPlayer) row).name.toUpperCase().startsWith(
                        constraint.toString().toUpperCase())) {
                    filters.add(row);
                }
            }
            results.values = filters;
            results.count = filters.size();
        }
        return results;
    }

    @Override
    protected void publishResults(CharSequence constraint,
            FilterResults results) {
        if (results.count == 0) {
            listDatas.clear();
            adapter.notifyDataSetChanged();
        } else {
            listDatas.clear();
            ArrayList<FootballPlayer> resultList = (ArrayList<FootballPlayer>) results.values;
            for (FootballPlayer row : resultList) {
                listDatas.add(row);
            }
            adapter.notifyDataSetChanged();
        }
    }
}

performFiltering

filterTextonTextChanged  的回调时,将调用此方法。

  • filterText的输入文本是参数 constraint
  • 基于constraint文本,将返回合适的数据。 

通过此示例,它将在listBackupDatas中找到姓名以constraint开头的玩家,并添加到数组列表中。

该方法的返回数据是一个 FilterResults 对象。 它包含

  • values:包含nameconstraint文本开头的玩家的arraylist
  • count:上述arraylist的数量。

publishResults

调用此方法以将过滤器结果通知给UI线程。 使用此示例

  • 如果从performFiltering返回的数据,则列表视图listDatas的数据将被清除,并且adapter.notifyDataSetChanged()。 在这种情况下,列表当然将为空。
  • 否则,基于从performFiltering方法返回的 FilterResults ,将 FilterResults.values 的所有玩家添加到adapter.listDatas,然后调用adapter.notifyDataSetChanged()以刷新列表视图。

最终结果如下

关注点

根据我的经验,如果对于每个过滤器列表,我们创建两个列表数据,一个用于显示,另一个用于备份,那就更好了。 这将有助于轻松控制。 在此示例中,它们是

public ArrayList<FootballPlayer> listDatas = new ArrayList<MainActivity.FootballPlayer>();
public ArrayList<FootballPlayer> listBackupDatas = new ArrayList<MainActivity.FootballPlayer>(); 
  • listDatas 将用作适配器的主要数据。 它的数据将在过滤时更改。
  • listBackupDatas 用作备份数据。

有关更多信息,您可以使用此技巧中的编辑文本,以获得带有搜索图标的编辑文本。:)

历史

  • 2013 - 08 - 11:第一个版本。
© . All rights reserved.