带有拼音排序的列表仍是比较经常使用到的。好比手机通信录、好友列表等等这些均可以使用这种view来进行展现。具体的效果就像下面的同样。java
对汉字的排序咱们可使用集合里面的Collections.sort(List,Comparator)进行排序,固然,这个Comparator咱们须要重写一遍,以知足咱们的须要。具体代码能够参考下面的。android
/**
* 对集合进行中文拼音排序,排序依据是传入的字段名称
* @param <T> 泛型,泛指传入的对象类型
* @param list 集合,即将要排序的集合
* @param file 排序的依据字段
* @return 返回排序好的集合
*/
public static <T> List<T> sortForCn(List<T> list, final String file) {
try {
//对集合进行排序
Collections.sort(list,new Comparator<T>() {
@Override
public int compare(T o1,T o2) {
try {
// 经过属性获取对象的属性
Field field = o1.getClass().getDeclaredField(file);
// 对象的属性的访问权限设置为可访问
field.setAccessible(true);
// 获取属性的对应的值
String value = field.get(o1).toString();
// 经过属性获取对象的属性
Field fieldTwo = o2.getClass().getDeclaredField(file);
// 对象的属性的访问权限设置为可访问
fieldTwo.setAccessible(true);
// 获取属性的对应的值
String valueTwo = fieldTwo.get(o2).toString();
// TODO Auto-generated method stub
Comparator<Object> com = Collator.getInstance(java.util.Locale.SIMPLIFIED_CHINESE);
return com.compare(value, valueTwo);
}catch(Exception e) {
System.out.println("排序失败,具体失败缘由为:"+e.getLocalizedMessage());
return 0;
}
}
}
);
} catch (Exception e) {
System.out.println("排序失败,缘由:"+e.getLocalizedMessage());
return null;
}
return list;
}
复制代码
上面的排序方法我是放到了一个SortUtils的工具类里面,方便使用。由于在调用时才清楚具体要依据类里面的那个属性值来进行排序,故属性值的获取我直接使用映射的方式来获取了。须要排序时直接传入一个集合和须要排序的属性名称就能够了,放回结果是排序好的集合。git
自定义的view我是直接继承自LinearLayout的,固然,其余的也能够,只是为了后面布局里面调用时方便一点。我先贴除这个类里面的布局文件代码github
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/content"
android:layout_weight="1"/>
<RadioGroup
android:layout_width="25dp"
android:layout_height="wrap_content"
android:id="@+id/tab"
android:orientation="vertical"
android:layout_gravity="center"
android:gravity="center"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:clickable="true">
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="A"
android:button="@null"
android:layout_gravity="center"
android:gravity="center"
android:id="@+id/a"
android:textColor="@drawable/tab_bg"
android:checked="true"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="B"
android:button="@null"
android:layout_gravity="center"
android:gravity="center"
android:textColor="@drawable/tab_bg"
android:id="@+id/b"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="C"
android:button="@null"
android:textColor="@drawable/tab_bg"
android:layout_gravity="center"
android:gravity="center"
android:id="@+id/c"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="D"
android:button="@null"
android:textColor="@drawable/tab_bg"
android:layout_gravity="center"
android:gravity="center"
android:id="@+id/d"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="E"
android:button="@null"
android:textColor="@drawable/tab_bg"
android:layout_gravity="center"
android:gravity="center"
android:id="@+id/e"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="F"
android:button="@null"
android:layout_gravity="center"
android:textColor="@drawable/tab_bg"
android:gravity="center"
android:id="@+id/f"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="G"
android:button="@null"
android:textColor="@drawable/tab_bg"
android:layout_gravity="center"
android:gravity="center"
android:id="@+id/g"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="H"
android:button="@null"
android:layout_gravity="center"
android:textColor="@drawable/tab_bg"
android:gravity="center"
android:id="@+id/h"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="I"
android:button="@null"
android:layout_gravity="center"
android:textColor="@drawable/tab_bg"
android:gravity="center"
android:id="@+id/i"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="J"
android:button="@null"
android:layout_gravity="center"
android:textColor="@drawable/tab_bg"
android:gravity="center"
android:id="@+id/j"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="K"
android:button="@null"
android:layout_gravity="center"
android:textColor="@drawable/tab_bg"
android:gravity="center"
android:id="@+id/k"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="L"
android:button="@null"
android:layout_gravity="center"
android:textColor="@drawable/tab_bg"
android:gravity="center"
android:id="@+id/l"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="M"
android:button="@null"
android:layout_gravity="center"
android:textColor="@drawable/tab_bg"
android:gravity="center"
android:id="@+id/m"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="N"
android:button="@null"
android:textColor="@drawable/tab_bg"
android:layout_gravity="center"
android:gravity="center"
android:id="@+id/n"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="O"
android:button="@null"
android:layout_gravity="center"
android:textColor="@drawable/tab_bg"
android:gravity="center"
android:id="@+id/o"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="P"
android:textColor="@drawable/tab_bg"
android:button="@null"
android:layout_gravity="center"
android:gravity="center"
android:id="@+id/p"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="Q"
android:textColor="@drawable/tab_bg"
android:button="@null"
android:layout_gravity="center"
android:gravity="center"
android:id="@+id/q"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="R"
android:button="@null"
android:layout_gravity="center"
android:textColor="@drawable/tab_bg"
android:gravity="center"
android:id="@+id/r"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="S"
android:button="@null"
android:textColor="@drawable/tab_bg"
android:layout_gravity="center"
android:gravity="center"
android:id="@+id/s"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="T"
android:button="@null"
android:layout_gravity="center"
android:textColor="@drawable/tab_bg"
android:gravity="center"
android:id="@+id/t"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="U"
android:textColor="@drawable/tab_bg"
android:button="@null"
android:layout_gravity="center"
android:gravity="center"
android:id="@+id/u"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="V"
android:textColor="@drawable/tab_bg"
android:button="@null"
android:layout_gravity="center"
android:gravity="center"
android:id="@+id/v"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="W"
android:textColor="@drawable/tab_bg"
android:button="@null"
android:layout_gravity="center"
android:gravity="center"
android:id="@+id/w"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="25dp"
android:text="Z"
android:button="@null"
android:textColor="@drawable/tab_bg"
android:layout_gravity="center"
android:gravity="center"
android:id="@+id/z"/>
</RadioGroup>
<TextView
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_centerInParent="true"
tools:text="G"
android:visibility="gone"
android:gravity="center"
android:background="@drawable/alert_bg"
android:textSize="30dp"
android:id="@+id/alert"/>
</RelativeLayout>
复制代码
这个布局文件里面主体包含三部分,分别是数据列表,侧导航栏和点击导航栏时出现的提示,里面并无什么好介绍的,都是一看就懂的。让后咱们在自定义view的构造方法里面加入 LayoutInflater.from(context).inflate(R.layout.custom_recyclerview_classify,this,true);
这行代码就能够正常显示了bash
recyclerview的监听器主要目的是在活动时改变radioGroup的选中状态,radioGroup的监听器主要目的是在点击时,时recyclerview跳转到指定的位置。在写监听器以前,咱们须要引入一个依赖: implementation 'com.github.open-android:pinyin4j:2.5.0'
,在项目的gradle文件中加入maven { url "https://jitpack.io" }
。咱们使用这个的目的主要时获取须要排序字段的汉字的首字母。利用这个首字母,咱们能够很精确的改变radioGroup下的radioButton的状态。recyclerview滑动监听代码以下:maven
final HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
rec.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
//若是recyclerview中止滑动状态,容许点击tab栏
if (newState == 0){
isRecMove = false;
}else {
isRecMove = true;
}
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//滑动时获取屏幕第一条可见数据,并获取到此数据的行字首字母
int position = llm.findFirstVisibleItemPosition();
try{
//获取汉字首字母
String[] args = PinyinHelper.toHanyuPinyinStringArray(testBeams.get(position).getName().charAt(0), format);
//indexMap.get(String.valueOf(args[0].charAt(0)))为获取此条数据的汉字首字母在tab中的位置。
RadioButton radioButton = ((RadioButton)(tab.getChildAt(indexMap.get(String.valueOf(args[0].charAt(0))))));
radioButton.setChecked(true);
}catch (Exception e){
Log.e("日志","错误");
}
}
});
复制代码
上面的indexMap是一个hashmap,存放的是侧栏字母的位置。存放内容是indexMap.put("A",0);
这样的,一直put到24,就不贴出代码了。上面的代码中有注释,因该也好理解,**就是获取首条屏幕上出现的数据,从中获取数据中汉字的首字母,拿这个首字母到indexmap中获取到radiobutton在radiogroup中的位置,获取到位置后就能够直接改变状态了。**而后就到点击radiobutton时改变recyclerview位置的代码了,这部分代码都集中在radiogroup的监听器中。代码以下:ide
tab.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
try{
//若是是由于滑动recyclerview触发的,无需作任何处理,这里只处理右边tab点击时触发的事件
if (!isRecMove){
//获取点击位置的字母
String pinyin = ((RadioButton)(radioGroup.findViewById(radioGroup.getCheckedRadioButtonId()))).getText().toString();
if (recAdapter.getIndexMap().get(pinyin) != null){
int index = recAdapter.getIndexMap().get(pinyin);
//让recyclerview活动到对应的位置。recAdapter.getIndexMap().get(pinyin)是获取数据集合中第一条出现该字母数据的索引。
llm.scrollToPositionWithOffset(index,0);
llm.setStackFromEnd(true);
}
showOrHideAlert(pinyin);
}
}catch (Exception e){
Log.e("日志","出现错误:"+e.getLocalizedMessage());
}
}
});
复制代码
上面须要注意的时,若是直接使用recyclerview的scrollToPosition(position)这个方法并很差,因此换成了llm.scrollToPositionWithOffset(position,0)这个方法。recAdapter时recyclerview的adapter。实现原理是:点击radiobutton时,获取到按钮上的字母,经过字母到recAdapter里面的一个hashmap获取出现该字母的第一条数据的位置,而后让recyclerview跳转到此位置便可。showOrHideAlert(pinyin)这个方法主要是显示点击后的提示,代码不贴出了,后面能够到码云上去看。工具
这个adapter编写起来和平时同样,只是在设置数据时多设置了一个hashmap,这个map记录的是集合中相同字母出现的第一条记录,主要用户方便获取跳转地点用的。代码以下:布局
public void setList(List<TestBeam> testBeams){
this.testBeams = testBeams;
final HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
for (int i=0;i<testBeams.size();i++){
try{
String[] args = PinyinHelper.toHanyuPinyinStringArray(testBeams.get(i).getName().charAt(0), format);
//获取文字的第一个拼音
String pinyin = String.valueOf(args[0].charAt(0));
//保存第一条字母的索引位置,目的是后面能够快速跳转到对应的位置
if (indexMap.get(pinyin) == null){
indexMap.put(pinyin,i);
}else {
continue;
}
}catch (Exception e){
Log.e("日志","在第"+i+"个字符时转换失败,缘由:"+e.getLocalizedMessage());
}
}
notifyDataSetChanged();
}
复制代码
从代码不难看出,主要是遍历集合,保存第一个相同字母出现的位置而已。gradle
到这里一个能够实现汉字排序的view就制做完成了 码云地址