先上效果:
aa.gif
文字描述我就不写了,直接上代码:
1.中文转拼音工具类,要用到pinyin4android.jar和pinyin4j-2.5.0.jar
public class PingYinUtil implements Comparator<Object> {
// @Override
// public int compare(Object o1, Object o2) {
// String[] str1=(String[])o1;
// String[] str2=(String[])o2;
// String pingYin1 = getPingYin(str1[1]);
// String pingYin2 = getPingYin(str2[1]);
// return pingYin1.compareTo(pingYin2);
// }
@Override
public int compare(Object o1, Object o2) {
String str1 = (String) o1;
String str2 = (String) o2;
String pingYin1 = getPingYin(str1.substring(0, 1));
String pingYin2 = getPingYin(str2.substring(0, 1));
return pingYin1.compareTo(pingYin2);
}
/**
* 将字符串中的中文转化为拼音,其他字符不变
*/
public static String getPingYin(String inputString) {
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
format.setVCharType(HanyuPinyinVCharType.WITH_V);
Pattern p = Pattern.compile("^[\u4E00-\u9FA5A-Za-z_]+$");
Matcher matcher = p.matcher(inputString.substring(0, 1));
if (matcher.find()) {
char[] input = inputString.trim().toCharArray();
String output = "";
try {
for (int i = 0; i < input.length; i++) {
if (Character.toString(input[i]).matches("[\\u4E00-\\u9FA5]+")) {
String[] temp = PinyinHelper.toHanyuPinyinStringArray(input[i], format);
output += temp[0];
} else
output += Character.toString(input[i]);
}
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
}
return output;
} else {
return "";
}
}
public static String converterToFirstSpell(String chines) {
String pinyinName = "";
char[] nameChar = chines.toCharArray();
HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
defaultFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE);
defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
for (int i = 0; i < nameChar.length; i++) {
if (nameChar[i] > 128) {
try {
pinyinName += PinyinHelper.toHanyuPinyinStringArray(nameChar[i], defaultFormat)[0].charAt(0);
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
}
} else {
pinyinName += nameChar[i];
}
}
return pinyinName;
}
}
或者使用系统自带的中文根据拼音排序,以下是工具类
/**
* android官方提供的排序方法
*/
public class CheaseChatCom implements Comparator {
@Override
public int compare(Object o1, Object o2) {
//中文排序
Collator collator = Collator.getInstance(Locale.CHINA);
if (collator.compare(o1, o2) < 0)
return -1;
else if (collator.compare(o1, o2) > 0)
return 1;
else
return 0;
}
}
数据分类
/**
* 每一条item的数据
*/
public class ItemEntity {
String name;
String title;
Boolean showTitle;
public ItemEntity(String name, String title,Boolean showTitle) {
this.name = name;
this.title = title;
this.showTitle=showTitle;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Boolean getShowTitle() {
return showTitle;
}
public void setShowTitle(Boolean showTitle) {
this.showTitle = showTitle;
}
@Override
public String toString() {
return "ItemEntity{" +
"name='" + name + '\'' +
", title='" + title + '\'' +
", showTitle=" + showTitle +
'}';
}
}
用到的adapter
public class Test3Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static final Integer TITLE_ITEM = 0x10;
public static final Integer NORMAL_ITEM = 0x11;
public static final Integer ZORE_ITEM = 0x12;
List<ItemEntity> data;
public Test3Adapter(List<ItemEntity> data) {
this.data = data;
}
public List<ItemEntity> getData() {
return data;
}
@Override
public int getItemViewType(int position) {
if (position == 0) {
return ZORE_ITEM;
} else {
ItemEntity itemEntity = data.get(position-1);
Boolean showTitle = itemEntity.getShowTitle();
if (showTitle) {
return TITLE_ITEM;
} else {
return NORMAL_ITEM;
}
}
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (viewType==ZORE_ITEM){
return new Holder2(LayoutInflater.from(parent.getContext()).inflate(
R.layout.rv_zore_item, parent, false
));
}else {
return new Holder(LayoutInflater.from(parent.getContext()).inflate(
R.layout.rv_item, parent, false
));
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (holder instanceof Holder){
ItemEntity itemEntity = data.get(position-1);
Boolean showTitle = itemEntity.getShowTitle();
if (showTitle) {
if (position == 1) {
((Holder)holder).title.setVisibility(View.GONE);
} else {
((Holder)holder).title.setText(itemEntity.getTitle());
((Holder)holder).title.setVisibility(View.VISIBLE);
}
} else {
((Holder)holder).title.setVisibility(View.GONE);
}
((Holder)holder).content.setText(itemEntity.getName());
}
}
@Override
public int getItemCount() {
return data.size()+1;
}
static class Holder extends RecyclerView.ViewHolder {
private final TextView title;
private final TextView content;
Holder(@NonNull View itemView) {
super(itemView);
title = itemView.findViewById(R.id.title);
content = itemView.findViewById(R.id.content);
}
}
static class Holder2 extends RecyclerView.ViewHolder {
Holder2(@NonNull View itemView) {
super(itemView);
}
}
}
adapter用到的布局
<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="vertical" />
<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
android:background="@android:color/white"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="36dp"
android:gravity="center_vertical"
android:paddingStart="12dp"
android:paddingLeft="12dp"
android:textColor="@android:color/darker_gray"
android:textSize="15sp"
tools:ignore="RtlSymmetry"
tools:text="A" />
<TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="42dp"
android:gravity="center_vertical"
android:paddingStart="12dp"
android:paddingLeft="12dp"
android:textColor="@android:color/black"
android:textSize="16sp"
tools:ignore="RtlSymmetry"
tools:text="阿塞拜疆" />
</LinearLayout>
在activity中使用
public class Main3Activity extends AppCompatActivity {
final String TAG = getClass().getSimpleName();
List<String> labelList = new ArrayList<>();
private StringBuilder sb;
private RecyclerView rv;
private AppCompatTextView label;
private LinearLayoutManager manager;
private Test3Adapter test3Adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
rv = findViewById(R.id.rv);
label = findViewById(R.id.label);
manager = new LinearLayoutManager(
this, RecyclerView.VERTICAL, false);
rv.setLayoutManager(manager);
labelList.add("阿凡达");
labelList.add("浙江");
labelList.add("舒服可");
labelList.add("湖北");
labelList.add("河南");
labelList.add("江苏");
labelList.add("广东");
labelList.add("四川");
labelList.add("新疆");
labelList.add("西藏");
labelList.add("江门");
labelList.add("阿叔克");
labelList.add("林芝");
labelList.add("陕西");
labelList.add("北京");
labelList.add("江西");
labelList.add("阿塞拜疆");
labelList.add("南京");
labelList.add("阿福级");
labelList.add("山西");
labelList.add("天津");
labelList.add("上海");
labelList.add("阿骨打");
labelList.add("杭州");
labelList.add("武汉");
labelList.add("武威");
labelList.add("山东");
CheaseChatCom cheaseChatCom = new CheaseChatCom();
Collections.sort(labelList, cheaseChatCom);
if (sb == null)
sb = new StringBuilder();
List<ItemEntity> itemEntities = new ArrayList<>();
for (String s : labelList) {
String aCase = PingYinUtil.getPingYin(s).substring(0, 1).toUpperCase();
// Log.i(TAG, "======= " + aCase);
if (!sb.toString().contains(aCase)) {
ItemEntity itemEntity = new ItemEntity(s, aCase, true);
itemEntities.add(itemEntity);
sb.append(aCase);
} else {
ItemEntity itemEntity = new ItemEntity(s, aCase, false);
itemEntities.add(itemEntity);
}
}
test3Adapter = new Test3Adapter(itemEntities);
rv.setAdapter(test3Adapter);
label.setText(itemEntities.get(0).getTitle());
rvScrollListener();
// String s = append.toString();
// Log.i(TAG, s);
}
private int labelHeight;
private int mCurrentPosition;
private void rvScrollListener() {
rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
labelHeight = label.getHeight();
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (mCurrentPosition != 0 && test3Adapter.getItemViewType(mCurrentPosition + 1)
== Test3Adapter.TITLE_ITEM) {
View nextView = manager.findViewByPosition(mCurrentPosition + 1);
if (nextView != null) {
float y = nextView.getTop();
if (y <= labelHeight) {
float v = labelHeight - y;
label.setY(-v);
} else {
label.setY(0);
}
}
}
//manager.findFirstVisibleItemPosition() 获取当前窗口可以看见的第一个Item的位置
if (mCurrentPosition != manager.findFirstVisibleItemPosition()) {
mCurrentPosition = manager.findFirstVisibleItemPosition();
Log.i(TAG, "====== mCurrentPosition:" + mCurrentPosition);
if (mCurrentPosition == 0) {
updateSuspensionBar(mCurrentPosition);
} else {
updateSuspensionBar(mCurrentPosition - 1);
}
label.setY(0);
}
}
});
}
private void updateSuspensionBar(int position) {
List<ItemEntity> data = test3Adapter.getData();
if (data != null) {
ItemEntity itemEntity = data.get(position);
label.setText(itemEntity.getTitle());
}
}
}
activity的布局
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@android:color/white"
tools:context=".activitys.Main3Activity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/label"
android:layout_width="match_parent"
android:layout_height="40dp"
android:paddingStart="12dp"
android:background="@android:color/white"
android:gravity="center_vertical"
android:textColor="@android:color/darker_gray"
android:textSize="16sp"
android:textStyle="bold"
tools:text="标签"
android:paddingLeft="12dp"
tools:ignore="RtlSymmetry" />
</FrameLayout>
参考博文:https://www.jianshu.com/p/0a7ec9580cb9
另外有一篇博文是通过RecyclerView的分隔线实现的,我没有去实现,各位有兴趣可以试下:https://www.jianshu.com/p/f4e3abfab18c
网友评论