getData() {
83 | return mData;
84 | }
85 |
86 | /**
87 | * 用新数据替换所有的旧数据
88 | * NOTE:数据源的指向并没有改变, 只是将数据源的数据{@link List #clear()}再 {@link List #addAll(Collection)}
89 | * @param newData
90 | */
91 | public synchronized void update(Collection extends T> newData) {
92 | mData.clear();
93 | if( newData != null ) {
94 | mData.addAll(newData);
95 | }
96 | notifyDataSetChanged();
97 | }
98 |
99 | /**
100 | * 直接将源数据替换,将新数据的指向设置给适配器
101 | * @param newData
102 | */
103 | public void replaceOriginData(List newData) {
104 | mData = (List) newData;
105 | notifyDataSetChanged();
106 | }
107 |
108 |
109 | /**
110 | * 在原有数据的基础上再添加数据
111 | * NOTE:数据源的指向并没有改变,只是在原有数据源的基础上添加数据
112 | * @param appendData
113 | */
114 | public synchronized void append(Collection extends T> appendData) {
115 | if( appendData == null || appendData.isEmpty() ) {
116 | return;
117 | }
118 | mData.addAll(appendData);
119 | notifyDataSetChanged();
120 | }
121 |
122 | /**
123 | * 添加一个数据
124 | * @param item
125 | */
126 | public synchronized void add(T item) {
127 | mData.add(item);
128 | notifyDataSetChanged();
129 | }
130 |
131 | /**
132 | * 清空所有数据
133 | */
134 | public void clear() {
135 | mData.clear();
136 | notifyDataSetChanged();
137 | }
138 |
139 | @Override
140 | public View getView(int position, View convertView, ViewGroup parent) {
141 | if( convertView == null ) {
142 | convertView = mLayoutInflater.inflate(mLayoutRes, parent, false);
143 | }
144 | mCurrentConvertView = convertView;
145 | bindData(position, getItem(position));
146 |
147 | return convertView;
148 | }
149 |
150 | abstract protected void bindData(int pos, T itemData);
151 |
152 | // ===========
153 | // some util method
154 | // ===========
155 | public void bindText(int textViewId, CharSequence value) {
156 | ((TextView)getViewFromHolder(textViewId)).setText(value);
157 | }
158 |
159 | public K getViewFromHolder(int id) {
160 | return ViewHolder.getView(mCurrentConvertView, id);
161 | }
162 |
163 | }
164 |
--------------------------------------------------------------------------------
/SearchBarDemo/assets/bank/hot_bank.json:
--------------------------------------------------------------------------------
1 | [{"key":"#","name":"中国工商银行","code":"1","logoName":"cyyh0"},{"key":"#","name":"中国农业银行股份有限公司","code":"2","logoName":"cyyh1"},{"key":"#","name":"中国建设银行股份有限公司总行","code":"3","logoName":"cyyh2"},{"key":"#","name":"中国邮政储蓄银行有限责任公司","code":"4","logoName":"cyyh3"},{"key":"#","name":"中国银行总行","code":"5","logoName":"cyyh4"},{"key":"#","name":"招商银行股份有限公司","code":"6","logoName":"cyyh5"},{"key":"#","name":"交通银行","code":"7","logoName":"cyyh6"},{"key":"#","name":"中国光大银行","code":"8","logoName":"cyyh7"},{"key":"#","name":"平安银行(原深圳发展银行)","code":"9","logoName":"cyyh8"},{"key":"#","name":"中国民生银行","code":"10","logoName":"cyyh9"},{"key":"#","name":"兴业银行总行","code":"11","logoName":"cyyh10"},{"key":"#","name":"中信银行股份有限公司","code":"12","logoName":"cyyh11"},{"key":"#","name":"上海浦东发展银行","code":"13","logoName":"cyyh12"},{"key":"#","name":"广发银行股份有限公司","code":"14","logoName":"cyyh13"},{"key":"LU","name":"泸州市商业银行","code":"453"},{"key":"JIAO","name":"焦作市商业银行","code":"404"},{"key":"ZHOU","name":"周口银行","code":"410"},{"key":"ZAO","name":"枣庄市商业银行","code":"386"},{"key":"SHI","name":"石嘴山银行","code":"484"},{"key":"SHA","name":"厦门银行","code":"372"},{"key":"CHAO","name":"朝阳银行","code":"322"},{"key":"DE","name":"德州银行","code":"394"},{"key":"ZUN","name":"遵义市商业银行","code":"467"},{"key":"DAN","name":"丹东银行","code":"313"},{"key":"JIA","name":"嘉兴银行","code":"361"},{"key":"TANG","name":"唐山市商业银行","code":"285"},{"key":"HAI","name":"海南省农村信用社联合社","code":"564"},{"key":"XING","name":"兴业银行北京分行","code":"203"},{"key":"JIN","name":"锦州银行北京分行","code":"273"},{"key":"DONG","name":"东营市商业银行","code":"387"},{"key":"HAN","name":"邯郸银行","code":"288"},{"key":"TIAN","name":"天津银行北京分行","code":"268"},{"key":"MIAN","name":"绵阳市商业银行","code":"455"},{"key":"JIU","name":"九江银行","code":"377"},{"key":"ZHANG","name":"张家口市商业银行","code":"291"},{"key":"KUN","name":"昆仑银行","code":"486"},{"key":"WEN","name":"温州银行上海分行","code":"337"},{"key":"PAN","name":"盘锦市商业银行","code":"320"},{"key":"LIU","name":"柳州银行","code":"436"},{"key":"E","name":"鄂尔多斯银行","code":"305"},{"key":"WEI","name":"威海市商业银行济南分行","code":"380"},{"key":"XU","name":"许昌银行","code":"406"},{"key":"LIN","name":"临商银行宁波分行","code":"357"},{"key":"SHEN","name":"深圳发展银行北京分行","code":"150"},{"key":"XI","name":"西安银行科技路支行","code":"472"},{"key":"SAN","name":"三门峡市商业银行","code":"408"},{"key":"FU","name":"抚顺银行","code":"311"},{"key":"YING","name":"营口银行","code":"316"},{"key":"FO","name":"佛山顺德农村商业银行","code":"501"},{"key":"LIAO","name":"辽阳银行","code":"319"},{"key":"PING","name":"平安银行上海分行","code":"331"},{"key":"HE","name":"河北银行","code":"284"},{"key":"WU","name":"乌海银行","code":"304"},{"key":"HA","name":"哈尔滨银行大连分行","code":"308"},{"key":"ZHAN","name":"湛江市商业银行","code":"433"},{"key":"ZHAO","name":"招商银行北京分行","code":"169"},{"key":"HUI","name":"徽商银行南京分行","code":"534"},{"key":"GUI","name":"桂林银行","code":"437"},{"key":"BEI","name":"北京银行","code":"266"},{"key":"LAN","name":"兰州银行","code":"479"},{"key":"HUA","name":"华夏银行总行","code":"70"},{"key":"LAI","name":"莱商银行","code":"392"},{"key":"BEN","name":"本溪市商业银行","code":"312"},{"key":"LANG","name":"廊坊银行","code":"294"},{"key":"NAN","name":"南京银行北京分行(集中作业中心)","code":"269"},{"key":"RI","name":"日照银行","code":"396"},{"key":"ZI","name":"自贡市商业银行","code":"451"},{"key":"CHENG","name":"承德银行","code":"292"},{"key":"HU","name":"葫芦岛银行","code":"315"},{"key":"QU","name":"曲靖市商业银行","code":"470"},{"key":"SUI","name":"遂宁市商业银行","code":"456"},{"key":"YAN","name":"烟台银行","code":"388"},{"key":"YUN","name":"云南省农村信用社联合社","code":"567"},{"key":"TIE","name":"铁岭银行","code":"321"},{"key":"GAN","name":"赣州银行","code":"378"},{"key":"QING","name":"青岛银行","code":"384"},{"key":"LIANG","name":"凉山州商业银行","code":"462"},{"key":"QI","name":"齐鲁银行","code":"381"},{"key":"YA","name":"雅安市商业银行","code":"461"},{"key":"YANG","name":"阳泉市商业银行","code":"298"},{"key":"CANG","name":"沧州银行","code":"293"},{"key":"PU","name":"濮阳市商业银行","code":"405"},{"key":"HENG","name":"衡水市商业银行","code":"295"},{"key":"QUAN","name":"泉州银行","code":"373"},{"key":"YI","name":"宜宾市商业银行","code":"458"},{"key":"SHAO","name":"绍兴银行","code":"363"},{"key":"SHAN","name":"山西省农村信用社联合社","code":"543"},{"key":"HANG","name":"杭州银行北京分行","code":"276"},{"key":"JING","name":"景德镇市商业银行","code":"376"},{"key":"YU","name":"玉溪市商业银行","code":"471"},{"key":"ZHONG","name":"中信银行总行","code":"1"},{"key":"SHENG","name":"盛京银行北京分行","code":"270"},{"key":"JI","name":"吉林银行","code":"323"},{"key":"HEI","name":"黑龙江省农村信用社","code":"547"},{"key":"AN","name":"鞍山银行","code":"310"},{"key":"SHANG","name":"上海浦东发展银行北京分行","code":"232"},{"key":"LUO","name":"洛阳银行","code":"399"},{"key":"QIN","name":"秦皇岛市商业银行","code":"287"},{"key":"JIANG","name":"江苏银行北京分行","code":"271"},{"key":"SU","name":"苏州银行","code":"494"},{"key":"TAI","name":"台州银行","code":"366"},{"key":"BO","name":"渤海银行北京分行","code":"522"},{"key":"ZHE","name":"浙江泰隆商业银行上海分行","code":"336"},{"key":"BAI","name":"白银市商业银行","code":"480"},{"key":"SI","name":"四川省农村信用社联合社","code":"565"},{"key":"ZHENG","name":"郑州银行","code":"397"},{"key":"ZHU","name":"驻马店银行","code":"411"},{"key":"DA","name":"大连银行北京分行","code":"267"},{"key":"NEI","name":"内蒙古银行","code":"302"},{"key":"KU","name":"库尔勒市商业银行","code":"488"},{"key":"GUANG","name":"广发银行北京分行","code":"136"},{"key":"NING","name":"宁波银行北京分行","code":"272"},{"key":"KAI","name":"开封市商业银行","code":"398"},{"key":"XIN","name":"新乡银行","code":"403"},{"key":"LONG","name":"龙江银行","code":"326"},{"key":"LE","name":"乐山市商业银行","code":"457"},{"key":"BAO","name":"包商银行北京分行","code":"275"}]
--------------------------------------------------------------------------------
/SearchBarDemo/src/com/lwz/searchbar/demo/MainActivity.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014, 2015 Liu Wenzhu
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | *******************************************************************************/
22 | package com.lwz.searchbar.demo;
23 |
24 | import java.util.ArrayList;
25 |
26 | import android.graphics.Color;
27 | import android.os.Bundle;
28 | import android.support.v4.app.FragmentActivity;
29 | import android.text.TextUtils;
30 | import android.view.View;
31 | import android.view.ViewGroup;
32 | import android.widget.AdapterView;
33 | import android.widget.AdapterView.OnItemClickListener;
34 | import android.widget.EditText;
35 | import android.widget.ListView;
36 | import android.widget.Toast;
37 |
38 | import com.lwz.letterbarview.lib.LetterBarView;
39 | import com.lwz.letterbarview.lib.LetterBarView.OnLetterSelectListener;
40 | import com.lwz.searchbar.demo.BankFilter.OnPublishFilterResultsListener;
41 | import com.lwz.searchbar.demo.IndexAdapter.OnItemClickListenerWrapper;
42 | import com.lwz.widget.searchbar.SearchBarView;
43 | import com.lwz.widget.searchbar.SearchBarView.SimpleSearchBarStateChangedListener;
44 |
45 | public class MainActivity extends FragmentActivity implements
46 | OnLetterSelectListener, OnItemClickListener,
47 | OnPublishFilterResultsListener {
48 |
49 | public static final String[] LETTERS = { "热", "A", "B", "C", "D", "E", "F",
50 | "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S",
51 | "T", "U", "V", "W", "X", "Y", "Z" };
52 |
53 | public static final String PROPERTY_ON_ITEM_CLICK = "onItemClick";
54 | public static final String PROPERTY_BANK_DATA = "bank_data";
55 |
56 | LetterBarView mLetterBarView;
57 | ListView mBankList;
58 | BankIndexAdapter mBankIndexAdapter;
59 |
60 | SearchBarView mSearchBar;
61 | ViewGroup mSearchResultContainer;
62 | ListView mSearchResultList; // 搜索结果 list
63 | BankSearchResultAdapter mSearchResultAdapter;
64 |
65 | @Override
66 | protected void onCreate(Bundle arg0) {
67 | super.onCreate(arg0);
68 | setContentView(R.layout.activity_main);
69 |
70 | mSearchBar = (SearchBarView) findViewById(R.id.searchbar);
71 | mLetterBarView = (LetterBarView) findViewById(R.id.letterbar);
72 | mLetterBarView.setOverlayOffset(0, -200);
73 | mBankList = (ListView) findViewById(R.id.bank_list);
74 | mBankIndexAdapter = new BankIndexAdapter(this);
75 | mBankIndexAdapter.setOnPublishFilterResultsListener(this);
76 | mBankList.setAdapter(mBankIndexAdapter);
77 | mBankList.setOnItemClickListener(new OnItemClickListenerWrapper(this));
78 |
79 | mLetterBarView.setLetterSet(LETTERS);
80 |
81 | mSearchResultContainer = (ViewGroup) findViewById(R.id.search_result_container);
82 | mSearchResultList = (ListView) findViewById(R.id.search_result_list);
83 | mSearchResultAdapter = new BankSearchResultAdapter(this);
84 | mSearchResultList.setAdapter(mSearchResultAdapter);
85 | mSearchResultList.setOnItemClickListener(this);
86 |
87 | mLetterBarView.setOnLetterSelectListener(this);
88 | mSearchBar.setOnSearchBarStateChnagedListener(
89 | new SimpleSearchBarStateChangedListener() {
90 |
91 | @Override
92 | public void onPrepareSearch(EditText searchEidt) {
93 | showSearchResultContainer();
94 | }
95 |
96 | @Override
97 | public void onCancel(EditText searchEidt) {
98 | dismissSearchResultContainer();
99 | }
100 |
101 | @Override
102 | public void onTextChanged(CharSequence s, int start,
103 | int before, int count) {
104 | onSearchContentChanged(s.toString());
105 | }
106 |
107 | });
108 |
109 | // 加载热门银行数据,相关数据在 asset/bank 目录下
110 | mBankIndexAdapter.updateData(BankUtils.loadHotBank(getAssets()));
111 | }
112 |
113 | @Override
114 | public void onLetterSelect(String s) {
115 | if (!s.equals("热")) {
116 | mBankList.setSelection(mBankIndexAdapter.getIndexPosition(s));
117 | } else {
118 | mBankList.setSelection(0);
119 | }
120 | }
121 |
122 | @Override
123 | public void onItemClick(AdapterView> parent, View view, int position,
124 | long id) {
125 | Object itemData = parent.getItemAtPosition(position);
126 | if (itemData instanceof Bank) {
127 | Toast.makeText(this, ((Bank) itemData).name, Toast.LENGTH_SHORT).show();
128 | }
129 | }
130 |
131 | private void showSearchResultContainer() {
132 | mSearchResultContainer.setVisibility(View.VISIBLE);
133 | // 禁止点击事件向下传递
134 | mSearchResultContainer.setClickable(true);
135 | }
136 |
137 | private void dismissSearchResultContainer() {
138 | mSearchResultContainer.setVisibility(View.INVISIBLE);
139 | }
140 |
141 | private void onSearchContentChanged(String text) {
142 | if (TextUtils.isEmpty(text)) {
143 | mSearchResultAdapter.clear();
144 | mSearchResultList.setBackgroundColor(Color.parseColor("#77000000"));
145 | return;
146 | }
147 | mSearchResultList.setBackgroundColor(Color.WHITE);
148 | mBankIndexAdapter.filter(text);
149 | }
150 |
151 | @Override
152 | public void onPublishResults(CharSequence constraint,
153 | ArrayList results) {
154 | mSearchResultAdapter.update(results);
155 | }
156 |
157 | public void setBankData(ArrayList data) {
158 | mBankIndexAdapter.appendData(data);
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/SearchBarLibary/src/com/lwz/widget/searchbar/SearchBarView.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014, 2015 Liu Wenzhu.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package com.lwz.widget.searchbar;
17 |
18 | import android.content.Context;
19 | import android.text.Editable;
20 | import android.text.TextWatcher;
21 | import android.util.AttributeSet;
22 | import android.view.Gravity;
23 | import android.view.KeyEvent;
24 | import android.view.MotionEvent;
25 | import android.view.View;
26 | import android.view.inputmethod.EditorInfo;
27 | import android.view.inputmethod.InputMethodManager;
28 | import android.widget.Button;
29 | import android.widget.EditText;
30 | import android.widget.FrameLayout;
31 | import android.widget.LinearLayout;
32 | import android.widget.TextView;
33 | import android.widget.TextView.OnEditorActionListener;
34 |
35 | import com.lwz.widget.R;
36 |
37 | public class SearchBarView extends LinearLayout {
38 |
39 | EditText mSearchEdit;
40 | Button mCancelBtn;
41 | InputMethodManager mIMMService;
42 |
43 | public SearchBarView(Context context) {
44 | this(context, null);
45 | }
46 |
47 | public SearchBarView(Context context, AttributeSet attrs) {
48 | super(context, attrs);
49 | mIMMService = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
50 | inflate(context, R.layout.widget_searchbar_edit, this);
51 | mSearchEdit = (EditText) findViewById(R.id.search_edit);
52 | mCancelBtn = (Button) findViewById(R.id.cancel_btn);
53 | mCancelBtn.setOnClickListener(new OnClickListener() {
54 |
55 | @Override
56 | public void onClick(View v) {
57 | onCancelAction();
58 | }
59 | });
60 | mSearchEdit.addTextChangedListener(mStateChangedListenerWrapper);
61 | // 将输入法右下角的按钮变为搜索按钮
62 | mSearchEdit.setImeOptions(EditorInfo.IME_ACTION_SEARCH);
63 | mSearchEdit.setOnEditorActionListener(new OnEditorActionListener() {
64 |
65 | @Override
66 | public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
67 | if( actionId == EditorInfo.IME_ACTION_SEARCH ){
68 | return mStateChangedListenerWrapper.onSearchEvent(mSearchEdit);
69 | }
70 | return false;
71 | }
72 | });
73 | }
74 |
75 | @Override
76 | public boolean dispatchTouchEvent(MotionEvent ev) {
77 | // 由于 mSearchEdit 被设置为不可用的 setEnable(false),所以设置 click 监听也无效果,
78 | // 所以重写改方法来监听用户点击整个 searchbar 控件的事件,来将 mSearchEdit 设置为可以编辑的
79 | int action = ev.getAction();
80 | if( action == MotionEvent.ACTION_DOWN ) {
81 | if( !mSearchEdit.isEnabled() ) {
82 | onSearchAction();
83 | return true;
84 | }
85 | }
86 | return super.dispatchTouchEvent(ev);
87 | }
88 |
89 | /**
90 | * 搜索动作方法,执行搜索操作时调用改方法
91 | */
92 | private void onSearchAction() {
93 | mStateChangedListenerWrapper.onPrepareSearch(mSearchEdit);
94 | // 显示 取消按钮
95 | mCancelBtn.setVisibility(View.VISIBLE);
96 |
97 | // 改变search editText 的 gravity 和 宽度,使得 editText 靠左
98 | FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mSearchEdit.getLayoutParams();
99 | lp.gravity = Gravity.LEFT;
100 | lp.width = FrameLayout.LayoutParams.MATCH_PARENT;
101 | mSearchEdit.setLayoutParams(lp);
102 | // 设置为可编辑的
103 | mSearchEdit.setEnabled(true);
104 | mSearchEdit.requestFocus();
105 |
106 | // 唤起输入法
107 | mIMMService.showSoftInput(
108 | mSearchEdit, InputMethodManager.SHOW_IMPLICIT);
109 | }
110 |
111 | /**
112 | * 取消动作方法,当点击取消按钮时,调用该方法
113 | */
114 | private void onCancelAction() {
115 | // 隐藏 取消按钮
116 | mCancelBtn.setVisibility(View.GONE);
117 | // 清空输入框中的内容
118 | mSearchEdit.setText(null);
119 |
120 | // 改变search editText 的 gravity 和 宽度, 使得 editText 居中
121 | FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mSearchEdit.getLayoutParams();
122 | lp.gravity = Gravity.CENTER_HORIZONTAL;
123 | lp.width = FrameLayout.LayoutParams.WRAP_CONTENT;
124 | mSearchEdit.setLayoutParams(lp);
125 | // 设置为不可编辑
126 | mSearchEdit.setEnabled(false);
127 |
128 | // 隐藏输入法
129 | mIMMService.hideSoftInputFromWindow(
130 | mSearchEdit.getWindowToken(), InputMethodManager.SHOW_IMPLICIT);
131 | mStateChangedListenerWrapper.onCancel(mSearchEdit);
132 | }
133 |
134 | public void setOnSearchBarStateChnagedListener(OnSearchBarStateChangedListener l) {
135 | mStateChangedListener = l;
136 | }
137 |
138 | public static interface OnSearchBarStateChangedListener extends TextWatcher {
139 | /**
140 | * 准备搜索的时候会调用改方法
141 | * @param searchEidt
142 | */
143 | public void onPrepareSearch(EditText searchEdit);
144 |
145 | /**
146 | * 搜索被取消的时候调用改方法
147 | * @param searchEidt
148 | */
149 | public void onCancel(EditText searchEdit);
150 |
151 | /**
152 | * 用户点击输入法中的搜索按钮
153 | * @param searchEdit
154 | *
155 | * @return true if search event was handled, and IME was not dismiss.
156 | * false otherwise
157 | */
158 | public boolean onSearchEvent(EditText searchEdit);
159 | }
160 |
161 | OnSearchBarStateChangedListener mStateChangedListener;
162 | OnSearchBarStateChangedListener mStateChangedListenerWrapper =
163 | new OnSearchBarStateChangedListener() {
164 |
165 | @Override
166 | public void beforeTextChanged(CharSequence s, int start,
167 | int count, int after) {
168 | if( mStateChangedListener != null ) {
169 | mStateChangedListener.beforeTextChanged(s, start, count, after);
170 | }
171 | }
172 |
173 | @Override
174 | public void onTextChanged(CharSequence s, int start,
175 | int before, int count) {
176 | if( mStateChangedListener != null ) {
177 | mStateChangedListener.onTextChanged(s, start, before, count);
178 | }
179 | }
180 |
181 | @Override
182 | public void afterTextChanged(Editable s) {
183 | if( mStateChangedListener != null ) {
184 | mStateChangedListener.afterTextChanged(s);
185 | }
186 | }
187 |
188 | @Override
189 | public void onPrepareSearch(EditText searchEdit) {
190 | if( mStateChangedListener != null ) {
191 | mStateChangedListener.onPrepareSearch(searchEdit);
192 | }
193 | }
194 |
195 | @Override
196 | public void onCancel(EditText searchEdit) {
197 | if( mStateChangedListener != null ) {
198 | mStateChangedListener.onCancel(searchEdit);
199 | }
200 | }
201 |
202 | @Override
203 | public boolean onSearchEvent(EditText searchEdit) {
204 | if( mStateChangedListener != null ) {
205 | return mStateChangedListener.onSearchEvent(searchEdit);
206 | }
207 | return false;
208 | }
209 |
210 | };
211 |
212 | public static class SimpleSearchBarStateChangedListener implements OnSearchBarStateChangedListener {
213 |
214 | @Override
215 | public void beforeTextChanged(CharSequence s, int start, int count, int after) {
216 | }
217 |
218 | @Override
219 | public void onTextChanged(CharSequence s, int start, int before, int count) {
220 | }
221 |
222 | @Override
223 | public void afterTextChanged(Editable s) {
224 | }
225 |
226 | @Override
227 | public void onPrepareSearch(EditText searchEdit) {
228 | }
229 |
230 | @Override
231 | public void onCancel(EditText searchEdit) {
232 | }
233 |
234 | @Override
235 | public boolean onSearchEvent(EditText searchEdit) {
236 | return false;
237 | }
238 |
239 | }
240 |
241 | }
242 |
--------------------------------------------------------------------------------
/SearchBarDemo/src/com/lwz/searchbar/demo/IndexAdapter.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014, 2015 Liu Wenzhu
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | *******************************************************************************/
22 | package com.lwz.searchbar.demo;
23 |
24 | import java.util.ArrayList;
25 | import java.util.Collection;
26 | import java.util.Comparator;
27 | import java.util.HashMap;
28 | import java.util.Map.Entry;
29 | import java.util.Set;
30 | import java.util.TreeMap;
31 |
32 | import android.content.Context;
33 | import android.view.LayoutInflater;
34 | import android.view.View;
35 | import android.view.ViewGroup;
36 | import android.widget.AdapterView;
37 | import android.widget.AdapterView.OnItemClickListener;
38 | import android.widget.BaseAdapter;
39 | import android.widget.TextView;
40 |
41 | /**
42 | * 索引适配器
43 | * @author Liu Wenzhu
44 | */
45 | public abstract class IndexAdapter extends BaseAdapter {
46 |
47 | public static enum ViewType {
48 | index, normal
49 | }
50 |
51 | public static interface Index {
52 | public String getIndex();
53 | }
54 |
55 | ArrayList mOriginData;
56 | ArrayList