android模拟实现航拍遥控

本文实例为大家分享了android模拟实现航拍遥控的具体代码,供大家参考,具体内容如下

由于最近做一个航拍项目,手机端模拟遥控,控制无人机,之前在网上这方面的知识比较少,所有就贴出来demo供大家参考,废话少说,先贴图

左右两个点,在圈内活动,一个是控制油门,一个是控制方向,放手后会返回中心点,这些在游戏场景中经常看到,比如射击类的游戏,这里自定义view,继承ImageView,难点就在手指控制这部分,以下是源码。

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;//左边中点的坐标     Point rightCenter;//右边中点的坐标     /********************右边的底图**************************/     Bitmap btm_bg;     Rect rectSrc_bg;     Rect rectDst_bg;     /********************左边的底图**************************/     Bitmap btm_bar;     Rect rectSrc_bar;     Rect rectDst_bar;     /********************左边的圆点**************************/     Bitmap btm_circle_left;     MyPoint leftPoint;     double leftDistance;//距离中心点的距离     double leftAngle;//atan2的角度值     int leftCircle_2;//圆的一半     /********************右边的圆点**************************/     Bitmap btm_circle_right;     MyPoint rightPoint;     double rightDistance;//距离中心点的距离     double rightAngle;//atan2的角度值     int rightCircle_2;//圆的一半     int stopRadius;//圆的半径,左右的半径是一样的     Matrix matrix;//矩阵,同过改变矩阵来改变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;         //左边中心点的位置设为         leftCenter=new Point();         leftCenter.set(mDisplayWidth_4,mDisplayHeight_2);         //右边中心点的位置设为         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         );         /***********************左边的圆点位置***************************/         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         );         /***********************右边边的圆点位置***************************/         rightPoint=new MyPoint(rightCenter.x,rightCenter.y);         //半径为底图的一半,这里决定了可移动圆的大小         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);         //更新的左中心点的位置         matrix.reset();         matrix.postTranslate(leftPoint.x-leftCircle_2,leftPoint.y-leftCircle_2);         canvas.drawBitmap(btm_circle_left,matrix,null);        //更新的右中心点的位置         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;//圆点离中心点的距离         double angle;//圆点tan2的角度         float x2;         float y2;         double angle2;         double distance2;         switch (MotionEvent.ACTION_MASK & event.getAction())         {             case MotionEvent.ACTION_DOWN:                 //判断第一个手指按下的位置所在的区域                 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;                 //根据手指离开的id判断是开了的是哪个移动的点                 if(rightPoint.isCanMove() && rightPoint.getPointerIndex()==pointerId){                     rightPoint.setCanMove(false);                     //手指离开让圆点返回中心点                     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:                 //如果是单指移动                 if(event.getPointerCount()==1) {                     if (rightPoint.isCanMove()) {                         x=event.getX(0)-rightCenter.x;                         y=event.getY(0)-rightCenter.y;                         //计算角度,atan2的用法自己百度咯                         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(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                 {  //双指移动                     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;     }     /**      * 自定义坐标点,添加了两个属性      */     public class MyPoint extends Point{         //手指的index         private int pointerIndex=-1;         //是否能移动         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;         }     } }

在我的真正项目中对内存性能要求比较高,所有我并没有直接用继承ImageView,而是使用了SurfaceView,双缓冲,单独线程刷新画面,还有局部刷新,基本上跟上面的差不多,只是将onDraw()里面的刷新代码放到SurfaceView中,网上也有很多SurfaceView使用的例子,稍微借鉴一下就能转过来。

推荐阅读