新建一个类。举例为MySurfaceView
package com.example.blt; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.PorterDuff.Mode; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.SurfaceHolder.Callback; public class MySurfaceView extends SurfaceView implements Callback { private SurfaceHolder sfh; private Canvas canvas; private Paint paint; private int coordinate; // 固定摇杆背景圆形的半径 private int RockerCircleR, SmallRockerCircleR; // 摇杆的X,Y坐标以及摇杆的半径 private float SmallRockerCircleX, SmallRockerCircleY; private RudderListener listener = null; // 事件回调接口 public MySurfaceView(Context context) { super(context); } public MySurfaceView(Context context, AttributeSet as) { super(context, as); this.setKeepScreenOn(true); sfh = getHolder(); sfh.addCallback(this); paint = new Paint(); paint.setColor(Color.GREEN); paint.setAntiAlias(true);// 抗锯齿 setFocusable(true); setFocusableInTouchMode(true); setZOrderOnTop(true); sfh.setFormat(PixelFormat.TRANSPARENT);// 设置背景透明 } public void surfaceCreated(SurfaceHolder holder) { // 获得控件最小值 int little = this.getWidth() < this.getHeight() ? this.getWidth() : this.getHeight(); // 根据屏幕大小绘制 SmallRockerCircleX = SmallRockerCircleY = coordinate = little / 2; // 固定摇杆背景圆形的半径 RockerCircleR = (int) (little * 0.35); // 摇杆的半径 SmallRockerCircleR = (int) (little * 0.15); draw(); } /*** * 得到两点之间的弧度 */ 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; } @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) { // 当触屏区域不在活动范围内 if (Math.sqrt(Math.pow((coordinate - (int) event.getX()), 2) + Math.pow((coordinate - (int) event.getY()), 2)) >= RockerCircleR) { // 得到摇杆与触屏点所形成的角度 double tempRad = getRad(coordinate, coordinate, event.getX(), event.getY()); // 保证内部小圆运动的长度限制 getXY(coordinate, coordinate, RockerCircleR, tempRad); } else {// 如果小球中心点小于活动区域则随着用户触屏点移动即可 SmallRockerCircleX = (int) event.getX(); SmallRockerCircleY = (int) event.getY(); } } else if (event.getAction() == MotionEvent.ACTION_UP) { // 当释放按键时摇杆要恢复摇杆的位置为初始位置 SmallRockerCircleX = coordinate; SmallRockerCircleY = coordinate; } draw(); if (listener != null) { listener.onSteeringWheelChanged((SmallRockerCircleX - coordinate) / RockerCircleR, (coordinate - SmallRockerCircleY) / RockerCircleR); } return true; } /** * * @param R * 圆周运动的旋转点 * @param centerX * 旋转点X * @param centerY * 旋转点Y * @param rad * 旋转的弧度 */ public void getXY(float centerX, float centerY, float R, double rad) { // 获取圆周运动的X坐标 SmallRockerCircleX = (float) (R * Math.cos(rad)) + centerX; // 获取圆周运动的Y坐标 SmallRockerCircleY = (float) (R * Math.sin(rad)) + centerY; } public void draw() { try { canvas = sfh.lockCanvas(); // canvas.drawColor(Color.WHITE); canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);// 清除屏幕 // 设置透明度 paint.setColor(Color.CYAN); // 绘制摇杆背景 canvas.drawCircle(coordinate, coordinate, RockerCircleR, paint); paint.setColor(Color.RED); // 绘制摇杆 canvas.drawCircle(SmallRockerCircleX, SmallRockerCircleY, SmallRockerCircleR, paint); } catch (Exception e) { // TODO: handle exception } finally { try { if (canvas != null) sfh.unlockCanvasAndPost(canvas); } catch (Exception e2) { } } } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } public void surfaceDestroyed(SurfaceHolder holder) { } // 设置回调接口 public void setRudderListener(RudderListener rockerListener) { listener = rockerListener; } // 回调接口 public interface RudderListener { void onSteeringWheelChanged(float cross, float longitudinal); } }
主窗体中
package com.example.blt; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class ControlActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_control); MySurfaceView temp = (MySurfaceView) findViewById(R.id.rudder); temp.setRudderListener(new MySurfaceView.RudderListener() { @Override public void onSteeringWheelChanged(float cross, float longitudinal) { // TODO Auto-generated method stub Log.v("change", "c" + cross + "l" + longitudinal); ((TextView) findViewById(R.id.textView2)).setText("c:" + cross + "l:" + longitudinal); } }); ((Button) findViewById(R.id.button2)) .setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. // getMenuInflater().inflate(R.menu.control, menu); return false; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
----------------------主窗体XML
<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="#ffffff" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" > <GridLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:columnCount="3" > <com.example.blt.MySurfaceView android:id="@+id/rudder" android:layout_width="150dp" android:layout_height="150dp" android:layout_column="0" android:layout_gravity="left|bottom" /> <TextView android:id="@+id/textView2" android:layout_column="1" android:layout_gravity="left|top" android:text="TextView" /> <TableLayout android:layout_column="2" android:layout_gravity="bottom" android:layout_row="0" > <TableRow android:id="@+id/tableRow1" android:layout_width="wrap_content" android:layout_height="wrap_content" > <TextView android:id="@+id/axis_x" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" /> </TableRow> <TableRow android:id="@+id/tableRow2" android:layout_width="wrap_content" android:layout_height="wrap_content" > <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="自动" /> <Button android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" /> </TableRow> <TableRow android:id="@+id/tableRow3" android:layout_width="wrap_content" android:layout_height="wrap_content" > <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" /> <Button android:id="@+id/button4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" /> </TableRow> <TableRow android:id="@+id/tableRow4" android:layout_width="wrap_content" android:layout_height="wrap_content" > <Button android:id="@+id/button5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" /> <Button android:id="@+id/button6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" /> </TableRow> </TableLayout> </GridLayout> </RelativeLayout>
------------------------------应用到自定义控件