自定义View - 字母索引列表
2018-07-07 本文已影响2人
Peakmain

自定义view
public class LetterSideBar extends View {
private Paint mPaint;
// 定义26个字母
public static String[] mLetters = {"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 String mCurrentTouchLetter = "A";
public LetterSideBar(Context context) {
this(context, null);
}
public LetterSideBar(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public LetterSideBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
mPaint.setAntiAlias(true);
// 自定义属性,颜色 字体大小
// 设置的是像素
mPaint.setTextSize(sp2px(12));
// 默认颜色
mPaint.setColor(Color.BLUE);
}
/**
* sp 转 px
*/
private float sp2px(int sp) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
sp, getResources().getDisplayMetrics());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//计算其宽度,和画笔有关
//measure获取宽度
int textWidth = (int) mPaint.measureText("A");
int width = getPaddingLeft() + getPaddingRight() + textWidth;
//高度,直接获取即可
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
}
@Override
protected void onDraw(Canvas canvas) {
//每个文字的高度
int itemHeight = (getHeight() - getPaddingTop() - getPaddingBottom()) / mLetters.length;
for (int i = 0; i < mLetters.length; i++) {
int textWidth = (int) mPaint.measureText(mLetters[i]);
//每个字母的中心线
int letterCenter = i * itemHeight + itemHeight / 2 + getPaddingTop();
@SuppressLint("DrawAllocation") Paint.FontMetricsInt fontMetricsInt = new Paint.FontMetricsInt();
int dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom;
float baseLine = letterCenter + dy;
// x 绘制在最中间 = 宽度/2 - 文字/2
float x = getWidth() / 2 - textWidth / 2;
//高亮
if (mLetters[i].equals(mCurrentTouchLetter)) {
mPaint.setColor(Color.RED);
canvas.drawText(mLetters[i], x, baseLine, mPaint);
} else {
mPaint.setColor(Color.BLUE);
canvas.drawText(mLetters[i], x, baseLine, mPaint);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
// 计算出当前触摸字母 获取当前的位置
float currentMoveY = event.getY();
//每个文字的高度
int itemHeight = (getHeight() - getPaddingTop() - getPaddingBottom()) / mLetters.length;
int currentPosition = (int) (currentMoveY / itemHeight);
if(currentPosition<0){
currentPosition=0;
}
if(currentPosition>mLetters.length-1){
currentPosition=mLetters.length-1;
}
mCurrentTouchLetter=mLetters[currentPosition];
if (mListener != null) {
mListener.touch(mCurrentTouchLetter, true);
}
// 重新绘制
invalidate();
break;
case MotionEvent.ACTION_UP:
if (mListener != null) {
mListener.touch(mCurrentTouchLetter, false);
}
break;
default:
break;
}
return true;
}
private LetterTouchListener mListener;
public void setOnLetterTouchListener(LetterTouchListener listener) {
this.mListener = listener;
}
public interface LetterTouchListener {
void touch(CharSequence letter, boolean isTouch);
}
}
布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/letter_tv"
android:layout_width="wrap_content"
android:layout_centerInParent="true"
android:text="A"
android:visibility="gone"
android:textSize="16sp"
android:textColor="#FF0000"
android:layout_height="wrap_content" />
<com.peakmain.view.lettersidebar.LetterSideBar
android:id="@+id/letter_side_bar"
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:background="@color/colorPrimary"
android:layout_height="match_parent" />
</RelativeLayout>
使用
public class MainActivity extends AppCompatActivity implements LetterSideBar.LetterTouchListener {
private TextView mLetterTv;
private LetterSideBar mLetterSideBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLetterTv = (TextView) findViewById(R.id.letter_tv);
mLetterSideBar = (LetterSideBar) findViewById(R.id.letter_side_bar);
mLetterSideBar.setOnLetterTouchListener(this);
}
@Override
public void touch(CharSequence letter, boolean isTouch) {
if(isTouch) {
mLetterTv.setVisibility(View.VISIBLE);
mLetterTv.setText(letter);
}else{
mLetterTv.setVisibility(View.GONE);
}
}
}