帶有拼音排序的列表仍是比較經常使用到的。好比手機通信錄、好友列表等等這些均可以使用這種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就製做完成了 碼雲地址