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

标签:Android,RecyclerView
0
投稿

猜你喜欢

  • C#实现字符串进制转换方法汇总

    2022-01-03 09:30:37
  • DataGridView不显示最下面的新行、判断新增行、删除行操作

    2022-11-26 16:14:36
  • java的package和import机制原理解析

    2021-07-20 08:19:05
  • Spring Boot thymeleaf模板引擎的使用详解

    2022-07-27 07:42:54
  • SpringBoot集成Redisson实现分布式锁的方法示例

    2021-10-30 16:59:38
  • SpringCloud客户端报错:- was unable to send heartbeat!的解决

    2021-08-13 14:08:11
  • SpringBoot 上传文件判空以及格式检验流程

    2023-01-19 05:07:36
  • Unity Shader实现线框效果的制作步骤

    2023-10-10 06:14:54
  • 10分钟带你理解Java中的弱引用

    2023-02-09 10:35:55
  • Mybatis条件if test如何使用枚举值

    2023-11-19 14:15:33
  • Java 读写锁源码分析

    2021-08-31 01:48:54
  • Android拼接实现动态对象方法详解

    2021-12-23 10:09:46
  • java代理模式(静态代理、动态代理、cglib代理)

    2022-11-22 16:12:49
  • Android使用ViewFlipper和GestrueDetector共同实现滑屏效果实例

    2023-11-11 10:49:06
  • Android支付宝支付设计开发

    2022-11-19 18:05:25
  • Java二分查找算法与数组处理的应用实例

    2022-07-11 01:26:57
  • android编程实现设置、打开wifi热点共享供他人连接的方法

    2021-12-05 03:39:41
  • 通过实例了解java spring使用构造器注入的原因

    2022-11-25 03:48:24
  • 快速入门介绍Java中强大的String.format()

    2022-10-28 15:53:49
  • Java调取创蓝253短信验证码的实现代码

    2021-11-05 00:48:10
  • asp之家 软件编程 m.aspxhome.com