这个控件是通过SurfaceView每次重绘 并用 三角正切函数计算坐标位置 并记录控件运动轨迹方向 其中应该注意 个别方向的坐标计算 时间关系只做了 顺时针方向 逆时针时请参照更改
直接上源码
public class MainActivity extends Activity implements Runnable, SurfaceHolder.Callback { private SurfaceView sfv; private SurfaceHolder holder; private Thread thread; private Paint paint; private int screenWidth; private int screenHeight; private String myText = "adasd"; private Rect myBounds; private int angle; private float positionY = 30f; //控件高度 private float positionX = 0f; private Status myStatus; private float sX;//x反弹记录点 private float sY;//同上 private double tempTan;//保存正切值 提速计算 public enum Status { LEFT_UP, UP, RIGHT_UP, RIGHT, RIGHT_DOWN, DOWN, LEFT_DOWN, LEFT } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sfv = ((SurfaceView) findViewById(R.id.sfv)); holder = sfv.getHolder(); holder.addCallback(this); thread = new Thread(this); angle =30; myStatus = RIGHT_DOWN; myBounds = new Rect(); } @Override public void surfaceCreated(SurfaceHolder holder) { paint = new Paint(); paint.setColor(Color.RED); paint.setTextSize(40); paint.getTextBounds(myText, 0, myText.length(), myBounds); thread.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { screenWidth=width; screenHeight=height; } @Override public void surfaceDestroyed(SurfaceHolder holder) { thread.interrupt(); } @Override public void run() { while (true) { Canvas canvas = null; try { synchronized (holder) { canvas = holder.lockCanvas(); canvas.drawColor(Color.WHITE); // if(myStatus== DOWN&&y==getResources().getDisplayMetrics().heightPixels-30){ // canvas.drawText("asdasd", x=(float)(y* (Math.tan(Math.PI/180*(90-10)))),y++, paint); //myStatus= UP; // } //else // { // canvas.drawText("asdasd", x=(float)(y* (Math.tan(Math.PI/180*10))),y++, paint); // } switch (myStatus) { case RIGHT_DOWN: canvas.drawText(myText, positionX = sX+ (float) ((positionY-myBounds.height()) * (Math.tan(Math.PI / 180 * (angle)))), positionY++, paint); /* * 第一轨迹运动 xy轴增量成正比 * */ if (positionY >= screenHeight ) { myStatus = RIGHT_UP; sX = positionX; angle=90-angle; } if (positionX >= screenWidth - myBounds.width()) { myStatus = LEFT_DOWN;//撞墙转向 sX=positionX;//记录位置 sY=positionY;//同上 angle=90-angle;//转角 可以换角计算 不做这一步 tempTan=Math.tan(Math.PI / 180 * ( angle));//保存去正切值 } break; case RIGHT_UP: canvas.drawText(myText, positionX =(float) (((sY-myBounds.height())*tempTan) - ((positionY-myBounds.height()) * (tempTan))), positionY--, paint); // canvas.drawText(myText, positionX = 2* sX - timesX*(float) ((positionY-myBounds.height()) / (Math.tan(Math.PI / 180 * ( angle)))), positionY--, paint); if (positionX >= screenWidth - myBounds.width()) { myStatus = LEFT_UP; } if (positionY <= myBounds.height()) { myStatus = RIGHT_DOWN; sX=positionX; } break; case LEFT_DOWN: canvas.drawText(myText,positionX = (float)((screenWidth-((screenHeight-sY)/tempTan))-myBounds.width()+((screenHeight-positionY)/tempTan)), positionY++, paint); if (positionX <= 0) { myStatus = RIGHT_DOWN; } if (positionY >= screenHeight ) { myStatus = LEFT_UP; sX=positionX; tempTan=Math.tan(Math.PI / 180 * (angle)); } break; case LEFT_UP: canvas.drawText(myText, positionX = (float) ((positionY-(screenHeight-(tempTan*sX)))/tempTan), positionY--, paint); if (positionY <= 0) { myStatus = LEFT_DOWN; } if (positionX <= 0) { myStatus = RIGHT_UP; sX = 0; sY=positionY; angle=90-angle; tempTan=(Math.tan(Math.PI / 180 * ( angle))); } break; } Thread.sleep(1); } } catch (InterruptedException e) { e.printStackTrace(); } finally { if (canvas != null) holder.unlockCanvasAndPost(canvas); } } }}