origin
In the original project, the operation direction is up, down, left and right, and the left and right buttons need to be pressed at the same time for operation.
Recently upgraded the project to a joystick operation similar to King of Glory. The diagram below:
Draw the background
To realize the remote sensing button, it is necessary to draw the background and draw the remote sensing button in the center. To draw a remote sensing background, create a RemoteViewBg class to store the background image and reduce the need to create a bitmap repeatedly. The RemoteViewBg class code looks like this:
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); }}Copy the code
Click and touch events
Rewrite the touch time of the system to determine whether the touch point is in the background range or outside the background range
@Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN || Event.getaction () == motionEvent.action_move) {// // touch out of range 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; }Copy the code
Radian calculation
Get the current touch point through event.getx () and event.gety (), and calculate with the dot to obtain radians
Public float getRad(float px1, float py1, float px2, float py2) {float x = px2 - px1; float y = py1 - py2; // Long 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; }Copy the code
Graphics rendering
Through the canvas. Methods like drawCircle () and canvas. DrawBitmap () for remote sensing, remote sensing background and the drawing of button, pay attention to the preservation of the background on the remote sensing, if every time when drawing BitmapFactory decodeResource () can increase the time consuming, Therefore, the bitmap is generated only in surfaceCreated ().
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, bigCircleX + bigCircleR, bigCircleY + bigCircleR); Remoteviewbg.draw (canvas, paint, SRC, DST); paint.setColor(0x70ff0000); DrawCircle (smallCircleX, smallCircleY, smallCircleR, paint); } catch (Exception e) { // TODO: handle exception } finally { try { if (canvas ! = null) sfh.unlockCanvasAndPost(canvas); } catch (Exception e2) { e2.printStackTrace(); }}}Copy the code
use
Add it dynamically in the 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);
Copy the code
The key code
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; smallCircleX = width / 2; smallCircleY = height / 2; smallCircleR = width / 8; bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.fangxiang); remoteViewBg = new RemoteViewBg(bitmap); th = new Thread(this); flag = true; th.start(); Public float getRad(float px1, float py1, float px2, float py2) {float x = px2 - px1; float y = py1 - py2; // Long 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; } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN || Event.getaction () == motionEvent.action_move) {// Out of scope touch 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; } public void getXY(float x, float y, float R, double rad) { smallCircleX = (float) (R * Math.cos(rad)) + x; smallCircleY = (float) (R * Math.sin(rad)) + y; } 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); DrawCircle (smallCircleX, smallCircleY, smallCircleR, paint); } catch (Exception e) { // TODO: handle exception } finally { try { if (canvas ! = null) sfh.unlockCanvasAndPost(canvas); } catch (Exception e2) { e2.printStackTrace(); } } } public void run() { while (flag) { draw(); try { Thread.sleep(50); } catch (Exception ex) { ex.printStackTrace(); }}}Copy the code
subsequent
The blogger’s implementation mode has also been changed, from SurfaceView to View, but also increased the direction of the arrow indication, time, memory and other optimization, the subsequent update, like favorites.