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

常用的几个事件

动画事件

动画事件主要用于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开发笔记的完整目录

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券