Android實(shí)現(xiàn)recyclerview城市字母索引列表

轉(zhuǎn)拼音的依賴(lài)
implementation 'com.github.SilenceDut:jpinyin:v1.0'
FastIndexView實(shí)現(xiàn)列表右側(cè)字母索引列表
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);
//計(jì)算繪制字符的X方向起點(diǎn)
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();
//計(jì)算繪制字符的Y方向起點(diǎn)
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:
//計(jì)算當(dāng)前觸摸的字符索引
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:
//計(jì)算當(dāng)前觸摸的字符索引
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);
//得到當(dāng)前控件的寬度
viewWidth = getMeasuredWidth();
int mHeight = getMeasuredHeight();
//獲取單個(gè)字符能夠擁有的高度
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;
/**
* 根據(jù)手機(jī)的分辨率從 dp 的單位 轉(zhuǎn)成為 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) {
//創(chuàng)建不同的 ViewHolder
View view = null;
//根據(jù)viewtype來(lái)創(chuàng)建條目
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;
//主要用于展示數(shù)據(jù)的list
private List<CityInfoModel> list;
//第一次加載之后緩存的數(shù)據(jù)
private List<CityInfoModel> cacheList;
//頁(yè)面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("德陽(yáng)市"));
list.add(new CityInfoModel("綿陽(yáng)市"));
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) {
//這個(gè)是用來(lái)比較是否是同一組數(shù)據(jù)的
return list.get(position).getSortId();
}
@Override
public String getGroupName(int position) {
CityInfoModel cityInfoModel = list.get(position);
//拼音都是小寫(xiě)的
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);
}
});
}
//滾動(dòng)recyclerview
private void moveToLetterPosition(String letter) {
//這里主要是為了跳轉(zhuǎn)到最頂端
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綁定數(shù)據(jù)
*
* @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;//用于排序的全拼音 這個(gè)是用于后面的排序以及搜索
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>
到此這篇關(guān)于Android實(shí)現(xiàn)recyclerview城市字母索引列表的文章就介紹到這了,更多相關(guān)Android recyclerview字母索引內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Android性能優(yōu)化之RecyclerView分頁(yè)加載組件功能詳解
- Android開(kāi)發(fā)使用RecyclerView添加點(diǎn)擊事件實(shí)例詳解
- Android?RecyclerView實(shí)現(xiàn)九宮格效果
- Android?Recyclerview實(shí)現(xiàn)左滑刪除功能
- Android中RecyclerView實(shí)現(xiàn)商品分類(lèi)功能
- Android中RecyclerView實(shí)現(xiàn)簡(jiǎn)單購(gòu)物車(chē)功能
- Android開(kāi)發(fā)RecyclerView單獨(dú)刷新使用技巧
相關(guān)文章
Android網(wǎng)絡(luò)請(qǐng)求框架Retrofit詳解
這篇文章主要為大家詳細(xì)介紹了Android網(wǎng)絡(luò)請(qǐng)求框架Retrofit,使用Retrofit2.0.0版本進(jìn)行實(shí)例演示,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08
在Android上實(shí)現(xiàn)HttpServer的示例代碼
本篇文章主要介紹了在Android上實(shí)現(xiàn)HttpServer的示例代碼,實(shí)現(xiàn)Android本地的微型服務(wù)器,具有一定的參考價(jià)值,有興趣的可以了解一下2017-08-08
Android FrameWork之Zygote啟動(dòng)示例詳解
這篇文章主要為大家介紹了Android FrameWork之Zygote啟動(dòng)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
android教你打造獨(dú)一無(wú)二的上拉下拉刷新加載框架
本篇文章主要介紹了android教你打造獨(dú)一無(wú)二的下拉刷新加載框架,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-03-03
朋友圈實(shí)現(xiàn)圖片+文字轉(zhuǎn)發(fā)功能(必看篇)
下面小編就為大家?guī)?lái)一篇朋友圈實(shí)現(xiàn)圖片+文字轉(zhuǎn)發(fā)功能(必看篇)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-03-03
Android視頻播放器屏幕左側(cè)邊隨手指上下滑動(dòng)亮度調(diào)節(jié)功能的原理實(shí)現(xiàn)
這篇文章主要介紹了Android視頻播放器屏幕左側(cè)邊隨手指上下滑動(dòng)亮度調(diào)節(jié)功能的原理實(shí)現(xiàn),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-02-02
Kotlin?掛起函數(shù)CPS轉(zhuǎn)換原理解析
這篇文章主要為大家介紹了Kotlin?掛起函數(shù)CPS轉(zhuǎn)換原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
android wifi信號(hào)強(qiáng)度等級(jí)區(qū)分的修改介紹
calculateSignalLevel為計(jì)算信號(hào)等級(jí)函數(shù),MAX_RSSI和MIN_RSSI分別為最強(qiáng)和最弱信號(hào)強(qiáng)度等級(jí)的信號(hào)強(qiáng)度閥值2013-06-06

