先來個圖
兩個的
多個的
布局
<com.rsd.library.widget.RTabLayout
android:layout_width="wrap_content"
app:tabTextSize="20sp"
app:tabRadius="10dp"
app:tabBorderColor="#0000ff"
app:tabBorderWidth="1dp"
app:tabMenus="AAA,BBB"
android:layout_height="wrap_content" />
本來說圓角地方都不一樣,先是寫了一個用path實作的,不過那樣計算起來太麻煩。就想改成用xfermode的了,先畫個圓角rect,在前面畫幾個rect就可以了。
代碼
public class RTabLayout extends View {
private Paint paint;
private RectF rect;
private RectF rect2;
private Xfermode xfermode;
private String[] menus;
private RectF[] rects;
private float perWidth;
private int index;
private int radius;
private int borderWidth;
private int borderColor;
private int selectColor;
private int unSelectColor;
private int dividedColor;
private int textSize;
private float touchSlop;
private float startX = ;
private float startY = ;
private double distance = ;
private int touchIndex;
private boolean drawLine;
private OnItemClickListener onItemClickListener;
public RTabLayout(Context context) {
this(context, null);
}
public RTabLayout(Context context, AttributeSet attrs) {
this(context, attrs, );
}
public RTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RTabLayout, defStyleAttr, );
radius = array.getDimensionPixelSize(R.styleable.RTabLayout_tabRadius, );
borderWidth = array.getDimensionPixelSize(R.styleable.RTabLayout_tabBorderWidth, );
borderColor = array.getColor(R.styleable.RTabLayout_tabBorderColor, );
selectColor = array.getColor(R.styleable.RTabLayout_tabSelectColor, );
unSelectColor = array.getColor(R.styleable.RTabLayout_tabUnSelectColor, );
dividedColor = array.getColor(R.styleable.RTabLayout_tabDividedColor, );
textSize = array.getDimensionPixelSize(R.styleable.RTabLayout_tabTextSize, );
String menu = array.getString(R.styleable.RTabLayout_tabMenus);
if (menu == null) {
menus = new String[]{"A", "B"};
} else {
menus = menu.split(",");
}
setMenus(menus);
array.recycle();
init();
}
private void init() {
touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextSize(textSize);
rect = new RectF();
rect2 = new RectF();
xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
rect.set(, , w, h);
rect2.set(borderWidth, borderWidth, w - borderWidth, h - borderWidth);
perWidth = w / rects.length;
for (int i = ; i < rects.length; i++) {
rects[i] = new RectF(i * perWidth, , (i + ) * perWidth, h);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int w = , h = ;
if (widthMode == MeasureSpec.EXACTLY) {
w = widthSize;
} else {
int maxLen = ;
for (int i = ; i < menus.length; i++) {
if (menus[i].length() > maxLen) {
maxLen = menus[i].length();
}
}
w = textSize * (maxLen + ) * menus.length;
}
if (heightMode == MeasureSpec.EXACTLY) {
h = heightSize;
} else {
h = textSize * ;
}
setMeasuredDimension(w, h);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawBg(canvas);
drawLine(canvas);
drawText(canvas);
}
private void drawBg(Canvas canvas) {
paint.setColor(borderColor);
canvas.drawRoundRect(rect, radius, radius, paint);
int layer = canvas.saveLayer(rect, paint, Canvas.ALL_SAVE_FLAG);
canvas.drawRoundRect(rect2, radius, radius, paint);
paint.setXfermode(xfermode);
for (int i = ; i < rects.length; i++) {
if (i == index) {
paint.setColor(selectColor);
} else {
paint.setColor(unSelectColor);
}
canvas.drawRect(rects[i], paint);
}
paint.setXfermode(null);
canvas.restoreToCount(layer);
}
private void drawLine(Canvas canvas) {
if (drawLine) {
return;
}
paint.setColor(dividedColor);
for (int i = ; i < menus.length; i++) {
if (i == index || i == index + ) {
continue;
}
float x = perWidth * i;
float h = rect.height();
canvas.drawLine(x, h * f, x, h * f, paint);
}
drawLine = true;
}
private void drawText(Canvas canvas) {
float x;
float y;
for (int i = ; i < menus.length; i++) {
if (i == index) {
paint.setColor(unSelectColor);
} else {
paint.setColor(selectColor);
}
x = perWidth * (i + f) - paint.measureText(menus[i]) / ;
y = rect.height() / - (paint.descent() + paint.ascent()) / ;
canvas.drawText(menus[i], x, y, paint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
touchIndex = (int) (startX / perWidth);
break;
case MotionEvent.ACTION_MOVE:
distance = Math.sqrt((event.getX() - startX) * (event.getX() - startX) + (event.getY() - startY) * (event.getY() - startY));
break;
case MotionEvent.ACTION_UP:
if (distance < touchSlop) {
setCurrent(touchIndex);
if (onItemClickListener != null) {
onItemClickListener.onItemClick(touchIndex);
}
}
distance = ;
break;
}
return true;
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public void setMenus(String[] menus) {
this.menus = menus;
rects = new RectF[menus.length];
}
public void setCurrent(int position) {
this.index = position;
invalidate();
}
public interface OnItemClickListener {
void onItemClick(int position);
}
}