先上图,给吃瓜群众看一下。
效果图
起初拿到方案的时候,感觉很棘手。。。
设计稿
分拆为三部分。中间这个视野统计让我无从下手。不过经过仔细分析后,原来so easy!记录一下老菜鸟的实现过程。。。
图片实现
老菜鸟先写个view,里面画了4个圆,结果就是视野圆圈马赛克,大小拉伸。失败的效果图就不放出来了。
绘制实现
- 自定义view
public class DotaMapView extends View {
public DotaMapView(Context context) {
super(context);
}
public DotaMapView(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
- 控件大小背景图片处理
老菜鸟试过2种方案,第一种就是不设置,在xml里面background设置为dota地图。后来给否决了。因为位置和缩放问题。第二种就是把背景图绘制上去,nonono,不是绘制一个dota、地图。。。老菜鸟没那水平 ,是把背景图绘制出来。
所以,声明背景bitmap,并初始化
/** * 背景圖片 */
private Bitmap mBgImg;
public DotaMapView(Context context, AttributeSet attrs) { super(context, attrs); init();}
private void init() { mBgImg = BitmapFactory.decodeResource(getResources(), R.mipmap.math_data_map);}
- 然后自定义控件三部曲之onMeasure,因为地图是方的,并且以背景图为参照
/** * 控件的宽 */private int mWidth;
/** * 控件的高 */private int mHeight;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
/**
* 设置宽度
*/
int specMode = MeasureSpec.getMode(widthMeasureSpec);
int specSize = MeasureSpec.getSize(widthMeasureSpec);
if (specMode == MeasureSpec.EXACTLY)// match_parent , accurate
{
mWidth = specSize;
} else {
// 由图片决定宽
int desireByImg = getPaddingLeft() + getPaddingRight() + mBgImg.getWidth();
if (specMode == MeasureSpec.AT_MOST)// wrap_content
{
mWidth = Math.min(desireByImg, specSize);
}
}
/***
* 方形高=宽
*/
mHeight = mWidth;
setMeasuredDimension(mWidth, mHeight);
}
如果是设置的固定大小,比如
android:layout_width="match_parent" android:layout_width="50dp"
那么控件的大小就是设置大小,如果是wrap_content,那么有背景图片大小和布局宽度共同决定
- 没有什么排版布局,所以直接进入绘制,先把背景绘制出来,背景是充满控件并且完全展示的,所以用这个方法
绘制背景
第二个参数是图片的裁剪,因为我们是100%的,所以传个null,第三个参数是位置
mDestRect.left = 0; mDestRect.top = 0; mDestRect.right = mWidth; mDestRect.bottom = mHeight;
别再draw里new对象,所以在init里实例化Rect,然后绘制
//绘制背景图片
private void drawBackGroud(Canvas canvas) {
mDestRect.left = 0;
mDestRect.top = 0;
mDestRect.right = mWidth;
mDestRect.bottom = mHeight;
canvas.drawBitmap(mBgImg, null, mDestRect, mPaint);
}
-
然后分析眼睛
眼睛
首先是外边圆环,然后是中间透明度50的视野,然后是实心的圆心。
绘制这个眼睛,需要:整个眼睛半径,外环的宽度,内圆的半径。
我们定义三个画笔设置样式,声明颜色,开始绘制
//绘制t天辉真眼
private void drawDOs(Canvas canvas) {
//服务端给的坐标是在dota地图里的坐标,我们要换算成控件的坐标,比如x: 14,y: 68,地图宽高是127
int x= 14* mWidth / MAP_SIZE;
int y= 68* mHeight / MAP_SIZE;
mPaintOut.setColor(mDOutColor);
mPaintIn.setColor(mOBColor);
//外环的宽度是以外环中心为中点,像内外同时等量扩散的,比如一个半径为10的圆,外环半径为2,如果直接以半径为10画,那么整个圆的半径就是11。
//所以要重新计算半径:整个圆半径-圆环宽度/2
canvas.drawCircle( x,y,obRadius-PAINT_OUT_PX/2,mPaintOut);
//绘制中间半透明
canvas.drawCircle( x,y,obRadius-PAINT_OUT_PX,mPaintCenter);
//绘制实心圆
canvas.drawCircle( x,y,PAINT_IN_PX,mPaintIn);
}
- 然后把是四个圆都绘制出来
网友评论