Android搜索框通用版

之前项目总会遇到很多搜索框类的功能,虽然不是很复杂,不过每次都要去自己处理数据,并且去处理搜索框的变化,写起来也比较麻烦,今天来做一个比较简单的通用搜索栏。

先看下效果图:

没什么特别的,只是今天要做的就是简单的把搜索框的内容封装一下.

一、分析功能

先考虑一下,搜索框一般都是由一个搜索图标(一般都是一个放大镜),一个输入框和一个清除按钮组成.然后会通过监听输入框的变化去处理清除按钮的显示和隐藏并且去过滤相关的数据.最后去刷新适配器,显示过滤后的数据.基本上搜索框的功能都大同小异.
有了上边的分析,我们可以去提取出一个通用的搜索框布局,然后写一个自定义ViewGroup去处理相关的页面显示等问题.

二、具体实现

先来写一些自定的属性,方便之后使用,新建一个attr文件并定义自定义属性如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <!--搜索图标左边margin-->
  <attr name="SearchBarIconMarginLeft" format="dimension"/>
  <!--搜索图标右边margin-->
  <attr name="SearchBarIconMarginRight" format="dimension"/>
  <!--搜索图标-->
  <attr name="SearchBarIconSrc" format="reference"/>
  <!--清除图标左边margin-->
  <attr name="ClearIconMarginLeft" format="dimension"/>
  <!--清除图标右边margin-->
  <attr name="ClearIconMarginRight" format="dimension"/>
  <!--清除图标-->
  <attr name="ClearIconSrc" format="reference"/>
  <!--搜索文字大小-->
  <attr name="SearchTextSize" format="dimension"/>
  <!--搜索文字颜色-->
  <attr name="SearchTextColor" format="color"/>
  <declare-styleable name="CommolySearchView">
    <attr name="SearchBarIconMarginLeft"/>
    <attr name="SearchBarIconMarginRight"/>
    <attr name="SearchBarIconSrc"/>
    <attr name="ClearIconMarginLeft"/>
    <attr name="ClearIconMarginRight"/>
    <attr name="ClearIconSrc"/>
    <attr name="SearchTextSize"/>
    <attr name="SearchTextColor"/>
  </declare-styleable>

</resources>

然后写一下搜索栏的布局searchview_layout.xml:

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

  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical"
    android:orientation="horizontal"
    >

    <ImageView
      android:id="@+id/iv_search_icon"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_gravity="center_vertical"
      android:src="@mipmap/search_bar_icon"
      android:layout_marginRight="8dp"
      />

    <EditText
      android:id="@+id/et_search"
      android:layout_width="0dp"
      android:layout_height="match_parent"
      android:layout_weight="1"
      android:background="@null"
      android:singleLine="true"
      />

    <ImageView
      android:id="@+id/iv_search_clear"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_gravity="center_vertical"
      android:src="@mipmap/search_clear_icon"
      android:visibility="gone"
      />
  </LinearLayout>

</LinearLayout>

布局很简单,就是一个搜索图标加上一个输入框和一个清除图标,下边来写一下具体的实现,建立一个CommolySearchView继承自LinearLayout即可,先来定义一些属性,获取自定义属性并且绑定布局文件.代码如下:

/**
 * Created by junweiliu on 16/5/31.
 */
public class CommolySearchView<T> extends LinearLayout {
  /**
   * 上下文
   */
  private Context mContext;
  /**
   * 编辑框
   */
  private EditText mEditText;
  /**
   * 清除按钮
   */
  private ImageView mClearImg;
  /**
   * 搜索图标
   */
  private ImageView mSearchBarImg;
  /**
   * 适配器
   */
  private BaseAdapter mAdapter;
  /**
   * 数据源
   */
  private List<T> mDatas = new ArrayList<T>();
  /**
   * 数据源副本
   */
  private List<T> mDupDatas = new ArrayList<T>();

  /**
   * 筛选后的数据源
   */
  private List<T> mFilterDatas = new ArrayList<T>();
  /**
   * 筛选后的数据源副本
   */
  private List<T> mDupFilterDatas = new ArrayList<T>();
  /**
   * 搜索图标
   */
  private Bitmap mSearchIcon;
  /**
   * 搜索框距离左边边距
   */
  private int mSearchIconMarginLeft;
  /**
   * 搜索框距离右边边距
   */
  private int mSearchIconMarginRight;
  /**
   * 清除图标
   */
  private Bitmap mClearIcon;
  /**
   * 清除图标距离左边边距
   */
  private int mClearIconMarginLeft;
  /**
   * 清除图标距离右边边距
   */
  private int mClearIconMarginRight;
  /**
   * 搜索文字大小
   */
  private int mSearchTextSize;
  /**
   * 搜索文字颜色
   */
  private int mSearchTextColor;

  public CommolySearchView(Context context) {
    this(context, null);
  }

  public CommolySearchView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public CommolySearchView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    mContext = context;
    // 自定义属性
    TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CommolySearchView);
    Drawable searchD = ta.getDrawable(R.styleable.CommolySearchView_SearchBarIconSrc);
    mSearchIcon = drawableToBitamp(searchD);
    mSearchIconMarginLeft = px2dip(context, ta.getDimensionPixelOffset(R.styleable.CommolySearchView_SearchBarIconMarginLeft, 0));
    mSearchIconMarginRight = px2dip(context, ta.getDimensionPixelOffset(R.styleable.CommolySearchView_SearchBarIconMarginRight, 0));
    Drawable clearD = ta.getDrawable(R.styleable.CommolySearchView_ClearIconSrc);
    mClearIcon = drawableToBitamp(clearD);
    mClearIconMarginLeft = px2dip(context, ta.getDimensionPixelOffset(R.styleable.CommolySearchView_ClearIconMarginLeft, 0));
    mClearIconMarginRight = px2dip(context, ta.getDimensionPixelOffset(R.styleable.CommolySearchView_ClearIconMarginRight, 0));
    mSearchTextSize = px2sp(context, ta.getDimensionPixelOffset(R.styleable.CommolySearchView_SearchTextSize, 0));
    mSearchTextColor = ta.getColor(R.styleable.CommolySearchView_SearchTextColor, 0);
    ta.recycle();
    // 绑定布局文件
    LayoutInflater.from(context).inflate(R.layout.searchview_layout, this);
    initView();
  }

可以看到我们使用了泛型,目的是为了处理不同的数据源类型,接下来需要初始化控件,看一下initView方法:

  /**
   * 初始化控件
   */
  private void initView() {
    mEditText = (EditText) findViewById(R.id.et_search);
    mClearImg = (ImageView) findViewById(R.id.iv_search_clear);
    mSearchBarImg = (ImageView) findViewById(R.id.iv_search_icon);
    // 处理自定义属性
    if (0 != mSearchIconMarginLeft || 0 != mSearchIconMarginRight) {
      mSearchBarImg.setPadding(mSearchIconMarginLeft, 0, mSearchIconMarginRight, 0);
    }
    if (0 != mClearIconMarginLeft || 0 != mClearIconMarginRight) {
      mClearImg.setPadding(mClearIconMarginLeft, 0, mClearIconMarginRight, 0);
    }
    if (null != mSearchIcon) {
      mSearchBarImg.setImageBitmap(mSearchIcon);
    }
    if (null != mClearIcon) {
      mClearImg.setImageBitmap(mClearIcon);
    }
    if (0 != mSearchTextSize) {
      mEditText.setTextSize(mSearchTextSize);
    }
    if (0 != mSearchTextColor) {
      mEditText.setTextColor(mSearchTextColor);
    }
    // 清空按钮处理事件
    mClearImg.setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View view) {

      }
    });
    // 搜索栏处理事件
    mEditText.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) {

      }

      @Override
      public void afterTextChanged(Editable editable) {

      }
    });
  }

这样初始化控件的任务也完成了,下面就是处理具体逻辑的部分,我们打算在CommonlySearchView完成清除按钮的显示隐藏,编辑框内容的处理,对适配器进行刷新的功能,具体数据的筛选工作,使用一个回调接口,由使用者去进行筛选,只需要获取筛选后的数据即可,然后通过筛选后的数据,去刷新适配器来完成要实现的功能.所以要对外提供一些方法,来获取到适配器,及一些数据源.

  /**
   * 设置数据源
   *
   * @param datas
   */
  public void setDatas(List<T> datas) {
    if (null == datas) {
      return;
    }
    if (null != mDatas) {
      mDatas.clear();
    }
    if (null != mDupDatas) {
      mDupDatas.clear();
    }
    mDatas = datas;
    mDupDatas.addAll(mDatas);
  }

  /**
   * 设置适配器
   *
   * @param adapter
   */
  public void setAdapter(BaseAdapter adapter) {
    if (null == adapter) {
      return;
    }
    mAdapter = adapter;
  }

获取到适配器及数据源,并且做了相关数据备份工作.

接着要提供一个回调接口来得到筛选后的数据.

  /**
   * 回调接口
   *
   * @param <T>
   */
  interface SearchDatas<T> {
    /**
     * 参数一:全部数据,参数二:筛选后的数据,参数三:输入的内容
     *
     * @param datas
     * @param filterdatas
     * @param inputstr
     * @return 筛选后的数据
     */
    List<T> filterDatas(List<T> datas, List<T> filterdatas, String inputstr);
  }

  /**
   * 回调
   */
  private SearchDatas<T> mListener;

  /**
   * 设置回调
   *
   * @param listener
   */
  public void setSearchDataListener(SearchDatas<T> listener) {
    mListener = listener;

  }

同样需要对外提供一个方法,以便使用者获取到筛选后的数据去做相关操作.

  /**
   * 获取筛选后的数据
   *
   * @return
   */
  public List<T> getFilterDatas() {
    return (null != mDupFilterDatas && mDupFilterDatas.size() > 0) ? mDupFilterDatas : mDupDatas;
  }

得到数据之后,就是在输入框和清除按钮的监听方法中去做相关处理就可以了,完整代码如下:

package com.example.junweiliu.commonlysearchview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;

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

/**
 * Created by junweiliu on 16/5/31.
 */
public class CommolySearchView<T> extends LinearLayout {
  /**
   * 上下文
   */
  private Context mContext;
  /**
   * 编辑框
   */
  private EditText mEditText;
  /**
   * 清除按钮
   */
  private ImageView mClearImg;
  /**
   * 搜索图标
   */
  private ImageView mSearchBarImg;
  /**
   * 适配器
   */
  private BaseAdapter mAdapter;
  /**
   * 数据源
   */
  private List<T> mDatas = new ArrayList<T>();
  /**
   * 数据源副本
   */
  private List<T> mDupDatas = new ArrayList<T>();

  /**
   * 筛选后的数据源
   */
  private List<T> mFilterDatas = new ArrayList<T>();
  /**
   * 筛选后的数据源副本
   */
  private List<T> mDupFilterDatas = new ArrayList<T>();
  /**
   * 搜索图标
   */
  private Bitmap mSearchIcon;
  /**
   * 搜索框距离左边边距
   */
  private int mSearchIconMarginLeft;
  /**
   * 搜索框距离右边边距
   */
  private int mSearchIconMarginRight;
  /**
   * 清除图标
   */
  private Bitmap mClearIcon;
  /**
   * 清除图标距离左边边距
   */
  private int mClearIconMarginLeft;
  /**
   * 清除图标距离右边边距
   */
  private int mClearIconMarginRight;
  /**
   * 搜索文字大小
   */
  private int mSearchTextSize;
  /**
   * 搜索文字颜色
   */
  private int mSearchTextColor;

  /**
   * 回调接口
   *
   * @param <T>
   */
  interface SearchDatas<T> {
    /**
     * 参数一:全部数据,参数二:筛选后的数据,参数三:输入的内容
     *
     * @param datas
     * @param filterdatas
     * @param inputstr
     * @return
     */
    List<T> filterDatas(List<T> datas, List<T> filterdatas, String inputstr);
  }

  /**
   * 回调
   */
  private SearchDatas<T> mListener;

  /**
   * 设置回调
   *
   * @param listener
   */
  public void setSearchDataListener(SearchDatas<T> listener) {
    mListener = listener;

  }

  public CommolySearchView(Context context) {
    this(context, null);
  }

  public CommolySearchView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public CommolySearchView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    mContext = context;
    // 自定义属性
    TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CommolySearchView);
    Drawable searchD = ta.getDrawable(R.styleable.CommolySearchView_SearchBarIconSrc);
    mSearchIcon = drawableToBitamp(searchD);
    mSearchIconMarginLeft = px2dip(context, ta.getDimensionPixelOffset(R.styleable.CommolySearchView_SearchBarIconMarginLeft, 0));
    mSearchIconMarginRight = px2dip(context, ta.getDimensionPixelOffset(R.styleable.CommolySearchView_SearchBarIconMarginRight, 0));
    Drawable clearD = ta.getDrawable(R.styleable.CommolySearchView_ClearIconSrc);
    mClearIcon = drawableToBitamp(clearD);
    mClearIconMarginLeft = px2dip(context, ta.getDimensionPixelOffset(R.styleable.CommolySearchView_ClearIconMarginLeft, 0));
    mClearIconMarginRight = px2dip(context, ta.getDimensionPixelOffset(R.styleable.CommolySearchView_ClearIconMarginRight, 0));
    mSearchTextSize = px2sp(context, ta.getDimensionPixelOffset(R.styleable.CommolySearchView_SearchTextSize, 0));
    mSearchTextColor = ta.getColor(R.styleable.CommolySearchView_SearchTextColor, 0);
    ta.recycle();
    // 绑定布局文件
    LayoutInflater.from(context).inflate(R.layout.searchview_layout, this);
    initView();
  }

  /**
   * 初始化控件
   */
  private void initView() {
    mEditText = (EditText) findViewById(R.id.et_search);
    mClearImg = (ImageView) findViewById(R.id.iv_search_clear);
    mSearchBarImg = (ImageView) findViewById(R.id.iv_search_icon);
    // 处理自定义属性
    if (0 != mSearchIconMarginLeft || 0 != mSearchIconMarginRight) {
      mSearchBarImg.setPadding(mSearchIconMarginLeft, 0, mSearchIconMarginRight, 0);
    }
    if (0 != mClearIconMarginLeft || 0 != mClearIconMarginRight) {
      mClearImg.setPadding(mClearIconMarginLeft, 0, mClearIconMarginRight, 0);
    }
    if (null != mSearchIcon) {
      mSearchBarImg.setImageBitmap(mSearchIcon);
    }
    if (null != mClearIcon) {
      mClearImg.setImageBitmap(mClearIcon);
    }
    if (0 != mSearchTextSize) {
      mEditText.setTextSize(mSearchTextSize);
    }
    if (0 != mSearchTextColor) {
      mEditText.setTextColor(mSearchTextColor);
    }
    // 清空按钮处理事件
    mClearImg.setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View view) {
        mEditText.setText("");
        mClearImg.setVisibility(View.GONE);
        if (null != mDatas) {
          mDatas.clear();
        }
        mDatas.addAll(mDupDatas);
        mAdapter.notifyDataSetChanged();
        reSetDatas();
      }
    });
    // 搜索栏处理事件
    mEditText.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) {
        // 获取筛选后的数据
        mFilterDatas = mListener.filterDatas(mDupDatas, mFilterDatas, charSequence.toString());
        if (charSequence.toString().length() > 0 && !charSequence.toString().equals("")) {
          mClearImg.setVisibility(View.VISIBLE);
        } else {
          mClearImg.setVisibility(View.GONE);
        }
        if (null != mDatas) {
          mDatas.clear();
        }
        mDatas.addAll(mFilterDatas);
        mAdapter.notifyDataSetChanged();
        reSetDatas();
      }

      @Override
      public void afterTextChanged(Editable editable) {

      }
    });
  }

  /**
   * 获取筛选后的数据
   *
   * @return
   */
  public List<T> getFilterDatas() {
    return (null != mDupFilterDatas && mDupFilterDatas.size() > 0) ? mDupFilterDatas : mDupDatas;
  }

  /**
   * 重置数据
   */
  private void reSetDatas() {
    if (null != mFilterDatas) {
      if (null != mDupFilterDatas) {
        mDupFilterDatas.clear();
        mDupFilterDatas.addAll(mFilterDatas);
      }
      mFilterDatas.clear();
    }
  }

  /**
   * 设置数据源
   *
   * @param datas
   */
  public void setDatas(List<T> datas) {
    if (null == datas) {
      return;
    }
    if (null != mDatas) {
      mDatas.clear();
    }
    if (null != mDupDatas) {
      mDupDatas.clear();
    }
    mDatas = datas;
    mDupDatas.addAll(mDatas);
  }

  /**
   * 设置适配器
   *
   * @param adapter
   */
  public void setAdapter(BaseAdapter adapter) {
    if (null == adapter) {
      return;
    }
    mAdapter = adapter;
  }

  /**
   * drawable转bitmap
   *
   * @param drawable
   * @return
   */
  private Bitmap drawableToBitamp(Drawable drawable) {
    if (null == drawable) {
      return null;
    }
    if (drawable instanceof BitmapDrawable) {
      BitmapDrawable bd = (BitmapDrawable) drawable;
      return bd.getBitmap();
    }
    int w = drawable.getIntrinsicWidth();
    int h = drawable.getIntrinsicHeight();
    Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, w, h);
    drawable.draw(canvas);
    return bitmap;
  }

  /**
   * 将px值转换为dip或dp值,保证尺寸大小不变
   *
   * @param pxValue
   * @return
   * @param(DisplayMetrics类中属性density)
   */
  public int px2dip(Context context, float pxValue) {
    final float scale = context.getResources().getDisplayMetrics().density;
    return (int) (pxValue / scale + 0.5f);
  }

  /**
   * 将px值转换为sp值,保证文字大小不变
   *
   * @param pxValue
   * @return
   */
  public static int px2sp(Context context, float pxValue) {
    final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
    return (int) (pxValue / fontScale + 0.5f);
  }
}

三、完整代码及使用

换一个复杂点的listview来使用一下.很简单,就是普通的Listview绑定数据,我们结合CommolySearchView来使用一下.

实体Bean
SanGuoBean:

package com.example.junweiliu.commonlysearchview.bean;

/**
 * Created by junweiliu on 16/6/1.
 */
public class SanGuoBean {
  /**
   * 名称
   */
  private String sgName;
  /**
   * 描述
   */
  private String sgDescribe;
  /**
   * 头像
   */
  private int sgHeadBp;
  /**
   * 字
   */
  private String sgPetName;

  public SanGuoBean() {
  }

  public SanGuoBean(String sgName, String sgDescribe, int sgHeadBp, String sgPetName) {
    this.sgName = sgName;
    this.sgDescribe = sgDescribe;
    this.sgHeadBp = sgHeadBp;
    this.sgPetName = sgPetName;
  }

  public String getSgName() {
    return sgName;
  }

  public void setSgName(String sgName) {
    this.sgName = sgName;
  }

  public String getSgDescribe() {
    return sgDescribe;
  }

  public void setSgDescribe(String sgDescribe) {
    this.sgDescribe = sgDescribe;
  }

  public int getSgHeadBp() {
    return sgHeadBp;
  }

  public void setSgHeadBp(int sgHeadBp) {
    this.sgHeadBp = sgHeadBp;
  }

  public String getSgPetName() {
    return sgPetName;
  }

  public void setSgPetName(String sgPetName) {
    this.sgPetName = sgPetName;
  }
}

适配器每项布局文件sg_item:

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

  <ImageView
    android:id="@+id/iv_sghead"
    android:layout_width="80dp"
    android:layout_height="80dp"
    android:scaleType="fitXY"
    android:src="@mipmap/ic_launcher"
    />

  <LinearLayout
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_marginLeft="8dp"
    android:layout_weight="1"
    android:orientation="vertical"
    >

    <TextView
      android:id="@+id/tv_sgname"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:textSize="16sp"
      />

    <TextView
      android:id="@+id/tv_sgpetname"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_marginTop="2dp"
      android:textSize="12sp"
      />

    <TextView
      android:id="@+id/tv_sgdes"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_marginTop="2dp"
      android:textSize="12sp"
      />
  </LinearLayout>
</LinearLayout>

适配器SGAdapter:

package com.example.junweiliu.commonlysearchview.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.junweiliu.commonlysearchview.R;
import com.example.junweiliu.commonlysearchview.bean.SanGuoBean;
import com.example.junweiliu.commonlysearchview.bean.SearchBean;

import java.util.List;

/**
 * Created by junweiliu on 16/6/1.
 */
public class SGAdapter extends BaseAdapter {
  /**
   * 上下文
   */
  private Context mContext;

  /**
   * 数据源
   */
  private List<SanGuoBean> mDatas;

  /**
   * 构造函数
   *
   * @param context
   * @param datas
   */
  public SGAdapter(Context context, List<SanGuoBean> datas) {
    mContext = context;
    mDatas = datas;
  }

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

  @Override
  public Object getItem(int i) {
    return mDatas.get(i);
  }

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

  @Override
  public View getView(int position, View view, ViewGroup viewGroup) {
    ViewHolder vh = null;
    if (null == view) {
      vh = new ViewHolder();
      LayoutInflater mInflater = LayoutInflater.from(mContext);
      view = mInflater.inflate(R.layout.sg_item, null);
      vh.mNameTv = (TextView) view.findViewById(R.id.tv_sgname);
      vh.mPetNmaeTv = (TextView) view.findViewById(R.id.tv_sgpetname);
      vh.mDesTv = (TextView) view.findViewById(R.id.tv_sgdes);
      vh.mHeadImg = (ImageView) view.findViewById(R.id.iv_sghead);
      view.setTag(vh);
    } else {
      vh = (ViewHolder) view.getTag();
    }
    SanGuoBean bean = (SanGuoBean) getItem(position);
    if (null != bean) {
      vh.mNameTv.setText(bean.getSgName());
      vh.mDesTv.setText(bean.getSgDescribe());
      vh.mPetNmaeTv.setText(bean.getSgPetName());
      vh.mHeadImg.setImageResource(bean.getSgHeadBp());
    }
    return view;
  }

  /**
   * vh
   */
  class ViewHolder {
    /**
     * 姓名
     */
    TextView mNameTv;
    /**
     * 描述
     */
    TextView mDesTv;
    /**
     * 字
     */
    TextView mPetNmaeTv;
    /**
     * 头像
     */
    ImageView mHeadImg;
  }
}

MainActivity布局文件activity_main:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:search="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical"
  tools:context="com.example.junweiliu.commonlysearchview.MainActivity">

  <com.example.junweiliu.commonlysearchview.CommolySearchView
    android:id="@+id/csv_show"
    android:layout_width="match_parent"
    android:layout_height="40dp"
    android:layout_margin="8dip"
    android:background="@drawable/login_et_bg"
    search:SearchTextColor="#ff0000"
    search:SearchTextSize="14sp"
    >
  </com.example.junweiliu.commonlysearchview.CommolySearchView>

  <ListView
    android:id="@+id/lv_show"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
  </ListView>

</LinearLayout>

MainActivity:

package com.example.junweiliu.commonlysearchview;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;

import com.example.junweiliu.commonlysearchview.adapter.SGAdapter;
import com.example.junweiliu.commonlysearchview.adapter.SearchAdapter;
import com.example.junweiliu.commonlysearchview.bean.SanGuoBean;
import com.example.junweiliu.commonlysearchview.bean.SearchBean;

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

public class MainActivity extends Activity {
  /**
   * TAG
   */
  private static final String TAG = "MainActivity";
  /**
   * 数据显示listview
   */
  private ListView mListView;
  /**
   * 适配器
   */
  private SearchAdapter adapter;
  /**
   * 三国通用搜索框
   */
  private CommolySearchView<SanGuoBean> mSGCommolySearchView;
  /**
   * 三国数据源
   */
  private List<SanGuoBean> mSGDatas;
  /**
   * 三国适配器
   */
  private SGAdapter sgAdapter;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initDataI();
    initViewI();
  }
  /**
   * 初始化数据
   */
  private void initDataI() {
    mSGDatas = new ArrayList<SanGuoBean>();
    SanGuoBean sgbean1 = new SanGuoBean();
    sgbean1.setSgName("刘备");
    sgbean1.setSgPetName("玄德");
    sgbean1.setSgHeadBp(R.drawable.lb);
    sgbean1.setSgDescribe("刘备(161年-223年6月10日),字玄德,东汉末年幽州涿郡涿县(今河北省涿州市)人");
    SanGuoBean sgbean2 = new SanGuoBean();
    sgbean2.setSgName("关羽");
    sgbean2.setSgPetName("云长");
    sgbean2.setSgHeadBp(R.drawable.gy);
    sgbean2.setSgDescribe("关羽(?-220年),本字长生,后改字云长,河东郡解良(今山西运城)人");
    SanGuoBean sgbean3 = new SanGuoBean();
    sgbean3.setSgName("张飞");
    sgbean3.setSgPetName("翼德");
    sgbean3.setSgHeadBp(R.drawable.zf);
    sgbean3.setSgDescribe("张飞(?-221年),字益德[1] ,幽州涿郡(今河北省保定市涿州市)人氏");
    SanGuoBean sgbean4 = new SanGuoBean();
    sgbean4.setSgName("赵云");
    sgbean4.setSgPetName("子龙");
    sgbean4.setSgHeadBp(R.drawable.zy);
    sgbean4.setSgDescribe("赵云(?-229年),字子龙,常山真定(今河北省正定)人");
    SanGuoBean sgbean5 = new SanGuoBean();
    sgbean5.setSgName("马超");
    sgbean5.setSgPetName("孟起");
    sgbean5.setSgHeadBp(R.drawable.mc);
    sgbean5.setSgDescribe("马超(176年-222年),字孟起,司隶部扶风郡茂陵(今陕西兴平)人");
    SanGuoBean sgbean6 = new SanGuoBean();
    sgbean6.setSgName("黄忠");
    sgbean6.setSgPetName("汉升");
    sgbean6.setSgHeadBp(R.drawable.hz);
    sgbean6.setSgDescribe("黄忠(?-220年),字汉升(一作“汉叔”[1] ),南阳(今河南南阳)人");
    SanGuoBean sgbean7 = new SanGuoBean();
    sgbean7.setSgName("张辽");
    sgbean7.setSgPetName("文远");
    sgbean7.setSgHeadBp(R.drawable.zl);
    sgbean7.setSgDescribe("张辽(169年-222年),字文远,雁门马邑(今山西朔州)人");
    mSGDatas.add(sgbean1);
    mSGDatas.add(sgbean2);
    mSGDatas.add(sgbean3);
    mSGDatas.add(sgbean4);
    mSGDatas.add(sgbean5);
    mSGDatas.add(sgbean6);
    mSGDatas.add(sgbean7);

  }

  /**
   * 初始化控件
   */
  private void initViewI() {
    mSGCommolySearchView = (CommolySearchView) findViewById(R.id.csv_show);
    mListView = (ListView) findViewById(R.id.lv_show);
    sgAdapter = new SGAdapter(this, mSGDatas);
    mListView.setAdapter(sgAdapter);
    // 设置数据源
    mSGCommolySearchView.setDatas(mSGDatas);
    // 设置适配器
    mSGCommolySearchView.setAdapter(sgAdapter);
    // 设置筛选数据
    mSGCommolySearchView.setSearchDataListener(new CommolySearchView.SearchDatas<SanGuoBean>() {
      @Override
      public List<SanGuoBean> filterDatas(List<SanGuoBean> datas, List<SanGuoBean> filterdatas, String inputstr) {
        for (int i = 0; i < datas.size(); i++) {
          // 筛选条件
          if ((datas.get(i).getSgDescribe()).contains(inputstr) || datas.get(i).getSgName().contains(inputstr) || datas.get(i).getSgPetName().contains(inputstr)) {
            filterdatas.add(datas.get(i));
          }
        }
        return filterdatas;
      }
    });
    mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
      @Override
      public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        Toast.makeText(MainActivity.this, mSGCommolySearchView.getFilterDatas().get(i).getSgName() + "字" + mSGCommolySearchView.getFilterDatas().get(i).getSgPetName() + "\n" + mSGCommolySearchView.getFilterDatas().get(i).getSgDescribe(), Toast.LENGTH_SHORT).show();
      }
    });

  }
}

效果图如下:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android实现简单实用的搜索框

    本文实例为大家分享了Android实现搜索框展示的具体代码,供大家参考,具体内容如下 展示效果 代码区 SouActivity public class SouActivity extends AppCompatActivity implements TextWatcher{ @BindView(R.id.app_sou) EditText appSou; @BindView(R.id.app_sou_list) ListView appSouList; @BindView(R.id.activ

  • android搜索框上下滑动变色效果

    搜索框上下滑动变透明度是现在APP中很常见的效果,先看看效果: 首先来看下布局骨架: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height

  • Android SearchView搜索框组件的使用方法

    SearchView是搜索框组件,它可以让用户在文本框里输入文字,通过监听器取得用户的输入,当用户点击搜索时,监听器执行实际的搜索. 本文就为大家分享了SearchView搜索框组件的使用方法,供大家参考,具体内容如下 效果: 代码SearchActivity.java package com.jialianjia.bzw.activity; import android.os.Bundle; import android.widget.ArrayAdapter; import android.

  • Android EditText搜索框实现图标居中

    类似这样EditText 搜索框,hiht 提示有一个icon并且text内容. 重写EditText : package mobi.truekey.weapp2.widget; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.dr

  • Android搜索框SearchView属性和用法详解

    SearchView简介 SearchView是Android原生的搜索框控件,它提供了一个用户界面,用于用户搜索查询. SearchView默认是展示一个search的icon,点击icon展开搜索框,如果你想让搜索框默认就展开,可以通过setIconifiedByDefault(false);实现. SearchView属性 SearchView使用 xml中定义SearchView: <?xml version="1.0" encoding="utf-8"

  • Android的搜索框架实例详解

    基础知识 Android的搜索框架将代您管理的搜索对话框,您不需要自己去开发一个搜索框,不需要担心要把搜索框放什么位置,也不需要担心搜索框影响您当前的界面.所有的这些工作都由SearchManager类来为您处理(以下简称"搜索管理器"),它管理的Android搜索对话框的整个生命周期,并执行您的应用程序将发送的搜索请求,返回相应的搜索关键字. 当用户执行一个搜索,搜索管理器将使用一个专门的Intent把搜索查询的关键字传给您在配置文件中配置的处理搜索结果的Activity.从本质上讲

  • Android中如何实现清空搜索框的文字

    需求:项目中的有关搜索的地方,加上清空文字的功能,目的是为了增加用户体验,使用户删除文本更加快捷 解决过程:开始的时候感觉这个东西不太好实现,主要就是布局的问题,可能是开始顾虑的太多了,再加上当时产品催的不太紧,而且这个功能也不是必须实现的.但是今天不一样了,这个是老大让加上的,说别的很多应用中都有这个功能,没办法那就加上呗,试着去使用了相对布局去实现,把一个删除按键放在编辑框的右上方,当文字的时候就把删除按键给显示出来,当编辑框为空的时候就把删除按键给隐藏掉.布局代码 <?xml versio

  • Android搜索框组件SearchView的基本使用方法

    SearchView是android系统中内置的一个搜索框组件,可以很方便在添加在用户界面之上,但是也带来了一些问题,那就是searchview的UI是固定的,定制起来会很麻烦,如果对SearchView的要求比较高,完全可以采用button和EditText自己实现.这里先简单的说说SearchView的使用: main.xml: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" x

  • Android 根据EditText搜索框ListView动态显示数据

    根据EditText搜索框ListView动态显示数据是根据需求来的,觉得这之中涉及的东西可能比较的有意思,所以动手来写一写,希望对大家有点帮助. 首先,我们来分析下整个过程: 1.建立一个layout,包含一个EditText搜索框和一个ListView 2.创建一个数据集mData,用于ListView的Adapter的创建 3.添加EditText的文本改变的监听器 4.利用notifyDataSetChanged()动态更新ListView 第一步:创建一个搜索框 这个还是比较容易的,这

  • Android搜索框(SearchView)的功能和用法详解

    SearchView是搜索框组件,它可以让用户在文本框里输入文字,通过监听器取得用户的输入,当用户点击搜索时,监听器执行实际的搜索. 1.SearchView组件的常用方法如下: ①setIconifiedByDefault(boolean iconified) ===> 设置搜索框默认是否自动缩小为图标. ②setOnQueryTextListener(SearchView,OnQueryTextListener listener) ===> 为搜索框设置监听器 ③setSubmitButt

随机推荐