您好,登錄后才能下訂單哦!
本文小編為大家詳細(xì)介紹“android怎么模擬實(shí)現(xiàn)航拍遙控”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“android怎么模擬實(shí)現(xiàn)航拍遙控”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來(lái)學(xué)習(xí)新知識(shí)吧。
先貼圖
左右兩個(gè)點(diǎn),在圈內(nèi)活動(dòng),一個(gè)是控制油門,一個(gè)是控制方向,放手后會(huì)返回中心點(diǎn),這些在游戲場(chǎng)景中經(jīng)??吹?,比如射擊類的游戲,這里自定義view,繼承ImageView,難點(diǎn)就在手指控制這部分,以下是源碼。
package com.remotecontrol; import android.annotation.TargetApi; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; import android.os.Build; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.MotionEvent; import android.view.WindowManager; import android.widget.ImageView; /** * Created by qingyuan on 2016/5/20. * 自定義view 模擬遙控器 */ public class RemoteControl extends ImageView { public final String TAG="RemoteControl"; public RemoteControl(Context context) { super(context); InitData( context); } public RemoteControl(Context context, AttributeSet attrs) { super(context, attrs); InitData( context); } public RemoteControl(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); InitData( context); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public RemoteControl(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); InitData( context); } DisplayMetrics dm = new DisplayMetrics(); WindowManager manager; //屏幕的寬跟高 int mDisplayWidth; int mDisplayWidth_2;//屏幕寬的1/2 int mDisplayWidth_4;//屏幕寬的1/4 int mDisplayWidth_43;//屏幕寬的3/4 int mDisplayHeight; int mDisplayHeight_2;//屏幕高的1/2 int mDisplayHeight_4;//屏幕高的1/4 int mDisplayHeight_43;//屏幕高的3/4 Point leftCenter;//左邊中點(diǎn)的坐標(biāo) Point rightCenter;//右邊中點(diǎn)的坐標(biāo) /********************右邊的底圖**************************/ Bitmap btm_bg; Rect rectSrc_bg; Rect rectDst_bg; /********************左邊的底圖**************************/ Bitmap btm_bar; Rect rectSrc_bar; Rect rectDst_bar; /********************左邊的圓點(diǎn)**************************/ Bitmap btm_circle_left; MyPoint leftPoint; double leftDistance;//距離中心點(diǎn)的距離 double leftAngle;//atan2的角度值 int leftCircle_2;//圓的一半 /********************右邊的圓點(diǎn)**************************/ Bitmap btm_circle_right; MyPoint rightPoint; double rightDistance;//距離中心點(diǎn)的距離 double rightAngle;//atan2的角度值 int rightCircle_2;//圓的一半 int stopRadius;//圓的半徑,左右的半徑是一樣的 Matrix matrix;//矩陣,同過(guò)改變矩陣來(lái)改變bitmap的位置 final double degToRad = Math.PI/180.0; final double radToDeg = 180.0/Math.PI; public void InitData(Context context) { manager = (WindowManager) context .getSystemService(Context.WINDOW_SERVICE); manager.getDefaultDisplay().getMetrics(dm); mDisplayWidth = dm.widthPixels; mDisplayHeight = dm.heightPixels; mDisplayWidth_2=mDisplayWidth/2;//屏幕寬的1/2 mDisplayWidth_4=mDisplayWidth/4;//屏幕寬的1/4 mDisplayWidth_43=mDisplayWidth*3/4;//屏幕寬的3/4 mDisplayHeight_2=mDisplayHeight/2;//屏幕高的1/2 mDisplayHeight_4=mDisplayHeight/4;//屏幕高的1/4 mDisplayHeight_43=mDisplayHeight*3/4;//屏幕高的3/4 btm_bg= BitmapFactory.decodeResource(context.getResources(),R.drawable.control_bg); btm_circle_left= BitmapFactory.decodeResource(context.getResources(),R.drawable.records); btm_circle_right= BitmapFactory.decodeResource(context.getResources(),R.drawable.help); btm_bar= BitmapFactory.decodeResource(context.getResources(),R.drawable.shift_bar_bg); matrix = new Matrix(); float scaleSize= (float) (mDisplayHeight*1.0/btm_bg.getWidth()*0.65f);//縮放為屏幕的0.65 matrix.postScale(scaleSize,scaleSize); btm_bg = Bitmap.createBitmap(btm_bg,0,0,btm_bg.getWidth(),btm_bg.getHeight(),matrix,true); btm_bar = Bitmap.createBitmap(btm_bar,0,0,btm_bar.getWidth(),btm_bar.getHeight(),matrix,true); btm_circle_left = Bitmap.createBitmap(btm_circle_left,0,0,btm_circle_left.getWidth(),btm_circle_left.getHeight(),matrix,true); btm_circle_right = Bitmap.createBitmap(btm_circle_right,0,0,btm_circle_right.getWidth(),btm_circle_right.getHeight(),matrix,true); leftCircle_2=btm_circle_left.getWidth()/2; rightCircle_2=btm_circle_right.getWidth()/2; //左邊中心點(diǎn)的位置設(shè)為 leftCenter=new Point(); leftCenter.set(mDisplayWidth_4,mDisplayHeight_2); //右邊中心點(diǎn)的位置設(shè)為 rightCenter=new Point(); rightCenter.set(mDisplayWidth_43,mDisplayHeight_2); /***********************左邊的地圖位置***************************/ rectSrc_bar=new Rect(0,0,btm_bar.getWidth(),btm_bar.getHeight()); rectDst_bar=new Rect( leftCenter.x-btm_bg.getWidth()/2, leftCenter.y-btm_bg.getHeight()/2, leftCenter.x+btm_bg.getWidth()/2, leftCenter.y+btm_bg.getHeight()/2 ); /***********************左邊的圓點(diǎn)位置***************************/ leftPoint=new MyPoint(leftCenter.x, leftCenter.y); /***********************右邊的圓底圖位置***************************/ rectSrc_bg=new Rect(0,0,btm_bg.getWidth(),btm_bg.getHeight()); rectDst_bg=new Rect( rightCenter.x-btm_bar.getWidth()/2, rightCenter.y-btm_bar.getHeight()/2, rightCenter.x+btm_bar.getWidth()/2, rightCenter.y+btm_bar.getHeight()/2 ); /***********************右邊邊的圓點(diǎn)位置***************************/ rightPoint=new MyPoint(rightCenter.x,rightCenter.y); //半徑為底圖的一半,這里決定了可移動(dòng)圓的大小 stopRadius=btm_bg.getWidth()/2; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawBitmap(btm_bg,rectSrc_bg,rectDst_bg,null); canvas.drawBitmap(btm_bar,rectSrc_bar,rectDst_bar,null); //更新的左中心點(diǎn)的位置 matrix.reset(); matrix.postTranslate(leftPoint.x-leftCircle_2,leftPoint.y-leftCircle_2); canvas.drawBitmap(btm_circle_left,matrix,null); //更新的右中心點(diǎn)的位置 matrix.reset(); matrix.postTranslate(rightPoint.x-rightCircle_2,rightPoint.y-rightCircle_2); canvas.drawBitmap(btm_circle_right,matrix,null); } @TargetApi(Build.VERSION_CODES.ECLAIR) @Override public boolean onTouchEvent(MotionEvent event) { float x; float y; double distance;//圓點(diǎn)離中心點(diǎn)的距離 double angle;//圓點(diǎn)tan2的角度 float x2; float y2; double angle2; double distance2; switch (MotionEvent.ACTION_MASK & event.getAction()) { case MotionEvent.ACTION_DOWN: //判斷第一個(gè)手指按下的位置所在的區(qū)域 if(Math.abs(event.getX()-rightPoint.x)<btm_circle_right.getWidth() && Math.abs(event.getY()-rightPoint.y)<btm_circle_right.getHeight()) { rightPoint.setPointerIndex(0); rightPoint.setCanMove(true); } else if(Math.abs(event.getX()-leftPoint.x)<btm_circle_left.getWidth() && Math.abs(event.getY()-leftPoint.y)<btm_circle_left.getHeight()) { leftPoint.setPointerIndex(0); leftPoint.setCanMove(true); } break; case MotionEvent.ACTION_POINTER_UP: //獲取離開手指的id int pointerId = (event.getAction()&MotionEvent.ACTION_POINTER_ID_MASK)>>> MotionEvent.ACTION_POINTER_ID_SHIFT; //根據(jù)手指離開的id判斷是開了的是哪個(gè)移動(dòng)的點(diǎn) if(rightPoint.isCanMove() && rightPoint.getPointerIndex()==pointerId){ rightPoint.setCanMove(false); //手指離開讓圓點(diǎn)返回中心點(diǎn) rightPoint.x=rightCenter.x; rightPoint.y=rightCenter.y; rightPoint.setPointerIndex(-1); } if(leftPoint.isCanMove() &&leftPoint.getPointerIndex()==pointerId) { leftPoint.setCanMove(false); leftPoint.x=leftCenter.x; leftPoint.y=rightCenter.y; leftPoint.setPointerIndex(-1); } break; case MotionEvent.ACTION_UP: //全部手指離開之后 rightPoint.setCanMove(false); rightPoint.x=rightCenter.x; rightPoint.y=rightCenter.y; rightPoint.setPointerIndex(0); leftPoint.setCanMove(false); leftPoint.x=leftCenter.x; leftPoint.y=leftCenter.y; leftPoint.setPointerIndex(0); break; case MotionEvent.ACTION_POINTER_DOWN: //獲取第二根手指的id pointerId = (event.getAction()&MotionEvent.ACTION_POINTER_ID_MASK)>>> MotionEvent.ACTION_POINTER_ID_SHIFT; //第二根手指按下 if(!rightPoint.isCanMove() && Math.abs(event.getX(pointerId)-rightPoint.x)<btm_circle_right.getWidth() && Math.abs(event.getY(pointerId)-rightPoint.y)<btm_circle_right.getHeight()) { rightPoint.setPointerIndex(pointerId); rightPoint.setCanMove(true); }else if(!leftPoint.isCanMove() && Math.abs(event.getX(pointerId)-leftPoint.x)<btm_circle_left.getWidth() && Math.abs(event.getY(pointerId)-leftPoint.y)<btm_circle_left.getHeight()) { leftPoint.setPointerIndex(pointerId); leftPoint.setCanMove(true); } break; case MotionEvent.ACTION_MOVE: //如果是單指移動(dòng) if(event.getPointerCount()==1) { if (rightPoint.isCanMove()) { x=event.getX(0)-rightCenter.x; y=event.getY(0)-rightCenter.y; //計(jì)算角度,atan2的用法自己百度咯 angle = (Math.atan2( x, y )*radToDeg)-90; distance = Math.sqrt((x*x)+(y*y)); //判斷是不是超出了規(guī)定的半徑長(zhǎng)度 if( distance >= stopRadius ) { distance = stopRadius; double radAngle = angle*degToRad; rightPoint.x = (int) (distance*Math.cos(radAngle))+rightCenter.x; rightPoint.y = (int) (-distance*Math.sin(radAngle))+rightCenter.y; } else { rightPoint.x= (int) event.getX(0); rightPoint.y = (int)event.getY(0); } rightDistance=distance; rightAngle=angle; } else if(leftPoint.isCanMove()) { x=event.getX(0)-leftCenter.x; y=event.getY(0)-leftCenter.y; angle = (Math.atan2( x, y )*radToDeg)-90; distance = Math.sqrt((x*x)+(y*y)); if( distance >= stopRadius ) { distance = stopRadius; double radAngle = angle*degToRad; leftPoint.x = (int) (distance*Math.cos(radAngle))+leftCenter.x; leftPoint.y = (int) (-distance*Math.sin(radAngle))+leftCenter.y; } else { leftPoint.x = (int) event.getX(0); leftPoint.y = (int) event.getY(0); } } } else { //雙指移動(dòng) if (rightPoint.isCanMove() && rightPoint.getPointerIndex()!=-1 && rightPoint.getPointerIndex()<event.getPointerCount() ) { x=event.getX(rightPoint.getPointerIndex())-rightCenter.x; y=event.getY(rightPoint.getPointerIndex())-rightCenter.y; angle = (Math.atan2( x, y )*radToDeg)-90; distance = Math.sqrt((x*x)+(y*y)); if( distance >= stopRadius ) { distance = stopRadius; double radAngle = angle*degToRad; rightPoint.x = (int) (distance*Math.cos(radAngle))+rightCenter.x; rightPoint.y = (int) (-distance*Math.sin(radAngle))+rightCenter.y; } else { rightPoint.x = (int) event.getX(rightPoint.getPointerIndex()); rightPoint.y = (int) event.getY(rightPoint.getPointerIndex()); } rightDistance=distance; rightAngle=angle; } if(leftPoint.isCanMove() && leftPoint.getPointerIndex()!=-1 && leftPoint.getPointerIndex()<event.getPointerCount()) { x2=event.getX(leftPoint.getPointerIndex())-leftCenter.x; y2=event.getY(leftPoint.getPointerIndex())-leftCenter.y; angle2 = (Math.atan2( x2, y2 )*radToDeg)-90; distance2 = Math.sqrt((x2*x2)+(y2*y2)); if( distance2 >= stopRadius ) { distance2 = stopRadius; double radAngle = angle2*degToRad; leftPoint.x = (int) (distance2*Math.cos(radAngle))+leftCenter.x; leftPoint.y = (int) (-distance2*Math.sin(radAngle))+leftCenter.y; } else { leftPoint.x = (int) event.getX(leftPoint.getPointerIndex()); leftPoint.y = (int) event.getY(leftPoint.getPointerIndex()); } leftDistance=distance2; leftAngle=angle2; } } break; } invalidate(); return true; } public double getRightDistance() { return rightDistance; } public double getRightAngle() { return rightAngle; } public double getLeftAngle() { return leftAngle; } public double getLeftDistance() { return leftDistance; } /** * 自定義坐標(biāo)點(diǎn),添加了兩個(gè)屬性 */ public class MyPoint extends Point{ //手指的index private int pointerIndex=-1; //是否能移動(dòng) private boolean isCanMove; public boolean isCanMove() { return isCanMove; } public void setCanMove(boolean canMove) { isCanMove = canMove; } public MyPoint(int x, int y) { super(x, y); } public int getPointerIndex() { return pointerIndex; } public void setPointerIndex(int pointerIndex) { this.pointerIndex = pointerIndex; } } }
在我的真正項(xiàng)目中對(duì)內(nèi)存性能要求比較高,所有我并沒(méi)有直接用繼承ImageView,而是使用了SurfaceView,雙緩沖,單獨(dú)線程刷新畫面,還有局部刷新,基本上跟上面的差不多,只是將onDraw()里面的刷新代碼放到SurfaceView中,網(wǎng)上也有很多SurfaceView使用的例子,稍微借鑒一下就能轉(zhuǎn)過(guò)來(lái)。
讀到這里,這篇“android怎么模擬實(shí)現(xiàn)航拍遙控”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識(shí)點(diǎn)還需要大家自己動(dòng)手實(shí)踐使用過(guò)才能領(lǐng)會(huì),如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。