自定义属性:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="NumberKeyboard" > <attr name="isLine" format="boolean"/> <attr name="distance" format="dimension"/> <attr name="boundLineColor" format="color"/> <attr name="cutLineColor" format="color"/> <attr name="numberBg" format="color"/> <attr name="clearBg" format="color"/> <attr name="isRom" format="boolean"/> <attr name="delIcon" format="reference"/> <attr name="numRound" format="dimension"/> <attr name="numSize" format="dimension"/> </declare-styleable> </resources>代码:
import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import com.cesecsh.ims.R; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Created by wdy on 2017/11/13. */ public class NumberKeyboard extends View { private int viewWidth; private int viewHeight; private int rectWidth; private int rectHeight; private Context mContext; private boolean isLine; private boolean isRom; /** * 相邻按钮之间距离 */ private int distance; private int boundColor; private int cutLineColor; private int numBg; /** * 删除按钮背景色 */ private int clearBg; private Rect rectClear; private List<String> nums; private Drawable delDrawable; private float numSize; private float numRound; public NumberKeyboard(Context context) { super(context); } public NumberKeyboard(Context context, @Nullable AttributeSet attrs) { super(context, attrs); this.mContext = context; initAttrs(context, attrs); } private void initAttrs(Context context, AttributeSet attrs) { distance = 0; boundColor = Color.GRAY; cutLineColor = Color.BLACK; numBg = Color.WHITE; clearBg = Color.LTGRAY; numSize = 20; TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.NumberKeyboard); int indexCount = typedArray.getIndexCount(); for (int i = 0; i < indexCount; i++) { int index = typedArray.getIndex(i); switch (index) { case R.styleable.NumberKeyboard_boundLineColor: boundColor = typedArray.getColor(R.styleable.NumberKeyboard_boundLineColor, boundColor); break; case R.styleable.NumberKeyboard_clearBg: clearBg = typedArray.getColor(R.styleable.NumberKeyboard_clearBg, clearBg); break; case R.styleable.NumberKeyboard_isLine: isLine = typedArray.getBoolean(R.styleable.NumberKeyboard_isLine, isLine); break; case R.styleable.NumberKeyboard_distance: distance = (int) typedArray.getDimension(R.styleable.NumberKeyboard_distance, distance); break; case R.styleable.NumberKeyboard_cutLineColor: cutLineColor = typedArray.getColor(R.styleable.NumberKeyboard_cutLineColor, cutLineColor); break; case R.styleable.NumberKeyboard_isRom: isRom = typedArray.getBoolean(R.styleable.NumberKeyboard_isRom, isRom); break; case R.styleable.NumberKeyboard_numberBg: numBg = typedArray.getColor(R.styleable.NumberKeyboard_numberBg, numBg); break; case R.styleable.NumberKeyboard_delIcon: delDrawable = typedArray.getDrawable(R.styleable.NumberKeyboard_delIcon); break; case R.styleable.NumberKeyboard_numRound: numRound = typedArray.getDimension(R.styleable.NumberKeyboard_numRound, numRound); break; case R.styleable.NumberKeyboard_numSize: numSize = typedArray.getDimension(R.styleable.NumberKeyboard_numSize ,numSize); break; } } typedArray.recycle(); if (!isLine && distance == 0) { distance = 2; } else if (isLine) { distance = 0; numRound = 0; } } public void setLine(boolean line) { isLine = line; } public void setRom(boolean rom) { isRom = rom; } public void setDistance(int distance) { this.distance = distance; } public void setBoundColor(int boundColor) { this.boundColor = boundColor; } public void setCutLineColor(int cutLineColor) { this.cutLineColor = cutLineColor; } public void setNumBg(int numBg) { this.numBg = numBg; } public void setClearBg(int clearBg) { this.clearBg = clearBg; } public void setDelDrawable(Drawable delDrawable) { this.delDrawable = delDrawable; } public void setNumSize(float numSize) { this.numSize = numSize; } public void setNumRound(float numRound) { this.numRound = numRound; } public NumberKeyboard(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); viewWidth = getWidth(); viewHeight = getHeight(); rectWidth = viewWidth / 3; rectHeight = viewHeight / 4; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (isLine) { drawBound(canvas); drawCutLine(canvas); } else drawNumRect(canvas); drawNum(canvas); } private void drawNum(Canvas canvas) { Paint numPaint = new Paint(Paint.ANTI_ALIAS_FLAG); numPaint.setColor(Color.BLACK); numPaint.setTextSize(numSize); nums = new ArrayList<>(); for (int i = 0; i < 10; i++) { nums.add(i + ""); } if (isRom) { Collections.shuffle(nums); } for (int i = 0; i < nums.size(); i++) { switch (i) { case 0: case 1: case 2: canvas.drawText(nums.get(i), rectWidth / 2 + (i * rectWidth) - numSize / 2, rectHeight / 2 + numSize / 2, numPaint); break; case 3: case 4: case 5: canvas.drawText(nums.get(i), rectWidth / 2 + (i - 3) * rectWidth - numSize / 2, rectHeight / 2 * 3 + numSize / 2, numPaint); break; case 6: case 7: case 8: canvas.drawText(nums.get(i), rectWidth / 2 + (i - 6) * rectWidth - numSize / 2, rectHeight / 2 * 5 + numSize / 2, numPaint); break; case 9: canvas.drawText(nums.get(i), rectWidth / 2 * 3 - numSize / 2, rectHeight / 2 * 7 + numSize / 2, numPaint); break; } } if (delDrawable == null) return; int delWidth = delDrawable.getIntrinsicWidth(); int delHeight = delDrawable.getIntrinsicHeight(); if (delHeight > rectHeight) { delHeight = rectHeight; } if (delWidth > rectWidth) { delWidth = rectWidth; } Rect rect = new Rect(rectWidth * 2 + (rectWidth - delWidth) / 2, rectHeight * 3 + (rectHeight - delHeight) / 2, rectWidth * 2 + (rectWidth - delWidth) / 2 + delWidth, rectHeight * 3 + (rectHeight - delHeight) / 2 + delHeight); delDrawable.setBounds(rect); delDrawable.draw(canvas); } private void drawCutLine(Canvas canvas) { Paint cutLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); cutLinePaint.setColor(cutLineColor); canvas.drawLine(rectWidth, 0, rectWidth, viewHeight, cutLinePaint); canvas.drawLine(rectWidth * 2, 0, rectWidth * 2, viewHeight, cutLinePaint); canvas.drawLine(0, rectHeight, viewWidth, rectHeight, cutLinePaint); canvas.drawLine(0, rectHeight * 2, viewWidth, rectHeight * 2, cutLinePaint); canvas.drawLine(0, rectHeight * 3, viewWidth, rectHeight * 3, cutLinePaint); } private void drawBound(Canvas canvas) { Paint boundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); boundPaint.setColor(boundColor); canvas.drawLine(0, 0, viewWidth - 10, 0, boundPaint); canvas.drawLine(0, 0, 0, viewHeight - 10, boundPaint); canvas.drawLine(0, viewHeight - 10, viewWidth - 10, viewHeight - 10, boundPaint); canvas.drawLine(viewWidth - 10, 0, viewWidth - 10, viewHeight - 10, boundPaint); } private void drawNumRect(Canvas canvas) { Paint rectPaint = new Paint(Paint.ANTI_ALIAS_FLAG); rectPaint.setColor(numBg); Rect rect1 = new Rect(distance, distance, rectWidth - distance, rectHeight - distance); Rect rect2 = new Rect(rectWidth + distance, distance, rectWidth * 2 - distance, rectHeight - distance); Rect rect3 = new Rect(rectWidth * 2 + distance, distance, viewWidth - distance, rectHeight - distance); Rect rect4 = new Rect(distance, rectHeight + distance, rectWidth - distance, rectHeight * 2 - distance); Rect rect5 = new Rect(rectWidth + distance, rectHeight + distance, rectWidth * 2 - distance, rectHeight * 2 - distance); Rect rect6 = new Rect(rectWidth * 2 + distance, rectHeight + distance, viewWidth - distance, rectHeight * 2 - distance); Rect rect7 = new Rect(distance, rectHeight * 2 + distance, rectWidth - distance, rectHeight * 3 - distance); Rect rect8 = new Rect(rectWidth + distance, rectHeight * 2 + distance, rectWidth * 2 - distance, rectHeight * 3 - distance); Rect rect9 = new Rect(rectWidth * 2 + distance, rectHeight * 2 + distance, viewWidth - distance, rectHeight * 3 - distance); Rect rectBlank = new Rect(distance, rectHeight * 3 + distance, rectWidth - distance, viewHeight - distance); Rect rect0 = new Rect(rectWidth + distance, rectHeight * 3 + distance, rectWidth * 2 - distance, viewHeight - distance); rectClear = new Rect(rectWidth * 2 + distance, rectHeight * 3 + distance, viewWidth - distance, viewHeight - distance); canvas.drawRoundRect(new RectF(rect0), numRound, numRound, rectPaint); canvas.drawRoundRect(new RectF(rect1), numRound, numRound, rectPaint); canvas.drawRoundRect(new RectF(rect2), numRound, numRound, rectPaint); canvas.drawRoundRect(new RectF(rect3), numRound, numRound, rectPaint); canvas.drawRoundRect(new RectF(rect4), numRound, numRound, rectPaint); canvas.drawRoundRect(new RectF(rect5), numRound, numRound, rectPaint); canvas.drawRoundRect(new RectF(rect6), numRound, numRound, rectPaint); canvas.drawRoundRect(new RectF(rect7), numRound, numRound, rectPaint); canvas.drawRoundRect(new RectF(rect8), numRound, numRound, rectPaint); canvas.drawRoundRect(new RectF(rect9), numRound, numRound, rectPaint); rectPaint.setColor(clearBg); canvas.drawRoundRect(new RectF(rectClear), numRound, numRound, rectPaint); canvas.drawRoundRect(new RectF(rectBlank), numRound, numRound, rectPaint); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_UP: float x = event.getX(); float y = event.getY(); dragLocation(x, y); break; } return true; } private void dragLocation(float x, float y) { if (x < 0 || y < 0 || x > viewWidth || y > viewHeight) return; int num = -1; if (y < rectHeight - distance && y > distance) { if (x < rectWidth - distance && x > distance) { num = Integer.parseInt(nums.get(0)); } else if (x < rectWidth * 2 - distance && x > rectWidth + distance) { num = Integer.parseInt(nums.get(1)); } else if (viewWidth - distance > x && x > 2 * rectWidth + distance) num = Integer.parseInt(nums.get(2)); } else if (y < 2 * rectHeight - distance && y > rectHeight + distance) { if (x < rectWidth - distance && x > distance) { num = Integer.parseInt(nums.get(3)); } else if (x < rectWidth * 2 - distance && x > rectWidth + distance) { num = Integer.parseInt(nums.get(4)); } else if (viewWidth - distance > x && x > 2 * rectWidth + distance) num = Integer.parseInt(nums.get(5)); } else if (y < 3 * rectHeight && y > 2 * rectHeight + distance) { if (x < rectWidth - distance && x > distance) { num = Integer.parseInt(nums.get(6)); } else if (x < rectWidth * 2) { num = Integer.parseInt(nums.get(7)); } else num = Integer.parseInt(nums.get(8)); } else if (y < 4 * rectHeight && y > 3 * rectHeight + distance) { if (x < rectWidth - distance && x > distance) { num = -1; } else if (x < rectWidth * 2 - distance && x > rectWidth + distance) { num = Integer.parseInt(nums.get(9)); } else if (viewWidth - distance > x && x > 2 * rectWidth + distance) num = -2; } if (onNumKeyClickListener != null && num != -1) { onNumKeyClickListener.click(num); } ToastView.getInstance().toast(mContext, num + ""); } public interface OnNumKeyClickListener { void click(int num); } OnNumKeyClickListener onNumKeyClickListener; public void setOnNumKeyClickListener(OnNumKeyClickListener onNumKeyClickListener) { this.onNumKeyClickListener = onNumKeyClickListener; } }
所需知识点:
1.android中view的坐标知识
a.getX(),getY()获取自定义view的相对坐标 。getRowX(),getRowY()获取绝对坐标(到屏幕的坐标)
2.绘制相关知识
a.绘制图片 先获得一张图片drawable ,然后算出所应处的位置通过 drawable.setBounds()设置 ,最后调用drawable.draw()绘制出来