首先附上效果图

android 虚拟摇杆绘制_第1张图片

1、自定义RockerView

[java]  view plain  copy
  1. package com.example.rocker;  
  2.   
  3. import android.content.Context;  
  4. import android.graphics.Bitmap;  
  5. import android.graphics.BitmapFactory;  
  6. import android.graphics.Canvas;  
  7. import android.graphics.PointF;  
  8. import android.graphics.Rect;  
  9. import android.util.AttributeSet;  
  10. import android.util.Log;  
  11. import android.view.MotionEvent;  
  12. import android.view.View;  
  13. import android.view.ViewTreeObserver;  
  14. import android.view.ViewTreeObserver.OnPreDrawListener;  
  15.   
  16. public class RockerView extends View {  
  17.   
  18.     //固定摇杆背景圆形的X,Y坐标以及半径  
  19.     private float mRockerBg_X;  
  20.     private float mRockerBg_Y;  
  21.     private float mRockerBg_R;  
  22.     //摇杆的X,Y坐标以及摇杆的半径  
  23.     private float mRockerBtn_X;  
  24.     private float mRockerBtn_Y;  
  25.     private float mRockerBtn_R;  
  26.     private Bitmap mBmpRockerBg;  
  27.     private Bitmap mBmpRockerBtn;  
  28.       
  29.     private PointF mCenterPoint;  
  30.       
  31.     public RockerView(Context context, AttributeSet attrs) {  
  32.         super(context, attrs);  
  33.         // TODO Auto-generated constructor stub  
  34.         // 获取bitmap  
  35.         mBmpRockerBg = BitmapFactory.decodeResource(context.getResources(), R.drawable.rocker_bg);  
  36.         mBmpRockerBtn = BitmapFactory.decodeResource(context.getResources(), R.drawable.rocker_btn);  
  37.           
  38.         getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {  
  39.               
  40.             // 调用该方法时可以获取view实际的宽getWidth()和高getHeight()  
  41.             @Override  
  42.             public boolean onPreDraw() {  
  43.                 // TODO Auto-generated method stub  
  44.                 getViewTreeObserver().removeOnPreDrawListener(this);   
  45.                   
  46.                 Log.e("RockerView", getWidth() + "/" +  getHeight());  
  47.                 mCenterPoint = new PointF(getWidth() / 2, getHeight() / 2);  
  48.                 mRockerBg_X = mCenterPoint.x;  
  49.                 mRockerBg_Y = mCenterPoint.y;  
  50.                   
  51.                 mRockerBtn_X = mCenterPoint.x;  
  52.                 mRockerBtn_Y = mCenterPoint.y;  
  53.                   
  54.                 float tmp_f = mBmpRockerBg.getWidth() / (float)(mBmpRockerBg.getWidth() + mBmpRockerBtn.getWidth());  
  55.                 mRockerBg_R = tmp_f * getWidth() / 2;  
  56.                 mRockerBtn_R = (1.0f - tmp_f)* getWidth() / 2;  
  57.                   
  58.                 return true;  
  59.             }  
  60.         });  
  61.       
  62.           
  63.         new Thread(new Runnable() {  
  64.               
  65.             @Override  
  66.             public void run() {  
  67.                 // TODO Auto-generated method stub  
  68.                 while(true){  
  69.                       
  70.                     //系统调用onDraw方法刷新画面  
  71.                     RockerView.this.postInvalidate();  
  72.                       
  73.                     try {  
  74.                         Thread.sleep(100);  
  75.                     } catch (InterruptedException e) {  
  76.                         // TODO Auto-generated catch block  
  77.                         e.printStackTrace();  
  78.                     }  
  79.                 }  
  80.             }  
  81.         }).start();  
  82.     }  
  83.       
  84.     @Override  
  85.     protected void onDraw(Canvas canvas) {  
  86.         // TODO Auto-generated method stub  
  87.         super.onDraw(canvas);  
  88.         canvas.drawBitmap(mBmpRockerBg, null,   
  89.                 new Rect((int)(mRockerBg_X - mRockerBg_R),   
  90.                         (int)(mRockerBg_Y - mRockerBg_R),   
  91.                         (int)(mRockerBg_X + mRockerBg_R),   
  92.                         (int)(mRockerBg_Y + mRockerBg_R)),   
  93.                 null);  
  94.         canvas.drawBitmap(mBmpRockerBtn, null,   
  95.                 new Rect((int)(mRockerBtn_X - mRockerBtn_R),   
  96.                         (int)(mRockerBtn_Y - mRockerBtn_R),   
  97.                         (int)(mRockerBtn_X + mRockerBtn_R),   
  98.                         (int)(mRockerBtn_Y + mRockerBtn_R)),   
  99.                 null);  
  100.     }  
  101.       
  102.     @Override  
  103.     public boolean onTouchEvent(MotionEvent event) {  
  104.         // TODO Auto-generated method stub  
  105.         if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) {  
  106.             // 当触屏区域不在活动范围内  
  107.             if (Math.sqrt(Math.pow((mRockerBg_X - (int) event.getX()), 2) + Math.pow((mRockerBg_Y - (int) event.getY()), 2)) >= mRockerBg_R) {  
  108.                 //得到摇杆与触屏点所形成的角度  
  109.                 double tempRad = getRad(mRockerBg_X, mRockerBg_Y, event.getX(), event.getY());  
  110.                 //保证内部小圆运动的长度限制  
  111.                 getXY(mRockerBg_X, mRockerBg_Y, mRockerBg_R, tempRad);  
  112.             } else {//如果小球中心点小于活动区域则随着用户触屏点移动即可  
  113.                 mRockerBtn_X = (int) event.getX();  
  114.                 mRockerBtn_Y = (int) event.getY();  
  115.             }  
  116.             if(mRockerChangeListener != null) {  
  117.                 mRockerChangeListener.report(mRockerBtn_X - mCenterPoint.x, mRockerBtn_Y - mCenterPoint.y);  
  118.             }  
  119.         } else if (event.getAction() == MotionEvent.ACTION_UP) {  
  120.             //当释放按键时摇杆要恢复摇杆的位置为初始位置  
  121.             mRockerBtn_X = mCenterPoint.x;  
  122.             mRockerBtn_Y = mCenterPoint.y;  
  123.             if(mRockerChangeListener != null) {  
  124.                 mRockerChangeListener.report(00);  
  125.             }  
  126.         }  
  127.         return true;  
  128.     }  
  129.       
  130.     /*** 
  131.      * 得到两点之间的弧度 
  132.      */  
  133.     public double getRad(float px1, float py1, float px2, float py2) {  
  134.         //得到两点X的距离  
  135.         float x = px2 - px1;  
  136.         //得到两点Y的距离  
  137.         float y = py1 - py2;  
  138.         //算出斜边长  
  139.         float xie = (float) Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));  
  140.         //得到这个角度的余弦值(通过三角函数中的定理 :邻边/斜边=角度余弦值)  
  141.         float cosAngle = x / xie;  
  142.         //通过反余弦定理获取到其角度的弧度  
  143.         float rad = (float) Math.acos(cosAngle);  
  144.         //注意:当触屏的位置Y坐标<摇杆的Y坐标我们要取反值-0~-180  
  145.         if (py2 < py1) {  
  146.             rad = -rad;  
  147.         }  
  148.         return rad;  
  149.     }  
  150.       
  151.     /** 
  152.      *  
  153.      * @param R  圆周运动的旋转点 
  154.      * @param centerX 旋转点X 
  155.      * @param centerY 旋转点Y 
  156.      * @param rad 旋转的弧度 
  157.      */  
  158.     public void getXY(float centerX, float centerY, float R, double rad) {  
  159.         //获取圆周运动的X坐标   
  160.         mRockerBtn_X = (float) (R * Math.cos(rad)) + centerX;  
  161.         //获取圆周运动的Y坐标  
  162.         mRockerBtn_Y = (float) (R * Math.sin(rad)) + centerY;  
  163.     }  
  164.       
  165.     RockerChangeListener mRockerChangeListener = null;  
  166.     public void setRockerChangeListener(RockerChangeListener rockerChangeListener) {  
  167.         mRockerChangeListener = rockerChangeListener;  
  168.     }  
  169.     public interface RockerChangeListener {  
  170.         public void report(float x, float y);  
  171.     }  
  172. }  
2、布局文件中添加RockerView

[html]  view plain  copy
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:background="#ff4f4f4f"  
  6.     tools:context=".MainActivity" >  
  7.   
  8.     <com.example.rocker.RockerView   
  9.         android:id="@+id/rockerView1"  
  10.         android:layout_width="120dp"  
  11.         android:layout_height="120dp"  
  12.         android:layout_alignParentBottom="true"  
  13.         android:layout_marginLeft="20dp"  
  14.         android:layout_marginBottom="20dp"/>  
  15.       
  16.     <com.example.rocker.RockerView   
  17.         android:id="@+id/rockerView2"  
  18.         android:layout_width="120dp"  
  19.         android:layout_height="120dp"  
  20.         android:layout_alignParentBottom="true"  
  21.         android:layout_alignParentRight="true"  
  22.         android:layout_marginRight="20dp"  
  23.         android:layout_marginBottom="20dp"/>  
  24.   
  25. RelativeLayout>  


3、MainActiviy中使用RockerView

[java]  view plain  copy
  1. package com.example.rocker;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.util.DisplayMetrics;  
  6. import android.util.Log;  
  7. import android.view.View;  
  8. import android.view.ViewGroup.MarginLayoutParams;  
  9. import android.view.Window;  
  10. import android.view.WindowManager;  
  11. import android.widget.RelativeLayout;  
  12.   
  13. public class MainActivity extends Activity {  
  14.   
  15.     private static final String TAG = "MainActivity";  
  16.   
  17.     void doLog(String log) {  
  18.         Log.e(TAG, log);  
  19.     }  
  20.   
  21.     private RockerView rockerView1;  
  22.     private RockerView rockerView2;  
  23.     int screenWidth;  
  24.     int screenHeight;  
  25.   
  26.     @Override  
  27.     protected void onCreate(Bundle savedInstanceState) {  
  28.         super.onCreate(savedInstanceState);  
  29.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  30.         getWindow().setFlags(  
  31.                 WindowManager.LayoutParams.FLAG_FULLSCREEN  
  32.                         | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,  
  33.                 WindowManager.LayoutParams.FLAG_FULLSCREEN  
  34.                         | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);// 设置全屏  
  35.                                                                             // ,  
  36.                                                                             // 屏幕长亮  
  37.         setContentView(R.layout.activity_main);  
  38.   
  39.         DisplayMetrics dm = getResources().getDisplayMetrics();  
  40.         screenWidth = dm.widthPixels;  
  41.         screenHeight = dm.heightPixels;  
  42.   
  43.         rockerView1 = (RockerView) findViewById(R.id.rockerView1);  
  44.         rockerView2 = (RockerView) findViewById(R.id.rockerView2);  
  45.   
  46.         rockerView1.setRockerChangeListener(new RockerView.RockerChangeListener() {  
  47.   
  48.                     @Override  
  49.                     public void report(float x, float y) {  
  50.                         // TODO Auto-generated method stub  
  51.                         // doLog(x + "/" + y);  
  52.                         setLayout(rockerView2, (int)x, (int)y);  
  53.                     }  
  54.                 });  
  55.   
  56.         rockerView2.setRockerChangeListener(new RockerView.RockerChangeListener() {  
  57.   
  58.                     @Override  
  59.                     public void report(float x, float y) {  
  60.                         // TODO Auto-generated method stub  
  61.                         // doLog(x + "/" + y);  
  62.                         setLayout(rockerView1, (int)x, (int)y);  
  63.                     }  
  64.                 });  
  65.     }  
  66.   
  67.     public void setLayout(View v, int dx, int dy) {  
  68.         int left = v.getLeft() + dx;  
  69.         int top = v.getTop() + dy;  
  70.         int right = v.getRight() + dx;  
  71.         int bottom = v.getBottom() + dy;  
  72.         if (left < 0) {  
  73.             left = 0;  
  74.             right = left + v.getWidth();  
  75.         }  
  76.         if (right > screenWidth) {  
  77.             right = screenWidth;  
  78.             left = right - v.getWidth();  
  79.         }  
  80.         if (top < 0) {  
  81.             top = 0;  
  82.             bottom = top + v.getHeight();  
  83.         }  
  84.         if (bottom > screenHeight) {  
  85.             bottom = screenHeight;  
  86.             top = bottom - v.getHeight();  
  87.         }  
  88.         v.layout(left, top, right, bottom);  
  89.     }  
  90. }  

如下是代码下载地址

http://download.csdn.net/detail/qwjun/9282127

更多相关文章

  1. Android获取GPS坐标:
  2. Android获取基站坐标代码
  3. Android GPS坐标距离计算
  4. android 坐标布局 AbsoluteLayout
  5. Android 屏幕(View)坐标系统
  6. 2011.07.20——— android 获得当前view在屏幕的坐标
  7. Android 根据坐标获取地址
  8. Android坐标系分析

随机推荐

  1. Android显示图片避免OOM和ANR小结
  2. Android软键盘的显示方式
  3. Android(安卓)Webview js或css 替换 注入
  4. Android 启动栈管理方式 (一)
  5. android中的Binder(android内核学习记录)
  6. 如何高效地输出iOS和Android标注和切图
  7. Android增量升级的方法和原理
  8. Android智能手机恶意程序半年增加14.1倍
  9. android scroller overscroller用法
  10. SQLite3命令行使用查询android的telephon