栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 移动开发 > Android

Android自定义控件实现方向盘效果

Android 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android自定义控件实现方向盘效果

在很多开发中,为了界面更加的友好,在自定义View的基础上,开发者会开发出各种各样的自定义控件来满足实际开发需要,其中有一种”方向盘”的控件在实际开发中非常常见,便于用户进行一些实际性的方向控制。

在复习参考了许多自定义控件的基础上,我实现了一个最最基本的方向盘空间,并且可以根据方向做出相应的反应。话不多说,先看看效果。

做的有点丑,大家可以看看实际原理,后期再优化具体“方向盘”.

空间下面的几行字是我为了确定方向所写的一些参数,基本思想就是在方向盘的中心确定一个坐标轴,根据中间这个小圆的和中心点的距离与方向确定所处的方向。在手离开屏幕以后,小圆回到原点。

一言不合就放代码~~~~

具体是怎么实现的呢??

来我们一起看看代码,看完一目了然。

package com.sshhsun.socketudp.utils;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class MyWheel extends View implements Runnable,View.onTouchListener {

  public MyWheel(Context context) {
    super(context);
    // TODO Auto-generated constructor stub
  }

  //先定义一些绘图要用的基本参数
  public static final int BOTTOM = 7;
  public static final int BOTTOM_LEFT = 8;
  public static final long DEFAULT_LOOP_INTERVAL = 100L;
  public static final int FRONT = 3;
  public static final int FRONT_RIGHT = 4;
  public static final int LEFT = 1;
  public static final int LEFT_FRONT = 2;
  public static final int RIGHT = 5;
  public static final int RIGHT_BOTTOM = 6;
  private final double RAD = 57.295779500000002D;
  private Paint button;
  private int buttonRadius;
  public double centerX = 0.0D;
  public double centerY = 0.0D;
  private Paint horizontalLine;
  private int joystickRadius;
  private int lastAngle = 0;
  private int lastPower = 0;
  private long loopInterval = 100L;
  private Paint mainCircle;  //整个控件的大圆,及小红点的活动范围


  //自定义的接口用于监听处理控件的触摸事件
  private onMyWheelMoveListener onmywheelMoveListener;
  private Paint secondaryCircle;//第二个内圆,小红圆超过后开始处理角度
  private Thread thread = new Thread(this);
  private Paint verticalLine;
  private int xPosition = 0;
  private int yPosition = 0;
  private static final String tag="MyWheel";

  public MyWheel(Context paramContext, AttributeSet paramAttributeSet) {
    super(paramContext, paramAttributeSet);
    initMyWheel();  //好吧,我知道MyWheel这个名字有点太随便了........
  }

  public MyWheel(Context paramContext, AttributeSet paramAttributeSet,
      int paramInt) {
    super(paramContext, paramAttributeSet, paramInt);
    initMyWheel();
  }

  //根据所处的位置得到角度
  private int getAngle() {
    if (this.xPosition > this.centerX) {
      if (this.yPosition < this.centerY) {
 int m = (int) (90.0D + 57.295779500000002D * Math
     .atan((this.yPosition - this.centerY)
  / (this.xPosition - this.centerX)));
 this.lastAngle = m;
 return m;
      }
      if (this.yPosition > this.centerY) {
 int k = 90 + (int) (57.295779500000002D * Math
     .atan((this.yPosition - this.centerY)
  / (this.xPosition - this.centerX)));
 this.lastAngle = k;
 return k;
      }
      this.lastAngle = 90;
      return 90;
    }
    if (this.xPosition < this.centerX) {
      if (this.yPosition < this.centerY) {
 int j = (int) (57.295779500000002D * Math
     .atan((this.yPosition - this.centerY)
  / (this.xPosition - this.centerX)) - 90.0D);
 this.lastAngle = j;
 return j;
      }
      if (this.yPosition > this.centerY) {
 int i = -90
     + (int) (57.295779500000002D * Math
  .atan((this.yPosition - this.centerY)
      / (this.xPosition - this.centerX)));
 this.lastAngle = i;
 return i;
      }
      this.lastAngle = -90;
      return -90;
    }
    if (this.yPosition <= this.centerY) {
      this.lastAngle = 0;
      return 0;
    }
    if (this.lastAngle < 0) {
      this.lastAngle = -180;
      return -180;
    }
    this.lastAngle = 180;
    return 180;
  }

  //根据红色圆的距离和角度得到方向
  private int getDirection() {
    int k;
    int j = 0;
    int i;
    if ((this.lastPower == 0) && (this.lastAngle == 0)) {
      k = 0;
      return k;
    }

    if (this.lastAngle <= 0)
      j = 90 + -1 * this.lastAngle;
    while (true) {
      k = 1 + (j + 22) / 45;
      if (k <= 8) {
 break;
      }

      if (this.lastAngle <= 90) {
 j = 90 - this.lastAngle;
 continue;
      }
      j = 360 - (-90 + this.lastAngle);
    }
    return k;
  }

  //得到红色圆与中心的距离
  private int getPower() {
    return (this.lastPower=(int) (100.0D * Math.sqrt((this.xPosition - this.centerX)
 * (this.xPosition - this.centerX)
 + (this.yPosition - this.centerY)
 * (this.yPosition - this.centerY)) / this.joystickRadius));
  }

  private int measure(int paramInt) {
    int i = View.MeasureSpec.getMode(paramInt);
    int j = View.MeasureSpec.getSize(paramInt);
    if (i == 0)
      return 200;
    return j;
  }


  //初始化一些基本参数
  protected void initMyWheel() {
    this.mainCircle = new Paint(1);
    this.mainCircle.setColor(Color.BLUE);
    this.mainCircle.setStrokeWidth(3.0f);
    this.mainCircle.setStyle(Paint.Style.STROKE);
    this.secondaryCircle = new Paint();
    this.secondaryCircle.setColor(-16711936);
    this.secondaryCircle.setStrokeWidth(3.0f);
    this.secondaryCircle.setStyle(Paint.Style.STROKE);
    this.verticalLine = new Paint();
    this.verticalLine.setStrokeWidth(5.0F);
    this.verticalLine.setColor(-65536);
    this.horizontalLine = new Paint();
    this.horizontalLine.setStrokeWidth(2.0F);
    this.horizontalLine.setColor(-16777216);
    this.button = new Paint(1);
    this.button.setColor(Color.RED);
    this.button.setStyle(Paint.Style.FILL);
  }

  //初始化以后绘制方向盘。
  protected void onDraw(Canvas paramCanvas) {
    this.centerX = (getWidth() / 2);
    this.centerY = (getHeight() / 2);
    paramCanvas.drawCircle((int) this.centerX, (int) this.centerY,
 this.joystickRadius, this.mainCircle);
    paramCanvas.drawCircle((int) this.centerX, (int) this.centerY,
 this.joystickRadius / 2, this.secondaryCircle);
    paramCanvas
 .drawLine((float) this.centerX, (float) this.centerY,
     (float) this.centerX,
     (float) (this.centerY - this.joystickRadius),
     this.verticalLine);
    paramCanvas.drawLine((float) (this.centerX - this.joystickRadius),
 (float) this.centerY,
 (float) (this.centerX + this.joystickRadius),
 (float) this.centerY, this.horizontalLine);
    paramCanvas
 .drawLine((float) this.centerX,
     (float) (this.centerY + this.joystickRadius),
     (float) this.centerX, (float) this.centerY,
     this.horizontalLine);
    paramCanvas.drawCircle(this.xPosition, this.yPosition,
 this.buttonRadius, this.button);
  }

  protected void onFinishInflate() {
  }

  protected void onMeasure(int paramInt1, int paramInt2) {
    int i = Math.min(measure(paramInt1), measure(paramInt2));
    setMeasuredDimension(i, i);
  }

  protected void onSizeChanged(int paramInt1, int paramInt2, int paramInt3,
      int paramInt4) {
    super.onSizeChanged(paramInt1, paramInt2, paramInt3, paramInt4);
    this.xPosition = (getWidth() / 2);
    this.yPosition = (getWidth() / 2);
    int i = Math.min(paramInt1, paramInt2);
    this.buttonRadius = (int) (0.20D * (i / 2));
    this.joystickRadius = (int) (0.75D * (i / 2));
  }

  @Override
  public boolean onTouchEvent(MotionEvent paramMotionEvent) {
    //根据手触碰的坐标决定红色小圆的位置
    this.xPosition = (int) paramMotionEvent.getX();
    this.yPosition = (int) paramMotionEvent.getY();
    double d = Math.sqrt((this.xPosition - this.centerX)
 * (this.xPosition - this.centerX)
 + (this.yPosition - this.centerY)
 * (this.yPosition - this.centerY));
    if (d > this.joystickRadius) {
      this.xPosition = (int) ((this.xPosition - this.centerX)
   * this.joystickRadius / d + this.centerX);
      this.yPosition = (int) ((this.yPosition - this.centerY)
   * this.joystickRadius / d + this.centerY);
    }
    invalidate();//再重新绘制
    if (paramMotionEvent.getAction() == 1) {
      this.xPosition = (int) this.centerX;
      this.yPosition = (int) this.centerY;
      this.thread.interrupt();
      if (this.onmywheelMoveListener != null)
 this.onmywheelMoveListener.onValueChanged(getAngle(),
     getPower());
    }
    if ((this.onmywheelMoveListener != null)
 && (paramMotionEvent.getAction() == 0)) {
      if ((this.thread != null) && (this.thread.isAlive()))
 this.thread.interrupt();
      this.thread = new Thread(this);
      this.thread.start();
      if (this.onmywheelMoveListener != null)
 //自定义接口处理触摸事件
 this.onmywheelMoveListener.onValueChanged(getAngle(),
     getPower());
    }
    return true;
  }

  @Override
  public void run() {
    while (true) {
      if (Thread.interrupted())
 return;
      post(new Runnable() {
 public void run() {
//  Log.e(tag, "运行在"+Thread.currentThread().getName()+"线程中");
   if (MyWheel.this.onmywheelMoveListener != null)
     MyWheel.this.onmywheelMoveListener.onValueChanged(
  MyWheel.this.getAngle(),
  MyWheel.this.getPower());
 }
      });
      try {
 Thread.sleep(this.loopInterval);
      } catch (InterruptedException localInterruptedException) {
      }
    }
  }
  public void setonMyWheelMoveListener(
      onMyWheelMoveListener paramOnJoystickMoveListener, long paramLong) {
    this.onmywheelMoveListener = paramOnJoystickMoveListener;
    this.loopInterval = paramLong;
  }

  public static abstract interface onMyWheelMoveListener {
    public abstract void onValueChanged(int paramInt1, int paramInt2);
  }

  @SuppressLint("ClickableViewAccessibility")
  @Override
  public boolean onTouch(View v, MotionEvent event) {
    
    return true;
  }
}

怎么用?下面我给出我的调用实例进行讲解

首先在XML文件中应用。



  

    

在一个Fragment中引用实例并处理相应监听事件。

package com.sshhsun.socketudp.fragment;

import android.content.Context;
import android.os.Bundle;
import android.os.Vibrator;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView.FindListener;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;

import com.sshhsun.socketudp.R;
import com.sshhsun.socketudp.activity.constant.Constant;
import com.sshhsun.socketudp.utils.MyWheel;
import com.sshhsun.socketudp.utils.MyWheel.OnMyWheelMoveListener;
import com.sshhsun.socketudp.utils.UDPUtil;

public class SimpleFragment extends Fragment implements View.onClickListener {

  private MyWheel mtwheel;
  private TextView notice;
  private TextView show;
  private String direction = "none";
  private SeekBar seekbar;
  private static final String tag = "SimpleFragment";
  Vibrator vibator;
  private Context context = getActivity();
  private boolean isturn = false;
  private Button stand;
  private Button sit;
  private Button standinit;
  private Button rest;
  private Button standzero;
  private UDPUtil udpUtil;
  private boolean issend = false;
  private boolean isstop = true;

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState) {
    return initView(inflater, container, savedInstanceState);
  }

  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    initData();
    initListener();
  }

  public View initView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.frag_simple, null);

    //我的方向盘控件mtwheel
    mtwheel = (MyWheel) view.findViewById(R.id.mywheel);

    //控件下面的提示信息notice,其他控件大家可以忽略.
    notice = (TextView) view.findViewById(R.id.notice);
    seekbar = (SeekBar) view.findViewById(R.id.turns);
    seekbar.setProgress(50);
    stand = (Button) view.findViewById(R.id.simple_stand);
    sit = (Button) view.findViewById(R.id.simple_sit);
    standinit = (Button) view.findViewById(R.id.simple_standinit);
    rest = (Button) view.findViewById(R.id.simple_rest);
    standzero = (Button) view.findViewById(R.id.simple_standzero);
    return view;
  }

  public void initListener() {
    sit.setonClickListener(this);
    standinit.setonClickListener(this);
    rest.setonClickListener(this);
    standzero.setonClickListener(this);
    stand.setonClickListener(this);


    //下面的监听器代码最为重要!!!!!!!!
    mtwheel.setonMyWheelMoveListener(new onMyWheelMoveListener() {

      @Override
      // paramInt1:角度
      // paramInt2:距离 根据这两个参数可以算出方向盘的方位
      public void onValueChanged(int paramInt1, int paramInt2) {
 boolean isdistance = false;
 if (paramInt2 >= 50) {
   isdistance = true;
   int temp = Math.abs(paramInt1);
   if (paramInt1 >= 0) {
     if (temp > 50 && temp < 120) {
direction = "right";
if (!issend) {
  udpUtil.UdpSend(direction, Constant.port);
  issend = true;
  isstop = false;
}
     } else if (temp < 40) {
direction = "forward";
if (!issend) {
  udpUtil.UdpSend(direction, Constant.port);
  issend = true;
  isstop = false;
}
     } else if (temp > 140) {
direction = "back";
if (!issend) {
  udpUtil.UdpSend(direction, Constant.port);
  issend = true;
  isstop = false;
}
     } else {
direction = "指向不明确";
issend = false;
     }
   } else {
     if (temp > 50 && temp < 120) {
direction = "left";
if (!issend) {
  udpUtil.UdpSend(direction, Constant.port);
  issend = true;
  isstop = false;
}
     } else if (temp < 40) {
direction = "forward";
if (!issend) {
  udpUtil.UdpSend(direction, Constant.port);
  issend = true;
  isstop = false;
}
     } else if (temp > 140) {
direction = "back";
if (!issend) {
  udpUtil.UdpSend(direction, Constant.port);
  issend = true;
  isstop = false;
}
     } else {
direction = "指向不明确";
issend = false;
     }
   }
 } else {
   isdistance = false;
   direction = "stop";
   issend = false;
 }
 notice.setText(" getAngle:" + paramInt1 + "n" + " getPower:"
     + paramInt2 + "n" + "direction:" + direction);

 if (direction.equals("stop") && (!isstop)) {
   udpUtil.UdpSend(direction, Constant.port);
   isstop = true;
 }
      }
    }, 100L);
    seekbar.setonSeekBarChangeListener(new onSeekBarChangeListener() {

      @Override
      public void onStopTrackingTouch(SeekBar seekBar) {
 seekbar.setProgress(50);
 isturn = false;
 String command = "stop";
 udpUtil.UdpSend(command, Constant.port);
      }

      @Override
      public void onStartTrackingTouch(SeekBar seekBar) {

      }

      @Override
      public void onProgressChanged(SeekBar seekBar, int progress,
   boolean fromUser) {
 int cucrrent = seekbar.getProgress();
 String command = "hello";
 if (cucrrent < 20) {
   Toast.makeText(getActivity(), "onProgressChanged" + "左转", 0)
.show();
   if (!isturn) {
     Log.e(tag, "onProgressChanged" + "左转");
     command = "turnleft";
     udpUtil.UdpSend(command, Constant.port);
     vibator.vibrate(100);
     isturn = true;
   }
 } else if (cucrrent > 80) {
   Toast.makeText(getActivity(), "onProgressChanged" + "右转", 0)
.show();
   if (!isturn) {
     Log.e(tag, "onProgressChanged" + "右转");
     command = "turnright";
     udpUtil.UdpSend(command, Constant.port);
     vibator.vibrate(100);
     isturn = true;
   }
 }
      }
    });

  }

  public void initData() {
    udpUtil = new UDPUtil(Constant.Address);
    vibator = (Vibrator) getActivity().getSystemService(
 Context.VIBRATOR_SERVICE);
    Thread.currentThread().setName(tag);
  }

  public void processClick(View v) {
    String command = "hello";
    switch (v.getId()) {
    case R.id.simple_rest:
      command = "rest";
      break;
    case R.id.simple_sit:
      command = "sit";

      break;
    case R.id.simple_stand:
      command = "stand";

      break;
    case R.id.simple_standinit:
      command = "standinit";

      break;
    case R.id.simple_standzero:
      command = "standzero";

      break;
    default:
      break;
    }
    udpUtil.UdpSend(command, Constant.port);
  }

  @Override
  public void onClick(View v) {
    processClick(v);
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    vibator.cancel();
  }
  // @Override
  // public boolean onTouch(View v, MotionEvent event) {
  // if (v.getId() == R.id.turns) {
  // String notice = "";
  // switch (event.getAction()) {
  // case MotionEvent.ACTION_DOWN:
  // notice = "ACTION_DOWN"+event.getX();
  // int process=(int) Math.floor(event.getX()+0.5);
  // seekbar.setProgress(process);
  // break;
  // case MotionEvent.ACTION_UP:
  // notice = "ACTION_UP";
  // break;
  // case MotionEvent.ACTION_CANCEL:
  // notice = "ACTION_CANCEL";
  // break;
  // default:
  // break;
  // }
  // if (!TextUtils.isEmpty(notice)) {
  // Toast.makeText(getActivity(), notice, 0).show();
  // }
  // }
  // return true;
  // }

}

声明一下:

1.上面的控件代码(第一部分代码)可以实际使用
2.第二部分代码演示了控件的使用与处理
3.关于控件的实现原理和思想在代码与注释中已经详细标记

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/154198.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号