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);
}
}
});
}
} 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;
}
}
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 {
/**
* 傳回首字母,大寫
*/
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);
}
}
}
} 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;
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);
}
}