android 虚拟摇杆绘制

首先附上效果图

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

你可能感兴趣的:(android)