常用的几个事件
动画事件
动画事件主要用于Animation控件,可监控动画开始、结束、重播等行为。相关类名与方法说明如下:
监听器类名 : AnimationListener
设置监听器的方法 : setAnimationListener
监听器需要重写的方法 :
onAnimationStart : 动画开始播放时调用。
onAnimationEnd : 动画结束播放时调用,该方法用得较多。
onAnimationRepeat : 动画重新播放时调用。
动画事件的具体实现代码可参考《 Android开发笔记(二十一)横幅轮播页Banner》。
翻页事件
翻页事件,主要用于ViewPager控件,可监控翻页状态变化、滚动、选定等行为。相关类名与方法说明如下:
监听器类名 : OnPageChangeListener
设置监听器的方法 : setOnPageChangeListener
监听器需要重写的方法 :
onPageScrollStateChanged : 翻页状态改变时调用,状态参数取值说明为:0表示静止,1表示正在滑动,2表示滑动完毕。在翻页过程中,状态值变化依次为:正在滑动->滑动完毕->静止。
onPageScrolled : 在翻页过程中调用。该方法的三个参数取值说明为:第一个参数表示当前页面的序号;第二个参数表示当前页面偏移的百分比,最小值为0,最大值为1;第三个参数表示当前页面的偏移距离,单位px。
onPageSelected : 在页面选择时调用,该方法用得较多。位置参数表示当前页面的序号。
翻页事件的具体实现代码可参考《 Android开发笔记(二十一)横幅轮播页Banner》。
文本变化事件
文本变化事件,主要用于EditText控件,包括继承自EditText的AutoCompleteTextView控件,可监控文本变化前、变化中、变化后等行为。相关类名与方法说明如下:
监听器类名 : TextWatcher
设置监听器的方法 : addTextChangedListener
监听器需要重写的方法 :
beforeTextChanged : 在文本变化前调用。
onTextChanged : 在文本变化中调用。
afterTextChanged : 在文本变化后调用,该方法用得较多。
文本变化事件的具体实现代码可参考《 Android开发笔记(三十六)展示类控件》。
基于AutoCompleteTextView的搜索控件
动画事件和翻页事件在前面章节有过示例了,这里就示范一下文本变化事件的使用。在博文《 Android开发笔记(二十)顶部导航栏ActionBar》里面,博主提到ActionBar自带的搜索框SearchView,但是SearchView存在几点不足:
1、搜索按钮只能显示图标,不能显示中文;
2、搜索框只能放在顶部的ActionBar里面,不能放置于页面的其它位置;
3、用户输入搜索文本时,SearchView无法给出近似的关键词列表提示;
因为SearchView的这些先天不足,所以实际开发中很少直接使用SearchView。为解决以上问题,我们需要自己写个搜索控件,下面便是基于AutoCompleteTextView的一个实现。
首先熟悉下AutoCompleteTextView新增的几个属性:
completionHint : 指定下拉列表底部的提示文字
completionThreshold : 指定至少输入多少个字符才会显示提示
dropDownHorizontalOffset : 指定下拉列表与文本框之间的水平偏移
dropDownVerticalOffset : 指定下拉列表与文本框之间的垂直偏移
dropDownHeight : 指定下拉列表的高度
dropDownWidth : 指定下拉列表的宽度
singleLine : 指定列表中的每个元素是否单行显示,true表示单行显示,false表示多行显示
在代码中对应的方法是:
setCompletionHint : 设置下拉列表底部的提示文字
setThreshold : 设置至少输入多少个字符才会显示提示
setDropDownHorizontalOffset : 设置下拉列表与文本框之间的水平偏移
setDropDownVerticalOffset : 设置下拉列表与文本框之间的垂直偏移
setDropDownHeight : 设置下拉列表的高度
setDropDownWidth : 设置下拉列表的宽度
setSingleLine : 设置列表中的每个元素是否单行显示
示例代码主要实现了三个功能:
1、在文本框一开始获得焦点时,自动弹出历史搜索关键词下拉列表;
2、点击下拉列表的某项,文本框自动填入该项的关键词文本;
3、点击搜索按钮,主页面通过回调获得搜索关键词,从而能够做进一步的处理;
下面是AutoCompleteTextView方式的效果图
下面是AutoSearchView搜索控件的示例代码:
import com.example.exmsearch.R;
import android.annotation.SuppressLint;
import android.content.Context;
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.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.LinearLayout;
public class AutoSearchView extends LinearLayout
implements OnClickListener, OnFocusChangeListener, TextWatcher {
private final static String TAG = "AutoSearchView";
private Context mContext;
private LayoutInflater mInflater;
private View mView;
private SearchClickListener mListener = null;
private ArrayAdapter<String> mAdapter = null;
private String mKey;
private AutoCompleteTextView ac_text;
private Button btn_auto_search;
public AutoSearchView(Context context) {
this(context, null);
}
public AutoSearchView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mInflater = LayoutInflater.from(mContext);
}
public void setOnSearchListener(SearchClickListener listener) {
mListener = listener;
}
public SearchClickListener getOnSearchListener() {
return mListener;
}
public void setAdapter(ArrayAdapter<String> adapter) {
mAdapter = adapter;
}
public ArrayAdapter<String> getAdapter() {
return mAdapter;
}
@SuppressLint("InflateParams")
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
mView = mInflater.inflate(R.layout.view_search_auto, null);
addView(mView);
ac_text = (AutoCompleteTextView) mView.findViewById(R.id.ac_text);
ac_text.setAdapter(mAdapter);
ac_text.setOnFocusChangeListener(this);
ac_text.addTextChangedListener(this);
btn_auto_search = (Button) mView.findViewById(R.id.btn_auto_search);
btn_auto_search.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_auto_search) {
mListener.onSearchClick(mKey);
}
}
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (v instanceof AutoCompleteTextView) {
if (hasFocus) {
((AutoCompleteTextView)v).showDropDown();
}
}
}
@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) {
Log.d(TAG, "afterTextChanged s="+s);
mKey = s.toString();
}
}
下面是主页面的调用代码:
import com.example.exmsearch.widget.AutoSearchView;
import com.example.exmsearch.widget.SearchClickListener;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class AutoSearchActivity extends Activity implements SearchClickListener {
private final static String TAG = "AutoSearchActivity";
private AutoSearchView asv_text;
private TextView tv_auto;
private String[] hintArray = {"ab", "abc", "abcde", "abHtp", "aaeet", "aab"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_auto);
tv_auto = (TextView) findViewById(R.id.tv_auto);
asv_text = (AutoSearchView) findViewById(R.id.asv_text);
asv_text.setOnSearchListener(this);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
this, R.layout.list_auto, hintArray);
asv_text.setAdapter(adapter);
}
@Override
public void onSearchClick(String key) {
tv_auto.setText("您输入的搜索关键字是:"+key);
}
}
基于EditText+ListView的搜索控件
AutoCompleteTextView方式已经较好的实现了大部分搜索功能,可是还不能完全满足电商APP的业务需求。比如弹出商品关键词列表时,往往还希望在每行后面显示该关键词对应的商品数量,从而让用户更有目的地选择合适的商品。基于此,博主在下面又给出了基于EditText+ListView的实现方式,该方式除了在列表中显示关键词与数量外,还增加了一个叉号按钮用来立即清空文本框。
下面是EditText+ListView方式的效果图
下面是CustomSearchView搜索控件的示例代码:
import java.util.ArrayList;
import android.annotation.SuppressLint;
import android.content.Context;
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.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import com.example.exmsearch.R;
public class CustomSearchView extends LinearLayout implements OnClickListener, TextWatcher {
private final static String TAG = "CustomSearchView";
private Context mContext;
private LayoutInflater mInflater;
private View mView;
private SearchClickListener mListener = null;
private ArrayList<String> mSearchArray = null;
private String mKey;
private EditText et_text;
private Button btn_custom_search;
private Button btn_clear;
private ListView lv_custom;
public CustomSearchView(Context context) {
this(context, null);
}
public CustomSearchView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mInflater = LayoutInflater.from(mContext);
}
public void setOnSearchListener(SearchClickListener listener) {
mListener = listener;
}
public SearchClickListener getOnSearchListener() {
return mListener;
}
public void setSearchArray(ArrayList<String> keyArray) {
mSearchArray = keyArray;
}
public ArrayList<String> getSearchArray() {
return mSearchArray;
}
@SuppressLint("InflateParams")
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
mView = mInflater.inflate(R.layout.view_search_custom, null);
addView(mView);
et_text = (EditText) mView.findViewById(R.id.et_text);
et_text.addTextChangedListener(this);
btn_custom_search = (Button) mView.findViewById(R.id.btn_custom_search);
btn_custom_search.setOnClickListener(this);
btn_clear = (Button) mView.findViewById(R.id.btn_clear);
btn_clear.setOnClickListener(this);
lv_custom = (ListView) mView.findViewById(R.id.lv_custom);
}
private void refresh(boolean bShowList) {
lv_custom.setVisibility((bShowList==true)?View.VISIBLE:View.GONE);
et_text.setText(mKey);
et_text.setFocusable(true);
et_text.setSelection(mKey.length());
removeAllViews();
addView(mView);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_custom_search) {
mListener.onSearchClick(mKey);
} else if (v.getId() == R.id.btn_clear) {
mKey = "";
refresh(false);
}
}
@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 (mSearchArray != null && s.toString().equals(mKey)!=true) {
mKey = s.toString();
ArrayList<String> keyArray = new ArrayList<String>();
for (String item : mSearchArray) {
if (item.indexOf(mKey) == 0) {
keyArray.add(item);
}
}
if (keyArray.size() > 0) {
SearchListAdapter adapter = new SearchListAdapter(mContext, keyArray);
lv_custom.setAdapter(adapter);
lv_custom.setOnItemClickListener(adapter);
refresh(true);
} else {
refresh(false);
}
} else {
mKey = s.toString();
}
}
public class SearchListAdapter extends BaseAdapter implements OnItemClickListener {
private ArrayList<String> mKeyArray = new ArrayList<String>();
public SearchListAdapter(Context context, ArrayList<String> keyArray) {
mKeyArray = keyArray;
}
@Override
public int getCount() {
return mKeyArray.size();
}
@Override
public Object getItem(int arg0) {
return mKeyArray.get(arg0);
}
@Override
public long getItemId(int arg0) {
return arg0;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.list_custom, null);
holder.tv_key = (TextView) convertView.findViewById(R.id.tv_key);
holder.tv_count = (TextView) convertView.findViewById(R.id.tv_count);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
String keyItem = mKeyArray.get(position);
holder.tv_key.setText(keyItem.split(",")[0]);
holder.tv_count.setText(keyItem.split(",")[1]+"个结果");
return convertView;
}
public final class ViewHolder {
public TextView tv_key;
public TextView tv_count;
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mKey = mKeyArray.get(position).split(",")[0];
refresh(false);
}
}
}
下面是主页面的调用代码:
import java.util.ArrayList;
import com.example.exmsearch.widget.CustomSearchView;
import com.example.exmsearch.widget.SearchClickListener;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class CustomSearchActivity extends Activity implements SearchClickListener {
private final static String TAG = "CustomSearchActivity";
private CustomSearchView csv_text;
private TextView tv_custom;
private String[] hintArray = {"ab", "abc", "abcde", "abHtp", "aaeet", "aab"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom);
tv_custom = (TextView) findViewById(R.id.tv_custom);
csv_text = (CustomSearchView) findViewById(R.id.csv_text);
csv_text.setOnSearchListener(this);
ArrayList<String> searchArray = new ArrayList<String>();
for (int i=0; i<hintArray.length; i++) {
String item = hintArray[i]+","+(10-i);
searchArray.add(item);
}
csv_text.setSearchArray(searchArray);
}
@Override
public void onSearchClick(String key) {
tv_custom.setText("您输入的搜索关键字是:"+key);
}
}
点此查看Android开发笔记的完整目录