Android实现recyclerview城市字母索引列表
作者:“嗯哈 发布时间:2023-09-28 04:22:06
标签:Android,RecyclerView
转拼音的依赖
implementation 'com.github.SilenceDut:jpinyin:v1.0'
FastIndexView实现列表右侧字母索引列表
public class FastIndexView extends View {
private static final String INDEX_NAME = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private OnLetterUpdateListener listener;
private Paint mPaint;
private float cellHeight, viewWidth;
private int touchIndex = -1, selectedColor;
public FastIndexView(Context context) {
this(context, null);
}
public FastIndexView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public FastIndexView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
mPaint.setTextSize(AppUtils.dp2px(14));
mPaint.setAntiAlias(true);
//获取文字被选中的颜色
// selectedColor = ContextCompat.getColor(context, );
selectedColor = Color.parseColor("#999DA1");
}
@Override
protected void onDraw(Canvas canvas) {
for (int i = 0; i < INDEX_NAME.length(); i++) {
String text = INDEX_NAME.substring(i, i + 1);
//计算绘制字符的X方向起点
int x = (int) (viewWidth / 2.0f - mPaint.measureText(text) / 2.0f);
Rect bounds = new Rect();
mPaint.getTextBounds(text, 0, text.length(), bounds);
int textHeight = bounds.height();
//计算绘制字符的Y方向起点
int y = (int) (cellHeight / 2.0f + textHeight / 2.0f + i
* cellHeight);
mPaint.setColor(/*touchIndex == i ? Color.WHITE : */selectedColor);
canvas.drawText(text, x, y, mPaint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int index;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//计算当前触摸的字符索引
index = (int) (event.getY() / cellHeight);
if (index >= 0 && index < INDEX_NAME.length()) {
if (listener != null) {
listener.onLetterUpdate(INDEX_NAME.substring(index, index + 1));
}
touchIndex = index;
}
break;
case MotionEvent.ACTION_MOVE:
//计算当前触摸的字符索引
index = (int) (event.getY() / cellHeight);
if (index >= 0 && index < INDEX_NAME.length()) {
if (index != touchIndex) {
if (listener != null) {
listener.onLetterUpdate(INDEX_NAME.substring(index, index + 1));
}
touchIndex = index;
}
}
break;
}
invalidate();
return true;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//得到当前控件的宽度
viewWidth = getMeasuredWidth();
int mHeight = getMeasuredHeight();
//获取单个字符能够拥有的高度
cellHeight = mHeight * 1.0f / INDEX_NAME.length();
}
public interface OnLetterUpdateListener {
void onLetterUpdate(String letter);
}
public void setListener(OnLetterUpdateListener listener) {
this.listener = listener;
}
}
public class AppUtils {
private static float density;
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dp2px(float dpValue) {
if (density == 0)
density = Resources.getSystem().getDisplayMetrics().density;
return (int) (0.5f + dpValue * Resources.getSystem().getDisplayMetrics().density);
}
}
CityAdapter
public class CityAdapter extends RecyclerView.Adapter<CityAdapter.BaseViewHolder> {
private List<CityInfoModel> mDatas;
private Context mContext;
public CityAdapter(Context context, List<CityInfoModel> data) {
this.mDatas = data;
this.mContext = context;
}
@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//创建不同的 ViewHolder
View view = null;
//根据viewtype来创建条目
view = LayoutInflater.from(mContext).inflate(R.layout.item_layout_normal, parent, false);
return new NormalHolder(view);
}
@Override
public void onBindViewHolder(BaseViewHolder holder, final int position) {
CityInfoModel cityInfoModel = mDatas.get(position);
NormalHolder realHolder = (NormalHolder) holder;
realHolder.tvContent.setText(cityInfoModel.getCityName());
realHolder.tvContent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
}
static class BaseViewHolder extends RecyclerView.ViewHolder {
BaseViewHolder(View itemView) {
super(itemView);
}
}
@Override
public int getItemCount() {
if (mDatas != null) {
return mDatas.size();
}
return 0;
}
private class NormalHolder extends BaseViewHolder {
TextView tvContent;
public NormalHolder(View itemView) {
super(itemView);
tvContent = itemView.findViewById(R.id.tv_city);
}
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
@BindView(R.id.recy_list)
RecyclerView recyList;
@BindView(R.id.fastIndexView)
FastIndexView fastIndexView;
//主要用于展示数据的list
private List<CityInfoModel> list;
//第一次加载之后缓存的数据
private List<CityInfoModel> cacheList;
//页面recyclerview的适配器
private CityAdapter mainAdapter;
//布局管理器
private LinearLayoutManager layoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
initAdapter();
initListener();
}
private void initAdapter() {
list = new ArrayList<>();
cacheList = new ArrayList<>();
list.add(new CityInfoModel("安徽省"));
list.add(new CityInfoModel("北京市"));
list.add(new CityInfoModel("上海市"));
list.add(new CityInfoModel("广州市"));
list.add(new CityInfoModel("深圳市"));
list.add(new CityInfoModel("天津市"));
list.add(new CityInfoModel("南京市"));
list.add(new CityInfoModel("杭州市"));
list.add(new CityInfoModel("重庆市"));
list.add(new CityInfoModel("成都市"));
list.add(new CityInfoModel("石家庄市"));
list.add(new CityInfoModel("自贡市"));
list.add(new CityInfoModel("攀枝花市"));
list.add(new CityInfoModel("泸州市"));
list.add(new CityInfoModel("德阳市"));
list.add(new CityInfoModel("绵阳市"));
list.add(new CityInfoModel("广元市"));
list.add(new CityInfoModel("遂宁市"));
List<CityInfoModel> cityInfoModels = bindData(list);
layoutManager = new LinearLayoutManager(this);
recyList.setLayoutManager(layoutManager);
recyList.addItemDecoration(new CustomItemDecoration(this, new CustomItemDecoration.TitleDecorationCallback() {
@Override
public String getGroupId(int position) {
//这个是用来比较是否是同一组数据的
return list.get(position).getSortId();
}
@Override
public String getGroupName(int position) {
CityInfoModel cityInfoModel = list.get(position);
//拼音都是小写的
return cityInfoModel.getSortId().toUpperCase();
}
}));
mainAdapter = new CityAdapter(this, cityInfoModels);
recyList.setAdapter(mainAdapter);
}
private void initListener() {
fastIndexView.setListener(new FastIndexView.OnLetterUpdateListener() {
@Override
public void onLetterUpdate(String letter) {
moveToLetterPosition(letter);
}
});
}
//滚动recyclerview
private void moveToLetterPosition(String letter) {
//这里主要是为了跳转到最顶端
if ("#".equals(letter)) {
letter = "*";
}
for (int i = 0; i < list.size(); i++) {
CityInfoModel cityInfoModel = list.get(i);
if (cityInfoModel.getSortId().toUpperCase().equals(letter)) {
layoutManager.scrollToPositionWithOffset(i, 0);
return;
}
}
}
/**
* 给View绑定数据
*
* @param allCity 所有城市列表
*/
public List<CityInfoModel> bindData(List<CityInfoModel> allCity) {
if (allCity != null) {
for (CityInfoModel cityModel : allCity) {
try {
String pingYin = PinyinHelper.convertToPinyinString(cityModel.getCityName(), " ", PinyinFormat.WITHOUT_TONE);
cacheList.add(new CityInfoModel(cityModel.getCityName(), pingYin.substring(0, 1), pingYin));
} catch (PinyinException e) {
e.printStackTrace();
}
}
//排序
Collections.sort(cacheList, new Comparator<CityInfoModel>() {
@Override
public int compare(CityInfoModel o1, CityInfoModel o2) {
return o1.getSortName().compareTo(o2.getSortName());
}
});
this.list.clear();
this.list.addAll(cacheList);
}
return list;
}
}
CityInfoModel
public class CityInfoModel {
private String cityName;//用于显示的城市的名字
private String sortId;//用于排序的id 在这里是城市拼音的首字母
private String sortName;//用于排序的全拼音 这个是用于后面的排序以及搜索
public CityInfoModel(String cityName) {
this.cityName = cityName;
}
public CityInfoModel(String cityName, String sortId, String sortName) {
this.cityName = cityName;
this.sortId = sortId;
this.sortName = sortName;
}
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
public String getSortId() {
return sortId;
}
public void setSortId(String sortId) {
this.sortId = sortId;
}
public String getSortName() {
return sortName;
}
public void setSortName(String sortName) {
this.sortName = sortName;
}
}
activity_main
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recy_list"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<com.simin.indexrecyclerview.FastIndexView
android:id="@+id/fastIndexView"
android:layout_width="25dp"
android:layout_height="match_parent"
app:layout_constraintHeight_percent="0.7" />
</LinearLayout>
来源:https://blog.csdn.net/weixin_43117800/article/details/122583071


猜你喜欢
- 语法糖指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程
- 具体解释请仔细看注释里已经讲解的很细致了,这里就不多废话了using UnityEngine;using System.Collection
- 一.服务端代码:import java.net.*; // for Socket, ServerSocket, and InetAddres
- 本文实例为大家分享了javaweb多文件上传及zip打包下载的具体代码,供大家参考,具体内容如下项目中经常会使用到文件上传及下载的功能。本篇
- Docker 存储驱动详细介绍最近做项目,期间对Docker 存储驱动不会,于是在网上找资料,并解决了,这里就记录下。目的理解docker的
- 只要了解过多线程,我们就知道线程开始的顺序跟执行的顺序是不一样的。如果只是创建三个线程然后执行,最后的执行顺序是不可预期的。这是因为在创建完
- 前言相信大家都用过Spring Security和Shiro的框架,Spring Security必须配合Spring 全家桶使用和繁琐的配
- 前言前段时间看到一道面试题:“main函数可以被重载么?”,当时就蒙圈了,怎么还会有这种面试题,现在
- Web UI项目中, 很多 Spring controller 视图函数直接返回 html 页面, 还有一些视图函数是要重定向或转发到其他的
- Android 媒体库数据更新方法总结在项目中,我们经常要创建个自己的目录,里面存放一些图片啊文件之类,比如:我在SD卡中刚创建了一个文件夹
- 一、准备工作1、你需要android手机应用开发基础2、科大讯飞语音识别SDK android版3、科大讯飞语音识别开发API文档4、and
- 1.注解方式,yml文件配置上以下就可以直接使用mybatis-plus: mapper-locations: classpath:mapp
- 所谓前人栽树,后人乘凉,在此感谢博主的贡献。 原文:边缘凹凸的卡劵效果先上效果图:我实现的效果和原博主实现的效果是不一样的,我是左右边缘凹凸
- 很多童鞋反应在吧项目导入到eclipse(myeclipse)时中文会有乱码,修改了编码格式后还是乱码,这里给大家介绍一下关于中文乱码时修改
- 一、泛型的基本概念java与c#一样,都存在泛型的概念,及类型的参数化。java中的泛型是在jdk5.0后出现的,但是java中的泛型与C#
- 本文以在chart控件上和窗体上画矩形为例子讲述了C# GDI在控件上绘图的方法。分享给大家供大家参考。具体方法如下:具体的实现方法就不多解
- 第一步:后端简单建个SpringBoot项目,提供一个 helloWorld接口;版本选用 2.2.6.RELEASEpackage com
- 前言本文主要给大家介绍了如何更改Dialog的标题与按钮颜色的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。an
- 本文实例为大家分享了C#无损高质量压缩图片的具体代码,供大家参考,具体内容如下/// 无损压缩图片 /// <param
- 第一种方法:一、测试如下,直接设置小圆点不是图标二、准备工作1.在drawable创建dot.xml,设置小圆点,比较方便<?xml