Android recyclerview字母索引
“嗯哈 人气:11转拼音的依赖
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>
加载全部内容