- 首先在values中创建attrs.xml,并加入如下代码,自定义属性:
<declare-styleable name="CustomBar">
<attr name="textColor" format="color"/>
<attr name="selectColor" format="color"/>
</declare-styleable>
2.自定义CustomBar 继承View:
public class CustomBar extends View {
private int mSelectColor = Color.BLUE;
private int mNormalColor = Color.BLACK;
private Paint mPaint;
private final String[] mBarTexts = {"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 int mSelectPosition = -1;
private OnFlingTouchListener mOnFlingTouchListener;
public CustomBar(Context context) {
this(context, null);
}
public CustomBar(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
if (attrs != null) {
TypedArray typedArray = context.obtainStyledAttributes(R.styleable.CustomBar);
mSelectColor = typedArray.getColor(R.styleable.CustomBar_selectColor, Color.BLUE);
mNormalColor = typedArray.getColor(R.styleable.CustomBar_textColor, Color.BLACK);
typedArray.recycle();
}
mPaint = new Paint();
mPaint.setColor(mNormalColor);
mPaint.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas) {
for (int i = 0; i < mBarTexts.length; i++) {
String item = mBarTexts[i];
//获取字体的宽度
int textWidth = (int) mPaint.measureText(item);
int x = getWidth() / 2 - textWidth / 2;
Paint.FontMetricsInt fontMetricsInt = mPaint.getFontMetricsInt();
int dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom;
int itemHeight = (getHeight() - getPaddingBottom() - getPaddingTop()) / mBarTexts.length;
int y = dy + itemHeight / 2 + i * itemHeight;//基线
if (mSelectPosition == i) {
mPaint.setColor(mSelectColor);
} else {
mPaint.setColor(mNormalColor);
}
canvas.drawText(item, x, y, mPaint);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int textWidth = (int) mPaint.measureText("A");
int width = textWidth + getPaddingLeft() + getPaddingRight();
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
float dy = event.getY();
if(dy < 0){
return false;
}
int itemHeight = (getHeight() - getPaddingBottom() - getPaddingTop()) / mBarTexts.length;
int currentPosition = (int) (dy / itemHeight);
if (mSelectPosition != currentPosition && currentPosition < mBarTexts.length) {
mSelectPosition = currentPosition;
invalidate();
}
if(mOnFlingTouchListener != null){
mOnFlingTouchListener.touchPosition(mSelectPosition);
}
break;
case MotionEvent.ACTION_UP:
if(mOnFlingTouchListener != null){
mOnFlingTouchListener.cancelTouch();
}
break;
}
return true;
}
public void setOnFlingTouchListener(OnFlingTouchListener onFlingTouchListener) {
mOnFlingTouchListener = onFlingTouchListener;
}
interface OnFlingTouchListener{
void touchPosition(int position);
void cancelTouch();
}
}