SearchView 学习_0
来源:互联网 发布:iphone随机抽奖软件 编辑:程序博客网 时间:2024/06/02 03:51
1. 基本原理:SearchView是android中一个搜索框组件,它不是一个单独的view,而是一个LinearLayout布局,包括表示Search图标和清除图标等其它图标的imageView、具有下拉建议列表的AutoCompleteTextView等,有时候我们需要对SearchView做一些特定的修改,而SearchView本身却又没有提供相关的接口,这时需要对SearchView进行自顶向下的深度遍历,提取它的每一个子孙view,如果只要对特定类型的view进行修改,只需根据view的类型来提取(viewinstanceof XXXView),若要提取特定的某一个view,则需要知道该view的id号,可以从SearchView源代码找到。
search_view.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/search_bar" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <!-- This is actually used for the badge icon *or* the badge label (or neither) --> <TextView android:id="@+id/search_badge" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center_vertical" android:layout_marginBottom="2dip" android:drawablePadding="0dip" android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="?android:attr/textColorPrimary" android:visibility="gone" /> <ImageView android:id="@+id/search_button" style="?android:attr/actionButtonStyle" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="center_vertical" android:src="?android:attr/searchViewSearchIcon" android:contentDescription="@string/searchview_description_search" /> <LinearLayout android:id="@+id/search_edit_frame" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:layout_gravity="center_vertical" android:layout_marginTop="4dip" android:layout_marginBottom="4dip" android:layout_marginLeft="8dip" android:layout_marginRight="8dip" android:orientation="horizontal"> <ImageView android:id="@+id/search_mag_icon" android:layout_width="@dimen/dropdownitem_icon_width" android:layout_height="wrap_content" android:scaleType="centerInside" android:layout_marginLeft="@dimen/dropdownitem_text_padding_left" android:layout_gravity="center_vertical" android:src="?android:attr/searchViewSearchIcon" android:visibility="gone" /> <!-- Inner layout contains the app icon, button(s) and EditText --> <LinearLayout android:id="@+id/search_plate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:layout_gravity="center_vertical" android:orientation="horizontal" android:background="?android:attr/searchViewTextField"> <view class="android.widget.SearchView$SearchAutoComplete" android:id="@+id/search_src_text" android:layout_height="36dip" android:layout_width="0dp" android:layout_weight="1" android:minWidth="@dimen/search_view_text_min_width" android:layout_gravity="bottom" android:paddingLeft="@dimen/dropdownitem_text_padding_left" android:paddingRight="@dimen/dropdownitem_text_padding_right" android:singleLine="true" android:ellipsize="end" android:background="@null" android:inputType="text|textAutoComplete|textNoSuggestions" android:imeOptions="actionSearch" android:dropDownHeight="wrap_content" android:dropDownAnchor="@id/search_edit_frame" android:dropDownVerticalOffset="0dip" android:dropDownHorizontalOffset="0dip" android:contentDescription="@string/searchview_description_query" /> <ImageView android:id="@+id/search_close_btn" android:layout_width="wrap_content" android:layout_height="match_parent" android:paddingLeft="8dip" android:paddingRight="8dip" android:layout_gravity="center_vertical" android:background="?android:attr/selectableItemBackground" android:src="?android:attr/searchViewCloseIcon" android:focusable="true" android:contentDescription="@string/searchview_description_clear" /> </LinearLayout> <LinearLayout android:id="@+id/submit_area" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="match_parent" android:background="?android:attr/searchViewTextFieldRight"> <ImageView android:id="@+id/search_go_btn" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="center_vertical" android:paddingLeft="16dip" android:paddingRight="16dip" android:background="?android:attr/selectableItemBackground" android:src="?android:attr/searchViewGoIcon" android:visibility="gone" android:focusable="true" android:contentDescription="@string/searchview_description_submit" /> <ImageView android:id="@+id/search_voice_btn" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="center_vertical" android:paddingLeft="16dip" android:paddingRight="16dip" android:src="?android:attr/searchViewVoiceIcon" android:background="?android:attr/selectableItemBackground" android:visibility="gone" android:focusable="true" android:contentDescription="@string/searchview_description_voice" /> </LinearLayout> </LinearLayout></LinearLayout>
<h2>2. 我的使用格式:</h2><div> 根据我自己百度的资料,searchview有两种使用方式:1:放置到actionBar的位置。2:直接放置到布局中。自己跑了两个程序,感觉searchview放哪里都一样。</div><div> <strong>下面以放置到布局为例:</strong></div><div> 程序功能:实现一个SD卡的浏览器功能。listview中的数据就是当前目录下所有文件的(图标+文件名)。在搜索框输入搜索文本,listview内的数据刷新,只显示含义搜索文本的条目。(程序有点小bug,部分功能没实现,但能够说明searchview的大多数的基本用法)</div><div> 下面的代码copy到程序就可跑(文件名字有需要自己改动的地方:布局代码文件的文件名和主程序的文件名,图片资源需你自己更换一下)</div><div> 布局代码:<pre style="font-size: 9pt; color: rgb(169, 183, 198); font-family: 宋体; background-color: rgb(43, 43, 43);"><span style="color: rgb(152, 118, 170); "><em>activity_sdpathbrowse1.xml</em></span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(240, 240, 240);"> </span>
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_height="45dp" android:background="#000000"> <ImageView android:id="@+id/iv_back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:padding="10dp" android:src="@mipmap/back" /> <TextView android:id="@+id/tv_path" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toRightOf="@+id/iv_back" android:text="555555555555555555" android:textColor="#ffffff" /> </RelativeLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="60dp" android:background="#f2f2f2f2" android:orientation="vertical"> <SearchView android:id="@+id/sv_" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="8dp" android:background="@drawable/shape_bg_search" android:imeOptions="actionSearch" android:inputType="text" android:queryHint="请输入您要查找的内容" tools:ignore="NewApi" /> </LinearLayout> <ListView android:id="@+id/lv_list" android:layout_width="match_parent" android:layout_height="wrap_content"></ListView></LinearLayout>
主程序代码:
package com.SDPathBrowse;import java.io.File;import java.io.IOException;import java.lang.reflect.Field;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import android.annotation.SuppressLint;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Bundle;import android.os.Environment;import android.text.TextUtils;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.BaseAdapter;import android.widget.Filter;import android.widget.Filterable;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.ListView;import android.widget.RelativeLayout;import android.widget.SearchView;import android.widget.TextView;import android.widget.Toast;import android.view.LayoutInflater;import android.view.inputmethod.InputMethodManager;import engineering.R;/** * @version 1.0 */@SuppressLint("NewApi")public class SDPathBrowse1 extends Activity implements SearchView.OnQueryTextListener { //显示本路径下所有的文件夹和文件. ListView listView; //标题头,显示当前路径. TextView textView; // 记录当前的父文件夹 File currentParent; // 记录当前路径下的所有文件的文件数组 File[] currentFiles; //返回图标 ImageView parent; SearchView sv_; //listItems存储listview要加载的数据,根据serachView的输入,listView加载部分数据或全部数据. List<Map<String, Object>> listItems; //tmplistItems是listItem全部数据的拷贝。 List<Map<String, Object>> tmplistItems; MyAdapter myAdapter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sdpathbrowse1); initView(); initData(); initListener(); } public void initView() { // 获取列出全部文件的ListView listView = (ListView) findViewById(R.id.lv_list); listView.setTextFilterEnabled(true); //标题头,显示当前路径. textView = (TextView) findViewById(R.id.tv_path); // 返回上一级目录的 图标 parent = (ImageView) findViewById(R.id.iv_back); sv_ = (SearchView) findViewById(R.id.sv_); //searchView输入后 右面有搜索按钮.false则没有. sv_.setSubmitButtonEnabled(false); //搜索图标是否在输入框中 sv_.setIconifiedByDefault(true); // 创建一个List集合,List集合的元素是Map listItems = new ArrayList<Map<String, Object>>(); tmplistItems = new ArrayList<Map<String, Object>>(); //用到的数据集合(listItems)在本类中是全局变量,adapter类写到了同一个文件中。若不在同一个文件中,adapter的构造函数需传递数据集合,用于本文件的逻辑就需要改变。 myAdapter = new MyAdapter(this); listView.setAdapter(myAdapter); } public void initData() { // 获取系统的SD卡的目录,两段代码都可。 //File root = new File("/mnt/sdcard/"); File root = Environment.getExternalStorageDirectory(); Log.i("lyw", root.toString());//storage/emulated/0 // 如果 SD卡存在 if (root.exists()) { currentParent = root; //获取当前文件夹下的所有文件和文件夹 currentFiles = root.listFiles(); trimCurrentFiles(currentFiles); } } @SuppressLint("NewApi") public void initListener() { // 为ListView的列表项的单击事件绑定监听器 listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // 用户单击了文件,直接返回,不做任何处理 if (currentFiles[position].isFile()) { //此处可做对文件的各种操作,如对MP3的播放,图片的预览(预览界面可滑动),文本的打开等。 return; } // 获取用户点击的文件夹下的所有文件 File[] tmp = currentFiles[position].listFiles(); if (tmp == null || tmp.length == 0) { Toast.makeText(SDPathBrowse1.this , "当前路径不可访问或该路径下没有文件", Toast.LENGTH_SHORT).show(); } else { // 获取用户单击的列表项对应的文件夹,设为当前的父文件夹 currentParent = currentFiles[position]; // 保存当前的父文件夹内的全部文件和文件夹(即将临时tmp赋值给currentFiles). currentFiles = tmp; trimCurrentFiles(currentFiles); } } }); parent.setOnClickListener(new OnClickListener() { @Override public void onClick(View source) { try { String currentPath = currentParent.getCanonicalPath(); Log.i("lyw", currentPath); if (!currentParent.getCanonicalPath()//返回规范路径名 .equals("/")) { // 获取上一级目录 currentParent = currentParent.getParentFile(); // 列出当前目录下所有文件 currentFiles = currentParent.listFiles(); trimCurrentFiles(currentFiles); } } catch (IOException e) { e.printStackTrace(); } } }); //为searchview设置监听事件 sv_.setOnQueryTextListener(this); } /** * 初始化,返回上一级路径,进入下一级路径, * 整理数据,放置到listItems中。然后adapter.notifyDataSetChanged(). */ private void trimCurrentFiles(File[] files) { listItems.clear(); Map<String, Object> listItem; for (int i = 0; i < files.length; i++) { listItem = new HashMap<String, Object>(); // 如果当前File是文件夹,使用folder图标;否则使用file图标 if (files[i].isDirectory()) { listItem.put("icon", R.mipmap.folder); } else { listItem.put("icon", R.mipmap.file); } listItem.put("fileName", files[i].getName()); // 添加List项 listItems.add(listItem); } tmplistItems.addAll(listItems); myAdapter.notifyDataSetChanged();//每次listItems中的数据改变,通知adapter. try { textView.setText("当前路径为:" + currentParent.getCanonicalPath()); } catch (IOException e) { e.printStackTrace(); } } @Override public boolean onQueryTextChange(String s) { //当搜索文字发生改变,此处执行的代码与activity_searchView相应位置执行的代码做比对,同一功能两种不同的实现。 if (TextUtils.isEmpty(s)) { listView.clearTextFilter(); } else { listView.setFilterText(s.toString()); } return true; } //单击搜索按钮时激发该方法 @Override public boolean onQueryTextSubmit(String s) { return true; } public class MyAdapter extends BaseAdapter implements Filterable { private MyFilter myFilter; // private List<Map<String, Object>> list_Items; private LayoutInflater mInflater; public ImageView iv; public TextView tv; Bitmap bitmap; public MyAdapter(Context c) { mInflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public int getCount() { if (listItems == null) return 0; return listItems.size(); } @Override public View getView(int position, View convertView, ViewGroup Parent) { convertView = mInflater.inflate(R.layout.activity_sdpathbrowse1_item, null); iv = (ImageView) convertView.findViewById(R.id.iv_folder); tv = (TextView) convertView.findViewById(R.id.tv_filename); bitmap = BitmapFactory.decodeResource(getResources(), (Integer) listItems.get(position).get("icon")); iv.setImageBitmap(bitmap); tv.setText((CharSequence) listItems.get(position).get("fileName")); return convertView; } @Override public long getItemId(int position) { return position; } @Override public Object getItem(int position) { return listItems.get(position); } @Override public Filter getFilter() { if (null == myFilter) { myFilter = new MyFilter(); } return myFilter; } class MyFilter extends Filter { @Override // 该方法在子线程中执行 // 自定义过滤规则 protected FilterResults performFiltering(CharSequence charSequence) { FilterResults results = new FilterResults(); List<Map<String, Object>> newValues = new ArrayList<Map<String, Object>>(); String filterString = charSequence.toString().trim(); if (TextUtils.isEmpty(filterString)) { newValues = tmplistItems; } else { for (int i = 0; i < tmplistItems.size(); i++) { String str = (String) tmplistItems.get(i).get("fileName"); if (-1 != str.indexOf(filterString)) { newValues.add(tmplistItems.get(i)); } } } results.values = newValues; results.count = newValues.size(); return results; } @Override protected void publishResults(CharSequence charSequence, FilterResults filterResults) { listItems = (List<Map<String, Object>>) filterResults.values; if (filterResults.count > 0) { myAdapter.notifyDataSetChanged(); } else { myAdapter.notifyDataSetInvalidated(); } } } }}
架构 简单的说明:
public class SDPathBrowse1 extends Activity implements SearchView.OnQueryTextListener
本类implement SearchView.OnQueryTextListener
然后实现接口中未实现的方法:
public boolean onQueryTextChange(String s) {if (TextUtils.isEmpty(s)) { listView.clearTextFilter(); } else { listView.setFilterText(s.toString()); } return true;}public boolean onQueryTextSubmit(String s) {}在onQueryTextChange()中,listView调用setFilterText()方法。此方法是listView通过适配中getFilter()方法得到的。所以上面的MyAdapter类实现了 Filterable接口。
MyFilter继承Filter 作为MyAdapter的内部类。
至此,这就是整个程序的逻辑架构。
0 0
- SearchView 学习_0
- Linux_学习笔记_0
- 强化学习读书笔记_0
- 强化学习读书笔记_0
- 强化学习读书笔记_0
- 强化学习读书笔记_0
- 强化学习读书笔记_0
- 强化学习读书笔记_0
- 强化学习读书笔记_0
- 强化学习读书笔记_0
- JavaScript 学习笔记_0
- JavaScript 学习笔记_0
- SearchView
- SearchView
- searchview
- SearchView
- SearchView
- SearchView
- 项目1问题
- jQuery中html()、text()、val()的区别
- HDU 2196
- 软考——计算机系统知识
- IIS runs out of work items and causes RPC failures when connecting to a remote UNC path
- SearchView 学习_0
- Hibernate获取表配置信息包括Common注解信息
- spring
- mysql my.cnf文件配置
- pentaho bi server5.4MySQL部署
- 非常好的理解遗传算法的例子
- Cocos2d-x 3.X, IOS版添加广点通广告平台
- 整理hibernate.cfg.xml 与 applicationContext之间的配置方式
- windows命令行问题