android 虚拟摇杆绘制
首先附上效果图
1、自定义RockerView
package com.example.rocker; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.PointF; import android.graphics.Rect; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnPreDrawListener; public class RockerView extends View { //固定摇杆背景圆形的X,Y坐标以及半径 private float mRockerBg_X; private float mRockerBg_Y; private float mRockerBg_R; //摇杆的X,Y坐标以及摇杆的半径 private float mRockerBtn_X; private float mRockerBtn_Y; private float mRockerBtn_R; private Bitmap mBmpRockerBg; private Bitmap mBmpRockerBtn; private PointF mCenterPoint; public RockerView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub // 获取bitmap mBmpRockerBg = BitmapFactory.decodeResource(context.getResources(), R.drawable.rocker_bg); mBmpRockerBtn = BitmapFactory.decodeResource(context.getResources(), R.drawable.rocker_btn); getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { // 调用该方法时可以获取view实际的宽getWidth()和高getHeight() @Override public boolean onPreDraw() { // TODO Auto-generated method stub getViewTreeObserver().removeOnPreDrawListener(this); Log.e("RockerView", getWidth() + "/" + getHeight()); mCenterPoint = new PointF(getWidth() / 2, getHeight() / 2); mRockerBg_X = mCenterPoint.x; mRockerBg_Y = mCenterPoint.y; mRockerBtn_X = mCenterPoint.x; mRockerBtn_Y = mCenterPoint.y; float tmp_f = mBmpRockerBg.getWidth() / (float)(mBmpRockerBg.getWidth() + mBmpRockerBtn.getWidth()); mRockerBg_R = tmp_f * getWidth() / 2; mRockerBtn_R = (1.0f - tmp_f)* getWidth() / 2; return true; } }); new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub while(true){ //系统调用onDraw方法刷新画面 RockerView.this.postInvalidate(); try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }).start(); } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); canvas.drawBitmap(mBmpRockerBg, null, new Rect((int)(mRockerBg_X - mRockerBg_R), (int)(mRockerBg_Y - mRockerBg_R), (int)(mRockerBg_X + mRockerBg_R), (int)(mRockerBg_Y + mRockerBg_R)), null); canvas.drawBitmap(mBmpRockerBtn, null, new Rect((int)(mRockerBtn_X - mRockerBtn_R), (int)(mRockerBtn_Y - mRockerBtn_R), (int)(mRockerBtn_X + mRockerBtn_R), (int)(mRockerBtn_Y + mRockerBtn_R)), null); } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) { // 当触屏区域不在活动范围内 if (Math.sqrt(Math.pow((mRockerBg_X - (int) event.getX()), 2) + Math.pow((mRockerBg_Y - (int) event.getY()), 2)) >= mRockerBg_R) { //得到摇杆与触屏点所形成的角度 double tempRad = getRad(mRockerBg_X, mRockerBg_Y, event.getX(), event.getY()); //保证内部小圆运动的长度限制 getXY(mRockerBg_X, mRockerBg_Y, mRockerBg_R, tempRad); } else {//如果小球中心点小于活动区域则随着用户触屏点移动即可 mRockerBtn_X = (int) event.getX(); mRockerBtn_Y = (int) event.getY(); } if(mRockerChangeListener != null) { mRockerChangeListener.report(mRockerBtn_X - mCenterPoint.x, mRockerBtn_Y - mCenterPoint.y); } } else if (event.getAction() == MotionEvent.ACTION_UP) { //当释放按键时摇杆要恢复摇杆的位置为初始位置 mRockerBtn_X = mCenterPoint.x; mRockerBtn_Y = mCenterPoint.y; if(mRockerChangeListener != null) { mRockerChangeListener.report(0, 0); } } return true; } /*** * 得到两点之间的弧度 */ public double getRad(float px1, float py1, float px2, float py2) { //得到两点X的距离 float x = px2 - px1; //得到两点Y的距离 float y = py1 - py2; //算出斜边长 float xie = (float) Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); //得到这个角度的余弦值(通过三角函数中的定理 :邻边/斜边=角度余弦值) float cosAngle = x / xie; //通过反余弦定理获取到其角度的弧度 float rad = (float) Math.acos(cosAngle); //注意:当触屏的位置Y坐标<摇杆的Y坐标我们要取反值-0~-180 if (py2 < py1) { rad = -rad; } return rad; } /** * * @param R 圆周运动的旋转点 * @param centerX 旋转点X * @param centerY 旋转点Y * @param rad 旋转的弧度 */ public void getXY(float centerX, float centerY, float R, double rad) { //获取圆周运动的X坐标 mRockerBtn_X = (float) (R * Math.cos(rad)) + centerX; //获取圆周运动的Y坐标 mRockerBtn_Y = (float) (R * Math.sin(rad)) + centerY; } RockerChangeListener mRockerChangeListener = null; public void setRockerChangeListener(RockerChangeListener rockerChangeListener) { mRockerChangeListener = rockerChangeListener; } public interface RockerChangeListener { public void report(float x, float y); } }2、布局文件中添加RockerView
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ff4f4f4f" tools:context=".MainActivity" > <com.example.rocker.RockerView android:id="@+id/rockerView1" android:layout_width="120dp" android:layout_height="120dp" android:layout_alignParentBottom="true" android:layout_marginLeft="20dp" android:layout_marginBottom="20dp"/> <com.example.rocker.RockerView android:id="@+id/rockerView2" android:layout_width="120dp" android:layout_height="120dp" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginRight="20dp" android:layout_marginBottom="20dp"/> </RelativeLayout>
package com.example.rocker; import android.app.Activity; import android.os.Bundle; import android.util.DisplayMetrics; import android.util.Log; import android.view.View; import android.view.ViewGroup.MarginLayoutParams; import android.view.Window; import android.view.WindowManager; import android.widget.RelativeLayout; public class MainActivity extends Activity { private static final String TAG = "MainActivity"; void doLog(String log) { Log.e(TAG, log); } private RockerView rockerView1; private RockerView rockerView2; int screenWidth; int screenHeight; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);// 设置全屏 // , // 屏幕长亮 setContentView(R.layout.activity_main); DisplayMetrics dm = getResources().getDisplayMetrics(); screenWidth = dm.widthPixels; screenHeight = dm.heightPixels; rockerView1 = (RockerView) findViewById(R.id.rockerView1); rockerView2 = (RockerView) findViewById(R.id.rockerView2); rockerView1.setRockerChangeListener(new RockerView.RockerChangeListener() { @Override public void report(float x, float y) { // TODO Auto-generated method stub // doLog(x + "/" + y); setLayout(rockerView2, (int)x, (int)y); } }); rockerView2.setRockerChangeListener(new RockerView.RockerChangeListener() { @Override public void report(float x, float y) { // TODO Auto-generated method stub // doLog(x + "/" + y); setLayout(rockerView1, (int)x, (int)y); } }); } public void setLayout(View v, int dx, int dy) { int left = v.getLeft() + dx; int top = v.getTop() + dy; int right = v.getRight() + dx; int bottom = v.getBottom() + dy; if (left < 0) { left = 0; right = left + v.getWidth(); } if (right > screenWidth) { right = screenWidth; left = right - v.getWidth(); } if (top < 0) { top = 0; bottom = top + v.getHeight(); } if (bottom > screenHeight) { bottom = screenHeight; top = bottom - v.getHeight(); } v.layout(left, top, right, bottom); } }
如下是代码下载地址
http://download.csdn.net/detail/qwjun/9282127
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: Android 虚拟摇杆,多种模式回调,返回距离级别,方向,角度。
- 下一篇: android虚拟摇杆