Android开发笔记(四十四)动态UI事件

来源:互联网 发布:社交网络 豆瓣 编辑:程序博客网 时间:2024/05/21 10:04

常用的几个事件

动画事件

动画事件主要用于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")@Overrideprotected 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);}@Overridepublic void onClick(View v) {if (v.getId() == R.id.btn_auto_search) {mListener.onSearchClick(mKey);}}@Overridepublic void onFocusChange(View v, boolean hasFocus) {if (v instanceof AutoCompleteTextView) {if (hasFocus) {((AutoCompleteTextView)v).showDropDown();}}}@Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) {}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {}@Overridepublic 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"};@Overrideprotected 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);}@Overridepublic 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")@Overrideprotected 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);}@Overridepublic 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);}}@Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) {}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {}@Overridepublic 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;}@Overridepublic int getCount() {return mKeyArray.size();}@Overridepublic Object getItem(int arg0) {return mKeyArray.get(arg0);}@Overridepublic long getItemId(int arg0) {return arg0;}@Overridepublic 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;}@Overridepublic 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"};@Overrideprotected 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);}@Overridepublic void onSearchClick(String key) {tv_custom.setText("您输入的搜索关键字是:"+key);}}



点击下载本文用到的自定义搜索框的工程代码



点此查看Android开发笔记的完整目录



0 0