溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

android怎么模擬實(shí)現(xiàn)航拍遙控

發(fā)布時(shí)間:2022-08-17 15:51:24 來(lái)源:億速云 閱讀:127 作者:iii 欄目:開發(fā)技術(shù)

本文小編為大家詳細(xì)介紹“android怎么模擬實(shí)現(xiàn)航拍遙控”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“android怎么模擬實(shí)現(xiàn)航拍遙控”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來(lái)學(xué)習(xí)新知識(shí)吧。

先貼圖

android怎么模擬實(shí)現(xiàn)航拍遙控

左右兩個(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è)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(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)容。

AI