Android中ListView字母排序,实现字母挤压效果以及右侧快速选中字母,搜索关键字功能
来源:互联网 发布:万国数据是干嘛的 编辑:程序博客网 时间:2024/05/10 20:47
Android中ListView字母排序,实现字母挤压效果以及右侧快速选中字母,搜索关键字功能
本文中阐述如何自定义EditText实现搜索框自定义的样式以及挤压字母的思路等
- 自定义EditText
- 相关的drawable文件
- 主界面以及相关的适配器
- 结果展示
定义要呈现的EditText的样式
public class ClearEditText extends EditText implements OnFocusChangeListener, TextWatcher { /** * 定义删除按钮的引用 * */ private Drawable mClearDrawable; public ClearEditText(Context context) { this(context, null); } public ClearEditText(Context context, AttributeSet attrs) { //这个构造方法很重要,不加这个很多属性不能再XML中定义 this(context, attrs, android.R.attr.editTextStyle); } public ClearEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { //获取EidtText的DrawableRight,加入没有设置我们就使用自己的默认图片,getCompoundDrawables返回的是四个方向的图片信息 mClearDrawable = getCompoundDrawables()[2]; if (mClearDrawable == null) { mClearDrawable = getResources() .getDrawable(R.mipmap.emotionstore_progresscancelbtn); } //设置图片的宽高,前两个是组件左上角在容器中的坐标 后两个是组件的宽度和高度 mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight()); //默认初始化情况清空当前的图片信息 setClearIconVisible(false); //类似于文本框里面hint文字在初始化的时候显示或者隐藏的操作,就要用到setOnFocusChangeListener,同时监听有字符出现时就显示删除按钮 setOnFocusChangeListener(this); addTextChangedListener(this); } /** * 判断是否有删除按钮 * 设置删除按钮的点击事件:制空 * */ @Override public boolean onTouchEvent(MotionEvent event) { if (getCompoundDrawables()[2] != null) { if (event.getAction() == MotionEvent.ACTION_UP) { boolean touchable = event.getX() > (getWidth() - getPaddingRight() - mClearDrawable.getIntrinsicWidth()) && (event.getX() < ((getWidth() - getPaddingRight()))); if (touchable) { this.setText(""); } } } return super.onTouchEvent(event); } /** * 当焦点发生变化的情况设置删除按钮 * */ @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { setClearIconVisible(getText().length() > 0); } else { setClearIconVisible(false); } } /** * 设置删除按钮的显示或隐藏场景 * */ protected void setClearIconVisible(boolean visible) { Drawable right = visible ? mClearDrawable : null; setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], right, getCompoundDrawables()[3]); } /** * 判断是否有字符,如果有存在字符添加删除按钮 * */ @Override public void onTextChanged(CharSequence s, int start, int count, int after) { setClearIconVisible(s.length() > 0); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } public void setShakeAnimation(){ this.setAnimation(shakeAnimation(5)); } public static Animation shakeAnimation(int counts){ Animation translateAnimation = new TranslateAnimation(0, 10, 0, 0); translateAnimation.setInterpolator(new CycleInterpolator(counts)); translateAnimation.setDuration(1000); return translateAnimation; }}
ClearEditText设置获取焦点时的正在输入的样式以及背景样式相关的drawable文件
line_vertiacl文件
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@color/black"/> <size android:width="1dp"/></shape>
edit_background文件
stroke是外边框的边框宽度以及颜色
solid是填充的内部色彩
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@color/white"/> <stroke android:width="1dp" android:color="@color/green_light"/> <corners android:radius="30dp"/> <padding android:bottom="6dp" android:top="6dp" android:left="12dp" android:right="6dp" /></shape>
自定义SideBar实现右边的26个字母显示快捷选取目标
public class SideBar extends View { //触摸事件 private OnTouchingLetterChangedListener onTouchingLetterChangedListener; //26个字母 public static String[] b = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "#" }; private int choose = -1;// 选中的 private Paint paint = new Paint(); private TextView mTextDialog; public void setTextView(TextView mTextDialog) { this.mTextDialog = mTextDialog; } public SideBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public SideBar(Context context, AttributeSet attrs) { super(context, attrs); } public SideBar(Context context) { super(context); } /** * 重绘界面 */ protected void onDraw(Canvas canvas) { super.onDraw(canvas); //获取焦点改变背景颜色 int height = getHeight();// 获取对应高度 int width = getWidth(); // 获取对应宽度 int singleHeight = height / b.length;// 获取每一个字母的高度 for (int i = 0; i < b.length; i++) { //设置每一个字母的样式 paint.setColor(Color.rgb(33, 65, 98)); // paint.setColor(Color.WHITE); paint.setTypeface(Typeface.DEFAULT_BOLD); paint.setAntiAlias(true); paint.setTextSize(30); //选中状态 if (i == choose) { paint.setColor(Color.parseColor("#3399ff")); paint.setFakeBoldText(true); } // x坐标等于中间-字符串宽度一半 float xPos = width / 2 - paint.measureText(b[i]) / 2; //高度增加递增 float yPos = singleHeight * i + singleHeight; canvas.drawText(b[i], xPos, yPos, paint); paint.reset();// 重置画笔 } } /** * 点击的时候的状态 * */ @Override public boolean dispatchTouchEvent(MotionEvent event) { final int action = event.getAction(); final float y = event.getY();// 点击Y坐标 final int oldChoose = choose; final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener; final int c = (int) (y / getHeight() * b.length);// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数. switch (action) { case MotionEvent.ACTION_UP: setBackgroundDrawable(new ColorDrawable(0x00000000)); choose = -1; invalidate(); if (mTextDialog != null) { mTextDialog.setVisibility(View.INVISIBLE); } break; default: setBackgroundResource(R.drawable.sidebar_background); if (oldChoose != c) { if (c >= 0 && c < b.length) { if (listener != null) { listener.onTouchingLetterChanged(b[c]); } if (mTextDialog != null) { mTextDialog.setText(b[c]); mTextDialog.setVisibility(View.VISIBLE); } choose = c; invalidate(); } } break; } return true; } /** *向外公开的方法 * * @param onTouchingLetterChangedListener */ public void setOnTouchingLetterChangedListener( OnTouchingLetterChangedListener onTouchingLetterChangedListener) { this.onTouchingLetterChangedListener = onTouchingLetterChangedListener; } /** * 接口 * * @author coder * */ public interface OnTouchingLetterChangedListener { public void onTouchingLetterChanged(String s); }}
主界面的布局展示
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="fill_parent" android:orientation="vertical" android:focusable="true" android:focusableInTouchMode="true" tools:context="demo.test.com.myself.sortlistview.SortActivity"> <demo.test.com.myself.sortlistview.ClearEditText android:layout_margin="6dp" android:textCursorDrawable="@drawable/line_vertiacl" android:id="@+id/filter_edit" android:layout_marginTop="5dip" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/edit_background" android:drawableLeft="@mipmap/search_bar_icon_normal" android:hint="请输入关键字" android:singleLine="true" android:textSize="15.0dip" /> <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent" > <ListView android:id="@+id/country_lvcountry" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center" android:divider="@null" /> <!--设置就是设置顶部的字母排序--> <LinearLayout android:id="@+id/title_layout" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:background="#E0E0E0" > <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:textColor="#454545" android:paddingLeft="5dip" android:paddingTop="5dip" android:paddingBottom="5dip" android:text="A"/> </LinearLayout> <TextView android:id="@+id/dialog" android:layout_width="80.0dip" android:layout_height="80.0dip" android:layout_gravity="center" android:background="@drawable/toast_bg" android:gravity="center" android:textColor="#ffffffff" android:textSize="30.0dip" android:visibility="invisible" /> <demo.test.com.myself.sortlistview.SideBar android:id="@+id/sidrbar" android:layout_width="30.0dip" android:layout_height="fill_parent" android:layout_gravity="right|center" /> </FrameLayout></LinearLayout>
自定义的显示的数据Bean
public class SortModel { private String name; //显示的数据 private String sortLetters; //显示数据拼音的首字母 public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSortLetters() { return sortLetters; } public void setSortLetters(String sortLetters) { this.sortLetters = sortLetters; }}
按字母大小排序比较器实现
public class PinyinComparator implements Comparator<SortModel> { public int compare(SortModel o1, SortModel o2) { if (o1.getSortLetters().equals("@") || o2.getSortLetters().equals("#")) { return -1; } else if (o1.getSortLetters().equals("#") || o2.getSortLetters().equals("@")) { return 1; } else { return o1.getSortLetters().compareTo(o2.getSortLetters()); } }}
最重要的一步是要中文转拼音的操作,需要在网络中下载pinyin4j-2.5.0.jar或更高版本作为依赖添加到程序中,添加后实现转拼音方法
public static String getPingYin(String inputString) { HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat(); format.setCaseType(HanyuPinyinCaseType.LOWERCASE); format.setToneType(HanyuPinyinToneType.WITHOUT_TONE); format.setVCharType(HanyuPinyinVCharType.WITH_V); char[] input = inputString.trim().toCharArray(); String output = ""; try { for (char curchar : input) { if (java.lang.Character.toString(curchar).matches("[\u4e00-\u9fa5]+")) { String[] temp = PinyinHelper.toHanyuPinyinStringArray(curchar, format); output += temp[0]; } else output += java.lang.Character.toString(curchar); } } catch (BadHanyuPinyinOutputFormatCombination e) { e.printStackTrace(); } return output; }
主界面数据展示
public class SortActivity extends Activity { private ListView sortListView; private SideBar sideBar; private TextView dialog; private SortAdapter adapter; private ClearEditText mClearEditText; /** * 上次第一个可见元素,用于滚动时记录标识。 */ private int lastFirstVisibleItem = -1; private List<SortModel> SourceDateList; /** * 根据拼音来排列ListView里面的数据类 */ private PinyinComparator pinyinComparator; /** * 分组的布局 */ private LinearLayout titleLayout; /** * 分组上显示的字母 */ private TextView title; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sort); initViews(); } private void initViews() { titleLayout = (LinearLayout) findViewById(R.id.title_layout); title = (TextView) findViewById(R.id.title); pinyinComparator = new PinyinComparator(); sideBar = (SideBar) findViewById(R.id.sidrbar); dialog = (TextView) findViewById(R.id.dialog); sideBar.setTextView(dialog);//设置相应的字体背景样式 //设置右侧触摸监听 sideBar.setOnTouchingLetterChangedListener(new SideBar.OnTouchingLetterChangedListener() { @Override public void onTouchingLetterChanged(String s) { //该字母首次出现的位置 int position = adapter.getPositionForSection(s.charAt(0)); if (position != -1) { sortListView.setSelection(position); } } }); sortListView = (ListView) findViewById(R.id.country_lvcountry); sortListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //这里要利用adapter.getItem(position)来获取当前position所对应的对象 Toast.makeText(getApplication(), ((SortModel) adapter.getItem(position)).getName()+"="+position, Toast.LENGTH_SHORT).show(); } }); SourceDateList = getData(getResources().getStringArray(R.array.date)); // 根据a-z进行排序源数据 Collections.sort(SourceDateList, pinyinComparator); adapter = new SortAdapter(this, SourceDateList, this); sortListView.setAdapter(adapter); sortListView.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {// LogUtils.i(+visibleItemCount+"=当前对呀的Item是="+firstVisibleItem); //字母连续断层使不能置顶,例如 D (空) F使D到F阶段不存在置顶 int section; try{ section = adapter.getSectionForPosition(firstVisibleItem); }catch (Exception e){ return ; } int nextSecPosition = adapter.getPositionForSection(section + 1); //解决断层置顶 for (int i = 1; i < 30; i++) { //26个英文字母充分循环 if (nextSecPosition == -1) { //继续累加 int data = section + 1 + i; nextSecPosition = adapter.getPositionForSection(data); } else { break; } } if (firstVisibleItem != lastFirstVisibleItem) { ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) titleLayout.getLayoutParams(); params.topMargin = 0; titleLayout.setLayoutParams(params); title.setText(String.valueOf((char) section)); } if (nextSecPosition == firstVisibleItem + 1) { View childView = view.getChildAt(0); if (childView != null) { int titleHeight = titleLayout.getHeight(); int bottom = childView.getBottom(); ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) titleLayout .getLayoutParams(); if (bottom < titleHeight) { float pushedDistance = bottom - titleHeight; params.topMargin = (int) pushedDistance; titleLayout.setLayoutParams(params); } else { if (params.topMargin != 0) { params.topMargin = 0; titleLayout.setLayoutParams(params); } } } } lastFirstVisibleItem = firstVisibleItem; } }); mClearEditText = (ClearEditText) findViewById(R.id.filter_edit); //根据输入框输入值的改变来过滤搜索 mClearEditText.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { //当输入框里面的值为空,更新为原来的列表,否则为过滤数据列表 filterData(s.toString()); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }); } private List<SortModel> getData(String[] data) { List<SortModel> listarray = new ArrayList<SortModel>(); for (int i = 0; i < data.length; i++) { String pinyin = CharacterParser.getPingYin(data[i]); String Fpinyin = pinyin.substring(0, 1).toUpperCase(); SortModel person = new SortModel(); person.setName(data[i]); //person.setPinYin(pinyin); // 正则表达式,判断首字母是否是英文字母 if (Fpinyin.matches("[A-Z]")) { person.setSortLetters(Fpinyin); } else { person.setSortLetters("#"); } listarray.add(person); } return listarray; } /** * 根据输入框中的值来过滤数据并更新ListView * * @param filterStr */ private void filterData(String filterStr) { List<SortModel> filterDateList = new ArrayList<SortModel>(); if (TextUtils.isEmpty(filterStr)) { filterDateList = SourceDateList; titleLayout.setVisibility(View.VISIBLE); title.setText("A"); } else { titleLayout.setVisibility(View.GONE); filterDateList.clear(); for (SortModel sortModel : SourceDateList) { String name = sortModel.getName(); if (name.indexOf(filterStr.toString()) != -1 || CharacterParser.getPingYin(name).startsWith(filterStr.toString())) { filterDateList.add(sortModel); } } } // 根据a-z进行排序 Collections.sort(filterDateList, pinyinComparator); adapter.updateListView(filterDateList); }}
适配器adapter展示
public class SortAdapter extends BaseAdapter implements SectionIndexer{ private List<SortModel> list = null; private Context mContext; public SortAdapter(Context context, List<SortModel> list ) { this.mContext = context; this.list = list; } public void updateListView(List<SortModel> list){ this.list = list; notifyDataSetChanged(); } public int getCount() { return this.list.size(); } public SortModel getItem(int position) { return list.get(position); } public long getItemId(int position) { return position; } public View getView(final int position, View view, ViewGroup arg2) { ViewHolder viewHolder = null; final SortModel mContent = list.get(position); if (view == null) { viewHolder = new ViewHolder(); view = LayoutInflater.from(mContext).inflate(R.layout.item, null); viewHolder.tvTitle = (TextView) view.findViewById(R.id.title); viewHolder.tvLetter = (TextView) view.findViewById(R.id.catalog); view.setTag(viewHolder); } else { viewHolder = (ViewHolder) view.getTag(); } //// 获取首字母的assii值 int section = getSectionForPosition(position); //通过首字母的assii值来判断是否显示字母 int positionForSelection = getPositionForSection(section); viewHolder.tvLetter.setOnClickListener(null); if(position == getPositionForSection(section)){ viewHolder.tvLetter.setVisibility(View.VISIBLE); viewHolder.tvLetter.setText(mContent.getSortLetters()); }else{ viewHolder.tvLetter.setVisibility(View.GONE); } viewHolder.tvTitle.setText(this.list.get(position).getName()); return view; } final static class ViewHolder { TextView tvLetter; TextView tvTitle; } public int getSectionForPosition(int position) { return list.get(position).getSortLetters().charAt(0); } public int getPositionForSection(int section) { for (int i = 0; i < getCount(); i++) { String sortStr = list.get(i).getSortLetters(); char firstChar = sortStr.toUpperCase().charAt(0); if (firstChar == section) { return i; } } return -1; } @Override public Object[] getSections() { return null; }}
结果展示
源码下载(请记得给好评哦,有什么问题可以留言提问,作者会尽快给予解决,O(∩_∩)O谢谢)
http://download.csdn.net/detail/wyh_healer/9566682
0 0
- Android中ListView字母排序,实现字母挤压效果以及右侧快速选中字母,搜索关键字功能
- Android 仿联系人列表 实现ListView的A-Z字母排序和过滤搜索功能,并挤压效果(一)
- Android 仿联系人列表 实现ListView的A-Z字母排序和过滤搜索功能,并挤压效果
- Android listView按字母排序,关键字搜索功能
- Android右侧字母排序
- Android联系人列表,实现ListView的A-Z字母排序和过滤搜索功能,字母条目上顶
- Android ListView的字母排序和过滤搜索功能
- ListView实现SectionIndex,实现右侧栏字母的快速滑动
- Android 实现ListView的A-Z字母排序和过滤搜索功能,实现汉字转成拼音
- Android实现ListView的A-Z字母排序和过滤搜索功能,实现汉字转成拼音
- Android实现ListView的A-Z字母排序和过滤搜索功能,实现汉字转成拼音
- Android实现ListView的A-Z字母排序和过滤搜索功能,实现汉字转成拼音
- Android实现ListView的A-Z字母排序和过滤搜索功能,实现汉字转成拼音
- Android 实现ListView的A-Z字母排序和过滤搜索功能,实现汉字转成拼音
- Android 实现ListView的A-Z字母排序和过滤搜索功能,实现汉字转成拼音
- Android 实现ListView的A-Z字母排序和过滤搜索功能,实现汉字转成拼音
- Android 实现ListView的A-Z字母排序和过滤搜索功能,实现汉字转成拼音
- Android 实现ListView的A-Z字母排序和过滤搜索功能,实现汉字转成拼音
- 推送网页到kindle
- 开发平台的演变
- swift 学习指南
- play_scala框架学习04 表单
- 一个多maven项目聚合的实例
- Android中ListView字母排序,实现字母挤压效果以及右侧快速选中字母,搜索关键字功能
- 给VMware下的Linux扩展磁盘空间(以CentOS6.3为例)
- POM
- HttpClient模仿登陆并维持同一session请求(HttpClient4.3.X以上版本)
- play_scala框架学习05 数据库
- Kafka深度解析
- Spring Data Elasticsearch
- Retinex去照度算法
- Unity3D研究院之IOS&Android收集Log文件