//我写了两种方式,效果都差不多,不过第一个是通过网络接口串实现的,它里面有这个值,能知道当前的数据的拼音的第一个字母。第二个是我自己写的自定义数据,通过转成拼音,再通过截取拼音第一个字母,获取。
//第一个 没上传动图 凑合看一下,这个都是网络请求的数据:
//好了 第一步 先建立一个BaseView类继承View,自己来写自定义View
public class BaseView extends View {
/*绘制的列表导航字母*/
private String words[] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
"O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "#"};
/*字母画笔*/
private Paint wordsPaint=new Paint();
/*字母背景画笔*/
private Paint bgPaint;
/*每一个字母的宽度*/
private int itemWidth;
/*每一个字母的高度*/
private int itemHeight;
/*手指按下的字母索引*/
private int touchIndex = 0;
/*手指按下的字母改变接口*/
private onWordsChangeListener listener;
/*设置手指按下字母改变监听*/
public void setOnWordsChangeListener(onWordsChangeListener listener) {
this.listener = listener;
}
public BaseView(Context context) {
super(context);
}
public BaseView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public BaseView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
itemWidth = getMeasuredWidth();
//使得边距好看一些
int height = getMeasuredHeight() - 10;
itemHeight = height / 27;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
wordsPaint.setTextSize(40);
for (int i = 0; i < words.length; i++) {
//判断是不是我们按下的当前字母
if (touchIndex == i) {
//绘制文字圆形背景
// canvas.drawCircle(itemWidth / 2, itemHeight / 2 + i * itemHeight, 23, bgPaint);
wordsPaint.setColor(Color.RED);
} else {
wordsPaint.setColor(Color.BLACK);
}
//获取文字的宽高
Rect rect = new Rect();
wordsPaint.getTextBounds(words[i], 0, 1, rect);
int wordWidth = rect.width();
//绘制字母
float wordX = itemWidth / 2 - wordWidth / 2;
float wordY = itemWidth / 2 + i * itemHeight;
canvas.drawText(words[i], wordX, wordY, wordsPaint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
float y = event.getY();
//关键点===获得我们按下的是那个索引(字母)
int index = (int) (y / itemHeight);
if (index != touchIndex)
touchIndex = index;
//防止数组越界
if (listener != null && 0 <= touchIndex && touchIndex <= words.length - 1) {
//回调按下的字母
listener.wordsChange(words[touchIndex]);
}
//刷新
invalidate();
break;
case MotionEvent.ACTION_UP:
//手指抬起,不做任何操作
break;
}
return true;
}
/*手指按下了哪个字母的回调接口*/
public interface onWordsChangeListener {
void wordsChange(String words);
}
/*设置当前按下的是那个字母*/
public void setTouchIndex(String word) {
for (int i = 0; i < words.length; i++) {
if (words[i].equals(word)) {
touchIndex = i;
invalidate();
return;
}
}
}
}
//第二步 写布局
<RelativeLayout 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"
tools:context="com.example.hasee.a817ceshi.MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_toLeftOf="@+id/mView"
android:id="@+id/mDingWeiRe"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
<com.example.hasee.a817ceshi.BaseView
android:layout_alignParentRight="true"
android:id="@+id/mView"
android:layout_width="40dp"
android:layout_height="match_parent"
/>
<TextView
android:visibility="gone"
android:id="@+id/mDingWeiXianShi"
android:textSize="60sp"
android:background="@color/colorAccent"
android:gravity="center"
android:layout_centerInParent="true"
android:layout_width="100dp"
android:layout_height="100dp" />
</RelativeLayout>
</RelativeLayout>
// 第三步 Activity里开始具体使用,请求数据,适配,关联
//okhttp和gson解析的依赖
//implementation 'com.google.code.gson:gson:2.8.1'
//implementation 'com.squareup.okhttp3:okhttp:3.8.1'
public class MainActivity extends AppCompatActivity implements BaseView.onWordsChangeListener {
private ArrayList<DingWeiBean.ResultListBean.ListBean> arrayList;
private ListView mDingWeiRe;
private BaseView mView;
private TextView mDingWeiXianShi;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initDatas();
}
private void initView() {
mDingWeiRe = (ListView) findViewById(R.id.mDingWeiRe);
mView = (BaseView) findViewById(R.id.mView);
mDingWeiXianShi = (TextView) findViewById(R.id.mDingWeiXianShi);
//通过这个监听listView和自定义View互相关联上
mView.setOnWordsChangeListener(this);
}
//网络请求数据
private void initDatas() {
//get 异步
//private String url = "http://v.juhe.cn/toutiao/index?type=top&key=097060266650f67b2cebd2a06aded587";
OkHttpClient client = new OkHttpClient.Builder().build();
Request request = new Request.Builder().url("https://api.dyhoa.com/dapi/v4/city/android").method("GET", null).build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//请求失败
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//请求成功
arrayList = new ArrayList<>();
String string = response.body().string();
Gson gson = new Gson();
DingWeiBean dingWeiBean = gson.fromJson(string, DingWeiBean.class);
List<DingWeiBean.ResultListBean.ListBean> list = dingWeiBean.getResultList().getList();
for (int i = 0; i < list.size(); i++) {
DingWeiBean.ResultListBean.ListBean listBean = list.get(i);
arrayList.add(listBean);
Log.e("TAG1", arrayList.size() + "");
}
Log.e("TAG2", arrayList.size() + "");
//listView适配数据
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.e("TAG3", arrayList.size() + "");
mDingWeiRe.setAdapter(new MyAdapter(arrayList, MainActivity.this));
mDingWeiRe.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
//当滑动列表的时候,更新右侧字母列表的选中状态
mView.setTouchIndex(arrayList.get(firstVisibleItem).getFirst_letter());
}
});
}
});
}
});
}
@Override
public void wordsChange(String words) {
updateWord(words);
updateListView(words);
}
Handler handler = new Handler();
private void updateWord(String words) {
mDingWeiXianShi.setText(words);
mDingWeiXianShi.setVisibility(View.VISIBLE);
//清空之前的所有消息
handler.removeCallbacksAndMessages(null);
//500ms后让tv隐藏
handler.postDelayed(new Runnable() {
@Override
public void run() {
mDingWeiXianShi.setVisibility(View.GONE);
}
}, 500);
}
private void updateListView(String words) {
for (int i = 0; i < arrayList.size(); i++) {
String headerWord = arrayList.get(i).getFirst_letter();
//将手指按下的字母与列表中相同字母开头的项找出来
if (words.equals(headerWord)) {
//将列表选中哪一个
mDingWeiRe.setSelection(i);
//找到开头的一个即可
return;
}
}
}
}
//第四步 ListView适配器 适配数据:
public class MyAdapter extends BaseAdapter {
private ArrayList<DingWeiBean.ResultListBean.ListBean> list;
private Context context;
public MyAdapter(ArrayList<DingWeiBean.ResultListBean.ListBean> list, Context context) {
this.list = list;
this.context = context;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.dingweilayout, null);
holder.mDingWeiText1 = (TextView) convertView.findViewById(R.id.mDingWeiText1);
holder.mDingWeiText2 = (TextView) convertView.findViewById(R.id.mDingWeiText2);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
String first_letter = list.get(position).getFirst_letter();
holder.mDingWeiText1.setText(first_letter);
holder.mDingWeiText2.setText(list.get(position).getCity_name());
//将相同字母开头的合并在一起
if (position == 0) {
//第一个是一定显示的
holder.mDingWeiText1.setVisibility(View.VISIBLE);
} else {
//后一个与前一个对比,判断首字母是否相同,相同则隐藏
String first_letter1 = list.get(position - 1).getFirst_letter();
if (first_letter.equals(first_letter1)) {
holder.mDingWeiText1.setVisibility(View.GONE);
} else {
holder.mDingWeiText1.setVisibility(View.VISIBLE);
}
}
return convertView;
}
private class ViewHolder {
private TextView mDingWeiText1;
private TextView mDingWeiText2;
}
}
// 第五步 还有这个Bean类
public class DingWeiBean {
/**
* result :
* total : 2
* code : 200
* message : ok
* resultList : {"hot":[{"city_name":"北京市","province_id":110000,"first_letter":"B","is_hot":1,"latitude":"39.90469","base_results":0,"id":1,"displayorder":0,"city_id":110000,"status":1,"longitude":"116.40717"},{"city_name":"石家庄市","province_id":130000,"first_letter":"S","is_hot":1,"latitude":"38.04223","base_results":3000,"id":5,"displayorder":0,"city_id":130100,"status":1,"longitude":"114.51479"},{"city_name":"廊坊市","province_id":130000,"first_letter":"L","is_hot":1,"latitude":"39.52393","base_results":2900,"id":14,"displayorder":100,"city_id":131000,"status":1,"longitude":"116.70444"},{"city_name":"呼和浩特市","province_id":150000,"first_letter":"H","is_hot":1,"latitude":"40.842723","base_results":0,"id":27,"displayorder":0,"city_id":150100,"status":1,"longitude":"111.748426"},{"city_name":"南京市","province_id":320000,"first_letter":"N","is_hot":1,"latitude":"32.05935","base_results":0,"id":77,"displayorder":0,"city_id":320100,"status":1,"longitude":"118.79662"},{"city_name":"武汉市","province_id":420000,"first_letter":"W","is_hot":1,"latitude":"31.01269","base_results":2500,"id":172,"displayorder":0,"city_id":420100,"status":1,"longitude":"114.33996"},{"city_name":"昆明市","province_id":530000,"first_letter":"K","is_hot":1,"latitude":"24.87966","base_results":0,"id":271,"displayorder":0,"city_id":530100,"status":1,"longitude":"102.83322"},{"city_name":"西安市","province_id":610000,"first_letter":"X","is_hot":1,"latitude":"34.34749","base_results":0,"id":294,"displayorder":0,"city_id":610100,"status":1,"longitude":"108.94627"}],"list":[{"city_name":"北京市","province_id":110000,"first_letter":"B","is_hot":1,"latitude":"39.90469","base_results":0,"id":1,"displayorder":0,"city_id":110000,"status":1,"longitude":"116.40717"},{"city_name":"宝鸡市","province_id":610000,"first_letter":"B","is_hot":0,"latitude":"0.000000","base_results":0,"id":296,"displayorder":0,"city_id":610300,"status":1,"longitude":"0.000000"},{"city_name":"保定市","province_id":130000,"first_letter":"B","is_hot":0,"latitude":"38.86766","base_results":0,"id":10,"displayorder":0,"city_id":130600,"status":1,"longitude":"115.48233"},{"city_name":"沧州市","province_id":130000,"first_letter":"C","is_hot":0,"latitude":"38.31058","base_results":0,"id":13,"displayorder":0,"city_id":130900,"status":1,"longitude":"116.85746"},{"city_name":"邯郸市","province_id":130000,"first_letter":"H","is_hot":0,"latitude":"36.61227","base_results":0,"id":8,"displayorder":0,"city_id":130400,"status":1,"longitude":"114.49068"},{"city_name":"呼和浩特市","province_id":150000,"first_letter":"H","is_hot":1,"latitude":"40.842723","base_results":0,"id":27,"displayorder":0,"city_id":150100,"status":1,"longitude":"111.748426"},{"city_name":"衡水市","province_id":130000,"first_letter":"H","is_hot":0,"latitude":"37.7351","base_results":0,"id":15,"displayorder":0,"city_id":131100,"status":1,"longitude":"115.66599"},{"city_name":"济南市","province_id":370000,"first_letter":"J","is_hot":0,"latitude":"36.6512","base_results":0,"id":138,"displayorder":0,"city_id":370100,"status":1,"longitude":"117.1201"},{"city_name":"晋中市","province_id":140000,"first_letter":"J","is_hot":0,"latitude":"37.696495","base_results":0,"id":22,"displayorder":0,"city_id":140700,"status":1,"longitude":"112.736465"},{"city_name":"昆明市","province_id":530000,"first_letter":"K","is_hot":1,"latitude":"24.87966","base_results":0,"id":271,"displayorder":0,"city_id":530100,"status":1,"longitude":"102.83322"},{"city_name":"廊坊市","province_id":130000,"first_letter":"L","is_hot":1,"latitude":"39.52393","base_results":2900,"id":14,"displayorder":100,"city_id":131000,"status":1,"longitude":"116.70444"},{"city_name":"南京市","province_id":320000,"first_letter":"N","is_hot":1,"latitude":"32.05935","base_results":0,"id":77,"displayorder":0,"city_id":320100,"status":1,"longitude":"118.79662"},{"city_name":"秦皇岛市","province_id":130000,"first_letter":"Q","is_hot":0,"latitude":"39.942531","base_results":0,"id":7,"displayorder":0,"city_id":130300,"status":1,"longitude":"119.586579"},{"city_name":"石家庄市","province_id":130000,"first_letter":"S","is_hot":1,"latitude":"38.04223","base_results":3000,"id":5,"displayorder":0,"city_id":130100,"status":1,"longitude":"114.51479"},{"city_name":"上饶市","province_id":360000,"first_letter":"S","is_hot":0,"latitude":"28.44442","base_results":0,"id":137,"displayorder":0,"city_id":361100,"status":1,"longitude":"117.971185"},{"city_name":"太原市","province_id":140000,"first_letter":"T","is_hot":0,"latitude":"37.87046","base_results":0,"id":16,"displayorder":0,"city_id":140100,"status":1,"longitude":"112.549717"},{"city_name":"唐山市","province_id":130000,"first_letter":"T","is_hot":0,"latitude":"39.635113","base_results":0,"id":6,"displayorder":0,"city_id":130200,"status":1,"longitude":"118.175393"},{"city_name":"武汉市","province_id":420000,"first_letter":"W","is_hot":1,"latitude":"31.01269","base_results":2500,"id":172,"displayorder":0,"city_id":420100,"status":1,"longitude":"114.33996"},{"city_name":"武威市","province_id":620000,"first_letter":"w","is_hot":0,"latitude":"37.929996","base_results":0,"id":309,"displayorder":0,"city_id":620600,"status":1,"longitude":"102.634697"},{"city_name":"邢台市","province_id":130000,"first_letter":"X","is_hot":0,"latitude":"37.0682","base_results":0,"id":9,"displayorder":0,"city_id":130500,"status":1,"longitude":"114.50885"},{"city_name":"西安市","province_id":610000,"first_letter":"X","is_hot":1,"latitude":"34.34749","base_results":0,"id":294,"displayorder":0,"city_id":610100,"status":1,"longitude":"108.94627"}]}
*/
private String result;
private int total;
private int code;
private String message;
private ResultListBean resultList;
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public ResultListBean getResultList() {
return resultList;
}
public void setResultList(ResultListBean resultList) {
this.resultList = resultList;
}
public static class ResultListBean {
private List<HotBean> hot;
private List<ListBean> list;
public List<HotBean> getHot() {
return hot;
}
public void setHot(List<HotBean> hot) {
this.hot = hot;
}
public List<ListBean> getList() {
return list;
}
public void setList(List<ListBean> list) {
this.list = list;
}
public static class HotBean {
/**
* city_name : 北京市
* province_id : 110000
* first_letter : B
* is_hot : 1
* latitude : 39.90469
* base_results : 0.0
* id : 1
* displayorder : 0
* city_id : 110000
* status : 1
* longitude : 116.40717
*/
private String city_name;
private int province_id;
private String first_letter;
private int is_hot;
private String latitude;
private double base_results;
private int id;
private int displayorder;
private int city_id;
private int status;
private String longitude;
public String getCity_name() {
return city_name;
}
public void setCity_name(String city_name) {
this.city_name = city_name;
}
public int getProvince_id() {
return province_id;
}
public void setProvince_id(int province_id) {
this.province_id = province_id;
}
public String getFirst_letter() {
return first_letter;
}
public void setFirst_letter(String first_letter) {
this.first_letter = first_letter;
}
public int getIs_hot() {
return is_hot;
}
public void setIs_hot(int is_hot) {
this.is_hot = is_hot;
}
public String getLatitude() {
return latitude;
}
public void setLatitude(String latitude) {
this.latitude = latitude;
}
public double getBase_results() {
return base_results;
}
public void setBase_results(double base_results) {
this.base_results = base_results;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getDisplayorder() {
return displayorder;
}
public void setDisplayorder(int displayorder) {
this.displayorder = displayorder;
}
public int getCity_id() {
return city_id;
}
public void setCity_id(int city_id) {
this.city_id = city_id;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getLongitude() {
return longitude;
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}
}
public static class ListBean {
/**
* city_name : 北京市
* province_id : 110000
* first_letter : B
* is_hot : 1
* latitude : 39.90469
* base_results : 0.0
* id : 1
* displayorder : 0
* city_id : 110000
* status : 1
* longitude : 116.40717
*/
private String city_name;
private int province_id;
private String first_letter;
private int is_hot;
private String latitude;
private double base_results;
private int id;
private int displayorder;
private int city_id;
private int status;
private String longitude;
public String getCity_name() {
return city_name;
}
public void setCity_name(String city_name) {
this.city_name = city_name;
}
public int getProvince_id() {
return province_id;
}
public void setProvince_id(int province_id) {
this.province_id = province_id;
}
public String getFirst_letter() {
return first_letter;
}
public void setFirst_letter(String first_letter) {
this.first_letter = first_letter;
}
public int getIs_hot() {
return is_hot;
}
public void setIs_hot(int is_hot) {
this.is_hot = is_hot;
}
public String getLatitude() {
return latitude;
}
public void setLatitude(String latitude) {
this.latitude = latitude;
}
public double getBase_results() {
return base_results;
}
public void setBase_results(double base_results) {
this.base_results = base_results;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getDisplayorder() {
return displayorder;
}
public void setDisplayorder(int displayorder) {
this.displayorder = displayorder;
}
public int getCity_id() {
return city_id;
}
public void setCity_id(int city_id) {
this.city_id = city_id;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getLongitude() {
return longitude;
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}
}
}
}
//-----------------------------------第一种 完 -----------------------------------------
//------------------第二种 自定义的数据,不是网络请求的----------------
//第一步 还是一样 写个BaseView类继承View
public class BaseView extends View {
/*绘制的列表导航字母*/
private String words[] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
"O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "#"};
/*字母画笔*/
private Paint wordsPaint=new Paint();
/*字母背景画笔*/
private Paint bgPaint;
/*每一个字母的宽度*/
private int itemWidth;
/*每一个字母的高度*/
private int itemHeight;
/*手指按下的字母索引*/
private int touchIndex = 0;
/*手指按下的字母改变接口*/
private onWordsChangeListener listener;
/*设置手指按下字母改变监听*/
public void setOnWordsChangeListener(onWordsChangeListener listener) {
this.listener = listener;
}
public BaseView(Context context) {
super(context);
}
public BaseView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public BaseView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
itemWidth = getMeasuredWidth();
//使得边距好看一些
int height = getMeasuredHeight() - 10;
itemHeight = height / 27;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
wordsPaint.setTextSize(40);
for (int i = 0; i < words.length; i++) {
//判断是不是我们按下的当前字母
if (touchIndex == i) {
//绘制文字圆形背景
// canvas.drawCircle(itemWidth / 2, itemHeight / 2 + i * itemHeight, 23, bgPaint);
wordsPaint.setColor(Color.RED);
} else {
wordsPaint.setColor(Color.BLACK);
}
//获取文字的宽高
Rect rect = new Rect();
wordsPaint.getTextBounds(words[i], 0, 1, rect);
int wordWidth = rect.width();
//绘制字母
float wordX = itemWidth / 2 - wordWidth / 2;
float wordY = itemWidth / 2 + i * itemHeight;
canvas.drawText(words[i], wordX, wordY, wordsPaint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
float y = event.getY();
//关键点===获得我们按下的是那个索引(字母)
int index = (int) (y / itemHeight);
if (index != touchIndex)
touchIndex = index;
//防止数组越界
if (listener != null && 0 <= touchIndex && touchIndex <= words.length - 1) {
//回调按下的字母
listener.wordsChange(words[touchIndex]);
}
//刷新
invalidate();
break;
case MotionEvent.ACTION_UP:
//手指抬起,不做任何操作
break;
}
return true;
}
/*手指按下了哪个字母的回调接口*/
public interface onWordsChangeListener {
void wordsChange(String words);
}
/*设置当前按下的是那个字母*/
public void setTouchIndex(String word) {
for (int i = 0; i < words.length; i++) {
if (words[i].equals(word)) {
touchIndex = i;
invalidate();
return;
}
}
}
}
//第二步 布局
<android.support.constraint.ConstraintLayout 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"
tools:context="com.example.hasee.a817ceshi.Main2Activity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_toLeftOf="@+id/mView"
android:id="@+id/mRe"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
<com.example.hasee.a817ceshi.BaseView
android:layout_alignParentRight="true"
android:id="@+id/mView"
android:layout_width="40dp"
android:layout_height="match_parent"
/>
<TextView
android:visibility="gone"
android:id="@+id/mText"
android:textSize="60sp"
android:background="@color/colorAccent"
android:gravity="center"
android:layout_centerInParent="true"
android:layout_width="100dp"
android:layout_height="100dp" />
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
//第三步 写了一个拼音工具类,这个需要导入jar包,我导入的是pinyin4j-2.5.0.jar这个,大家可以网上下载一下。导入并add添加,就可以了。
下载地址:
public class PinyinUtil {
/**
* 将hanzi转成拼音
*
* @param hanzi 汉字或字母
* @return 拼音
*/
public static String getPinyin(String hanzi) {
StringBuilder sb = new StringBuilder();
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
//由于不能直接对多个汉子转换,只能对单个汉子转换
char[] arr = hanzi.toCharArray();
for (int i = 0; i < arr.length; i++) {
if (Character.isWhitespace(arr[i])) {
continue;
}
try {
String[] pinyinArr = PinyinHelper.toHanyuPinyinStringArray(arr[i], format);
if (pinyinArr != null) {
sb.append(pinyinArr[0]);
} else {
sb.append(arr[i]);
}
} catch (Exception e) {
e.printStackTrace();
//不是正确的汉字
sb.append(arr[i]);
}
}
//取字符串的前1个字符,只要第一个字母
String substring = sb.substring(0, 1);
return substring;
}
}
//第四步 Activity里的使用:
public class Main2Activity extends AppCompatActivity implements BaseView.onWordsChangeListener {
private ListView mRe;
private BaseView mView;
private TextView mText;
private List<Bean> mList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
initView();
}
private void initView() {
mRe = (ListView) findViewById(R.id.mRe);
mView = (BaseView) findViewById(R.id.mView);
mText = (TextView) findViewById(R.id.mText);
mView.setOnWordsChangeListener(this);
mList = new ArrayList<>();
//我写的这个数据也是没谁了,写代码写的有点短路
//这个第一个参数传递的是Bean类里的String类型的数据,通过这个拼音工具类转换与截取,把数据转换成第一个字母。
mList.add(new Bean(PinyinUtil.getPinyin("阿超"),"阿超"));
mList.add(new Bean(PinyinUtil.getPinyin("阿宽"),"阿宽"));
mList.add(new Bean(PinyinUtil.getPinyin("阿牛"),"阿牛"));
mList.add(new Bean(PinyinUtil.getPinyin("阿剑"),"阿剑"));
mList.add(new Bean(PinyinUtil.getPinyin("白小白"),"白小白"));
mList.add(new Bean(PinyinUtil.getPinyin("白百合"),"白百合"));
mList.add(new Bean(PinyinUtil.getPinyin("曹操"),"曹操"));
mList.add(new Bean(PinyinUtil.getPinyin("曹丕"),"曹丕"));
mList.add(new Bean(PinyinUtil.getPinyin("大龙"),"大龙"));
mList.add(new Bean(PinyinUtil.getPinyin("大飞"),"大飞"));
mList.add(new Bean(PinyinUtil.getPinyin("易中天"),"易中天"));
mList.add(new Bean(PinyinUtil.getPinyin("易大师"),"易大师"));
mList.add(new Bean(PinyinUtil.getPinyin("医生"),"医生"));
mList.add(new Bean(PinyinUtil.getPinyin("蚁人"),"蚁人"));
mList.add(new Bean(PinyinUtil.getPinyin("发哥"),"发哥"));
mList.add(new Bean(PinyinUtil.getPinyin("肥龙"),"肥龙"));
mList.add(new Bean(PinyinUtil.getPinyin("哥白尼"),"哥白尼"));
mList.add(new Bean(PinyinUtil.getPinyin("革命军"),"革命军"));
mList.add(new Bean(PinyinUtil.getPinyin("哈哈"),"哈哈"));
mList.add(new Bean(PinyinUtil.getPinyin("海哥"),"海哥"));
mList.add(new Bean(PinyinUtil.getPinyin("嘉禾"),"嘉禾"));
mList.add(new Bean(PinyinUtil.getPinyin("姬发"),"姬发"));
mList.add(new Bean(PinyinUtil.getPinyin("开牛"),"开牛"));
mList.add(new Bean(PinyinUtil.getPinyin("铠甲勇士"),"铠甲勇士"));
//ListView适配,把这个集合传到适配器,开始适配,适配器里还得判断。
mRe.setAdapter(new MyAdapters(mList, Main2Activity.this));
mRe.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
//当滑动列表的时候,更新右侧字母列表的选中状态
mView.setTouchIndex(mList.get(firstVisibleItem).getPing());
}
});
}
@Override
public void wordsChange(String words) {
updateWord(words);
updateListView(words);
}
Handler handler = new Handler();
private void updateWord(String words) {
mText.setText(words);
mText.setVisibility(View.VISIBLE);
//清空之前的所有消息
handler.removeCallbacksAndMessages(null);
//500ms后让tv隐藏
handler.postDelayed(new Runnable() {
@Override
public void run() {
mText.setVisibility(View.GONE);
}
}, 500);
}
private void updateListView(String words) {
for (int i = 0; i < mList.size(); i++) {
String headerWord = mList.get(i).getPing();
//将手指按下的字母与列表中相同字母开头的项找出来
if (words.equals(headerWord)) {
//将列表选中哪一个
mRe.setSelection(i);
//找到开头的一个即可
return;
}
}
}
}
//第五步 ListView适配器 适配数据:
public class MyAdapters extends BaseAdapter {
private List<Bean> list;
private Context context;
public MyAdapters(List<Bean> list, Context context) {
this.list = list;
this.context = context;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int i) {
return list.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View convertView, ViewGroup viewGroup) {
MyAdapters.ViewHolder holder;
if (convertView == null) {
holder = new MyAdapters.ViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.item, null);
holder.mDingT1 = (TextView) convertView.findViewById(R.id.mDingT1);
holder.mDingT2 = (TextView) convertView.findViewById(R.id.mDingT2);
convertView.setTag(holder);
} else {
holder = (MyAdapters.ViewHolder) convertView.getTag();
}
String first_letter = list.get(i).getPing();
holder.mDingT1.setText(first_letter);
holder.mDingT2.setText(list.get(i).getName());
//将相同字母开头的合并在一起
if (i == 0) {
//第一个是一定显示的
holder.mDingT1.setVisibility(View.VISIBLE);
} else {
//后一个与前一个对比,判断首字母是否相同,相同则隐藏
String first_letter1 = list.get(i - 1).getPing();
if (first_letter.equals(first_letter1)) {
holder.mDingT1.setVisibility(View.GONE);
} else {
holder.mDingT1.setVisibility(View.VISIBLE);
}
}
return convertView;
}
private class ViewHolder {
private TextView mDingT1;
private TextView mDingT2;
}
}
//第六步 Bean类:
public class Bean {
private String Ping;
private String name;
public Bean() {
}
public Bean(String ping, String name) {
Ping = ping;
this.name = name;
}
public String getPing() {
return Ping;
}
public void setPing(String ping) {
Ping = ping;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//---------------------------------------------------------------------------完----------------------------------------------------------------------------