Android 自定义 View 之游戏摇杆键盘实现 (一),二本学渣考研失败
由来
原本的项目,操作方向的方式为上下左右,左上需要同时按住左键和右键的方式进行操作。
近来升级项目,操作方式改为类似王者荣耀的摇杆操作。如下图:
绘制背景
实现遥感按钮,需要绘制背景,绘制中心的遥感按钮。绘制遥感背景,需要创建一个 RemoteViewBg 类,存储背景图,减少重复创建 bitmap。RemoteViewBg 类代码如下:
public class RemoteViewBg {private Bitmap bitmapBg;public RemoteViewBg(Bitmap bitmap) {bitmapBg = bitmap;}
//背景的绘图函数 public void draw(Canvas canvas, Paint paint, Rect src0 ,Rect dst0 ) {canvas.drawBitmap(bitmapBg, src0, dst0, paint);}}
点击触摸事件
重写系统的触摸时间,判断触摸点在背景范围内还是背景范围外
@Overridepublic boolean onTouchEvent(MotionEvent event) {if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) {// // 在范围外触摸 if (Math.sqrt(Math.pow((bigCircleX - (int) event.getX()), 2) + Math.pow((bigCircleY - (int) event.getY()), 2)) >= bigCircleR) {
double tempRad = getRad(bigCircleX, bigCircleY, event.getX(), event.getY());
getXY(bigCircleX, bigCircleY, bigCircleR, tempRad);} else {//范围内触摸 smallCircleX = (int) event.getX();smallCircleY = (int) event.getY();}} else if (event.getAction() == MotionEvent.ACTION_UP) {smallCircleX = bigCircleX;smallCircleY = bigCircleY;
}return true;}
弧度计算
通过 event.getX(), event.getY()获得当前的触摸点,与圆点进行计算,获取弧度
/***
得到两点之间的弧度*/public float getRad(float px1, float py1, float px2, float py2) {float x = px2 - px1;
float y = py1 - py2;//斜边的长 float z = (float) Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));float cosAngle = x / z;float rad = (float) Math.acos(cosAngle);
if (py2 < py1) {rad = -rad;}return rad;}
图形绘制
通过 canvas.drawCircle()和 canvas.drawBitmap()分别进行遥感按钮和遥感背景的绘制,注意对遥感背景的保存,如果在绘制的时候每次 BitmapFactory.decodeResource()会增加耗时,因此只需在 surfaceCreated()中进行 bitmap 的生成即可。
public void draw() {try {canvas = sfh.lockCanvas();canvas.drawColor(getResources().getColor(R.color.ghostwhite));
// 指定图片绘制区域(左上角的四分之一)Rect src = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
// 指定图片在屏幕上显示的区域 Rect dst = new Rect(bigCircleX - bigCircleR, bigCircleY - bigCircleR, bigCircleX + bigCircleR, bigCircleY + bigCircleR);// 绘制图片 remoteViewBg.draw(canvas, paint
, src, dst);paint.setColor(0x70ff0000);//绘制摇杆 canvas.drawCircle(smallCircleX, smallCircleY, smallCircleR, paint);} catch (Exception e) {// TODO: handle exception} finally {try {if (canvas != null)sfh.unlockCanvasAndPost(canvas);} catch (Exception e2) {e2.printStackTrace();}}}
使用
在 activity 中动态添加
RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.dance_relative_layout);remoteSurfaceView = new RemoteSurfaceView(this);params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT);remoteSurfaceView.setLayoutParams(params);relativeLayout.addView(remoteSurfaceView);
关键代码
public RemoteSurfaceView(Context context) {super(context);sfh = this.getHolder();sfh.addCallback(this);paint = new Paint();paint.setAntiAlias(true);setFocusable(true);setFocusableInTouchMode(true);setZOrderOnTop(true);getHolder().setFormat(PixelFormat.TRANSPARENT);
}
public void surfaceCreated(SurfaceHolder holder) {int width = getWidth();int height = getHeight();bigCircleX = width / 2;bigCircleY = height / 2;bigCircleR = width / 4;
评论