1.定义一个类,继承View,三个有参构造方法,以及onDraw方法,用接口回调的方法设置点击事件。写一个dispatchTouchEvent方法,判断如果松开就隐藏,按下则显示。
2.在activity_main中定义Textview控件和自定义的类,并设置id,在MainActivity中找到控件,。
代码:
MainActivity:
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ListView;
import android.widget.TextView;
import java.util.Collections;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ListView mListview;
private AddressAdapter adapter;
private List<Address> addressList;
private SlideBar mSlideBar;
private TextView mTextletter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout. activity_main);
mListview = (ListView) findViewById(R.id. mListView);
mSlideBar = (SlideBar) findViewById(R.id. sb_right);
mTextletter = (TextView) findViewById(R.id. txt_letter);
mSlideBar.setText( mTextletter);
addressList = Address. getAddress();
Collections. sort( addressList, new Sort.AddressCompartor());
adapter = new AddressAdapter( this, addressList);
adapter.setIndex();
mListview.setAdapter( adapter);
mSlideBar.setListener( new SlideBar.OnTouchDownListener() {
@Override
public void onTouch(String letter) {
int index = adapter.getIndex(letter);
if (index != - 1) {
// listview设置当前的位置
mListview.setSelection(index);
}
}
});
}
}
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ListView;
import android.widget.TextView;
import java.util.Collections;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ListView mListview;
private AddressAdapter adapter;
private List<Address> addressList;
private SlideBar mSlideBar;
private TextView mTextletter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout. activity_main);
mListview = (ListView) findViewById(R.id. mListView);
mSlideBar = (SlideBar) findViewById(R.id. sb_right);
mTextletter = (TextView) findViewById(R.id. txt_letter);
mSlideBar.setText( mTextletter);
addressList = Address. getAddress();
Collections. sort( addressList, new Sort.AddressCompartor());
adapter = new AddressAdapter( this, addressList);
adapter.setIndex();
mListview.setAdapter( adapter);
mSlideBar.setListener( new SlideBar.OnTouchDownListener() {
@Override
public void onTouch(String letter) {
int index = adapter.getIndex(letter);
if (index != - 1) {
// listview设置当前的位置
mListview.setSelection(index);
}
}
});
}
}
address:
import java.util.ArrayList;
import java.util.List;
public class Address {
private int id;
private String name;
public int getId() {
return id;
}
public void setId( int id) {
this. id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this. name = name;
}
public static List<Address> getAddress() {
List<String> list = getAllMember();
List<Address> addresses = new ArrayList<>();
for ( int i = 0; i < list.size(); i++) {
Address address = new Address();
address.setId(i);
address.setName(list.get(i));
addresses.add(address);
}
return addresses;
}
public static List<String> getAllMember() {
List<String> addresses = new ArrayList<>();
addresses.add( "bdvs");
addresses.add( "马你不");
addresses.add( "王九");
addresses.add( "李广");
addresses.add( "李飞");
addresses.add( "张伟");
addresses.add( "马田");
addresses.add( "商具体");
addresses.add( "韩可以");
addresses.add( "张交易");
addresses.add( "韩吗");
addresses.add( "张近一");
addresses.add( "李进度");
addresses.add( "1512薛美女");
addresses.add( "杨今天");
addresses.add( "行核对");
addresses.add( "郭按时");
addresses.add( "郭方式");
addresses.add( "李百度");
addresses.add( "王过的");
addresses.add( "段更多");
addresses.add( "李和他");
addresses.add( "张舒服");
addresses.add( "刘方式");
addresses.add( "靳广东人");
addresses.add( "徐是");
addresses.add( "李黄飞");
addresses.add( "崔广办");
addresses.add( "宋答复");
addresses.add( "廉干部");
addresses.add( "张水电");
addresses.add( "绳可以");
addresses.add( "陈监狱");
addresses.add( "黄回调");
addresses.add( "李后台");
addresses.add( "王菊花");
addresses.add( "丛好热");
addresses.add( "刘三个");
addresses.add( "庞黄飞");
addresses.add( "杨嗨翻天");
addresses.add( "尹听过");
return addresses;
}
}
import java.util.ArrayList;
import java.util.List;
public class Address {
private int id;
private String name;
public int getId() {
return id;
}
public void setId( int id) {
this. id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this. name = name;
}
public static List<Address> getAddress() {
List<String> list = getAllMember();
List<Address> addresses = new ArrayList<>();
for ( int i = 0; i < list.size(); i++) {
Address address = new Address();
address.setId(i);
address.setName(list.get(i));
addresses.add(address);
}
return addresses;
}
public static List<String> getAllMember() {
List<String> addresses = new ArrayList<>();
addresses.add( "bdvs");
addresses.add( "马你不");
addresses.add( "王九");
addresses.add( "李广");
addresses.add( "李飞");
addresses.add( "张伟");
addresses.add( "马田");
addresses.add( "商具体");
addresses.add( "韩可以");
addresses.add( "张交易");
addresses.add( "韩吗");
addresses.add( "张近一");
addresses.add( "李进度");
addresses.add( "1512薛美女");
addresses.add( "杨今天");
addresses.add( "行核对");
addresses.add( "郭按时");
addresses.add( "郭方式");
addresses.add( "李百度");
addresses.add( "王过的");
addresses.add( "段更多");
addresses.add( "李和他");
addresses.add( "张舒服");
addresses.add( "刘方式");
addresses.add( "靳广东人");
addresses.add( "徐是");
addresses.add( "李黄飞");
addresses.add( "崔广办");
addresses.add( "宋答复");
addresses.add( "廉干部");
addresses.add( "张水电");
addresses.add( "绳可以");
addresses.add( "陈监狱");
addresses.add( "黄回调");
addresses.add( "李后台");
addresses.add( "王菊花");
addresses.add( "丛好热");
addresses.add( "刘三个");
addresses.add( "庞黄飞");
addresses.add( "杨嗨翻天");
addresses.add( "尹听过");
return addresses;
}
}
PinyinUtils:
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
public class PinyinUtils {
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
public class PinyinUtils {
/** * 返回首字母,大写 */ public static String getFirstLetter(String str) { if (TextUtils.isEmpty(str)) { return ""; } // 得到一个字符串的拼音的大写 String pinyinStr = getPinyin(str).toUpperCase(); // 取拼音字符串的第一个字母 char firstCahr = pinyinStr.charAt(0); // 不是A-Z字母 if (firstCahr > 90 || firstCahr < 65) { return "#"; }else{ // 代表是A-Z return String.valueOf(firstCahr); } } /** * 得到一个字符串的拼音读音 */ public static String getPinyin(String chineseStr) { StringBuffer sb = new StringBuffer(); // 将汉字拆分成一个个的char char[] chars = chineseStr.toCharArray(); // 遍历汉字的每一个char for (int i = 0; i < chars.length; i++) { try { // 汉字的所有读音放在一个pinyins数组 String[] strings = PinyinHelper.toHanyuPinyinStringArray(chars[i], getDefaultFormat()); if (strings == null) { sb.append(chars[i]); } else { sb.append(strings[0]); } } catch (BadHanyuPinyinOutputFormatCombination badHanyuPinyinOutputFormatCombination) { badHanyuPinyinOutputFormatCombination.printStackTrace(); } } return sb.toString(); } /** * 设置默认的输出格式 */ public static HanyuPinyinOutputFormat getDefaultFormat() { HanyuPinyinOutputFormat outputFormat = new HanyuPinyinOutputFormat(); //去除声调 outputFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); //小写 outputFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); // 包含Unicode特殊字符 outputFormat.setVCharType(HanyuPinyinVCharType.WITH_U_UNICODE); return outputFormat; } }
Sort:
import java.util.Comparator;
public class Sort {
public static class AddressCompartor implements Comparator< Address>{
@Override public int compare( Address o1, Address o2) {
String o1f = PinyinUtils. getFirstLetter(o1.getName());
String o2f = PinyinUtils. getFirstLetter(o2.getName());
if (o1f.equals( "#")) {
return 1;
} else if (o2f.equals( "#")) {
return - 1;
} else {
return o1f.compareTo(o2f);
}
}
}
}
public class Sort {
public static class AddressCompartor implements Comparator< Address>{
@Override public int compare( Address o1, Address o2) {
String o1f = PinyinUtils. getFirstLetter(o1.getName());
String o2f = PinyinUtils. getFirstLetter(o2.getName());
if (o1f.equals( "#")) {
return 1;
} else if (o2f.equals( "#")) {
return - 1;
} else {
return o1f.compareTo(o2f);
}
}
}
}
AddressAdapter:
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.List;
public class AddressAdapter extends BaseAdapter {
private Context context;
private List<Address> list;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.List;
public class AddressAdapter extends BaseAdapter {
private Context context;
private List<Address> list;
private Map<String, Integer> indexMap = new HashMap<>(); public AddressAdapter(Context context, List<Address> list) { this.context = context; this.list = list; }public void setIndex() { indexMap.clear(); for (int i = 0; i < list.size(); i++) { // 遍历数据,得到首字母 String index = PinyinUtils.getFirstLetter(list.get(i).getName()); // 如果索引map中不包含这个字母,就添加进索引map,key是字母,value是第一次出现的位置 if (!indexMap.containsKey(index)) { indexMap.put(index, i); } } } @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=View.inflate(context, R.layout.activity_address,null);holder.title= (TextView) convertView.findViewById(R.id.text_title); holder.mTextName = (TextView) convertView.findViewById(R.id.mTextName); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); }// 拿到当前条目 String str = addressList.get(position).getName(); // 取当前条目的首字母 String first = PinyinUtils.getFirstLetter(str); if (indexMap.get(first) == position) { holder.title.setVisibility(View.VISIBLE); holder.title.setText(first); } else { holder.title.setVisibility(View.GONE); } holder.mTextName.setText(list.get(position).getName()); return convertView; } class ViewHolder {TextView title; TextView mTextName; } }
SlideBar: import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.TextView; import java.util.Date; public class SlideBar extends View { private static final String TAG = "SlideBar"; private String[] letters = { "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 OnTouchDownListener listener; private TextView textView; private int choose = -1; private int oldChoose = -1; public void setListener(OnTouchDownListener listener) { this.listener = listener; } public SlideBar(Context context) { super(context); } public SlideBar(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public SlideBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public void setText(TextView textView) { this.textView = textView; } @Override public boolean dispatchTouchEvent(MotionEvent event) { int action = event.getAction(); // 手指触摸的纵坐标 float y = event.getY(); // 计算公式,字母的位置 = y*字母的总个数/总高度 int pos = (int) (y * letters.length / getHeight()); oldChoose = choose; switch (action) { case MotionEvent.ACTION_UP: // 手指抬起 // 把显示字母的textview隐藏 if (textView != null) { textView.setVisibility(View.INVISIBLE); } // 按下的位置设置成-1,未选中 choose = -1; // 刷新,重绘 invalidate(); break; default: // 手指按下和移动 // 在边界内,也就是在letters范围之内 if (pos >= 0 && pos < letters.length) { // 按下的时候显示 显示字母的textview,并且把字母设置成我们按下的位置的字母 if (textView != null) { textView.setVisibility(VISIBLE); textView.setText(letters[pos]); } // 手指按下和移动的时候把当前选中的字母传出去 if (listener != null) { listener.onTouch(letters[pos]); } // 改变当前选中的字母 // 优化,只有当当前选中位置和上次选中的位置不同的时候才重绘 if (oldChoose != pos){ choose = pos; invalidate(); } } break; } return true; } @Override protected void onDraw(Canvas canvas) { Log.i(TAG, "onDraw: " + new Date(System.currentTimeMillis())); super.onDraw(canvas); int width = getWidth(); int height = getHeight(); int singleHeight = height / letters.length; Paint bgPaint = new Paint(); bgPaint.setColor(Color.parseColor("#44000000")); bgPaint.setAntiAlias(true); canvas.drawPaint(bgPaint); bgPaint.reset(); for (int i = 0; i < letters.length; i++) { Paint paint = new Paint(); paint.setColor(Color.parseColor("#FFFFFF")); paint.setTextSize(30); // 字符占的宽度 float f = paint.measureText(letters[i]); float xPos = width / 2 - f / 2; float yPos = singleHeight * (i + 1); if (i == choose) { paint.setColor(Color.parseColor("#FF0000")); paint.setFakeBoldText(true); } canvas.drawText(letters[i], xPos, yPos, paint); paint.reset(); } } interface OnTouchDownListener { void onTouch(String letter); } }