android 动态曲线,Android 动态绘制曲线等各种图形

Android 中动态的绘制有两种方法,一种是用OpenGL ES,它主要用来做3D图形开发,对于一般的应用,我们会采取自定义一个View,然后覆盖onDraw()的方法,下面说一下第二种方法。

基本的思路是:

1:创建一个类,继承自View(或者SurfaceView)。

2:覆盖onDraw()方法。

3:使用Canvas对象在界面上绘制不同的图形,使用invalidate()方法刷新界面

下面通过两个例子来说明

一:弹球实例

自定义一个View,代码如下:

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.os.Handler;

import android.os.Message;

import android.util.AttributeSet;

import android.view.View;

public class MyView extends View implements Runnable{

//图形当前的坐标

private int mX = 20;

private int mY = 20;

public MyView(Context context,AttributeSet attrs){

super(context,attrs);

//获取焦点

setFocusable(true);

//启动线程

new Thread(this).start();

}

@Override

public void run() {

RefreshThread mDrawHandler = new RefreshThread();

while(!Thread.currentThread().isInterrupted()){

Message msg = new Message();

msg.what = 0x101;

mDrawHandler.sendMessage(msg);

try {

Thread.sleep(500);

} catch (Exception e) {

e.printStackTrace();

}

}

}

@Override

protected void onDraw(Canvas canvas) {

//实例化画笔

Paint mPaint = new Paint();

//设置画笔颜色

mPaint.setColor(Color.RED);

//画圆

canvas.drawCircle(mX, mY, 20, mPaint);

super.onDraw(canvas);

}

class RefreshThread extends Handler{

@Override

public void handleMessage(Message msg) {

if(msg.what==0x101){

MyView.this.update();

}

super.handleMessage(msg);

}

}

/**

* 更新坐标

*/

private void update(){

int height = getHeight();

mY+=5;

if(mY>=height){

mY = 20;

}

}

}再创建一个Activity,在Activity中实例化这个自定义的View就行了,代码如下:import android.app.Activity;

import android.os.Bundle;

import com.example.views.MyView;

public class MyActivity extends Activity{

private MyView mView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

mView = new MyView(this,null);

setContentView(mView);

}

}

上面是一个非常简单的例子,下面是一个比较复杂的,主要教大家通过触屏,在界面上动态的画曲线,直接上代码:package com.example.views;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.util.ArrayList;

import java.util.Iterator;

import java.util.List;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.Path;

import android.graphics.Bitmap.CompressFormat;

import android.os.Environment;

import android.view.MotionEvent;

import android.view.View;

/**

*

* @category: View实现涂鸦、撤销以及重做功能

* @author: LuoYong

* @date: 2013-11-25

*

*/

public class TuyaView extends View {

private Bitmap mBitmap;

private Canvas mCanvas;

private Path mPath;

private Paint mBitmapPaint;// 画布的画笔

private Paint mPaint;// 真实的画笔

private float mX, mY;// 临时点坐标

private static final float TOUCH_TOLERANCE = 4;

// 保存Path路径的集合,用List集合来模拟栈

private static List savePath;

// 记录Path路径的对象

private DrawPath dp;

private int screenWidth, screenHeight;// 屏幕长宽

private class DrawPath {

public Path path;// 路径

public Paint paint;// 画笔

}

public TuyaView(Context context, int w, int h) {

super(context);

screenWidth = w;

screenHeight = h;

mBitmap = Bitmap.createBitmap(screenWidth, screenHeight,

Bitmap.Config.ARGB_8888);

// 保存一次一次绘制出来的图形

mCanvas = new Canvas(mBitmap);

mBitmapPaint = new Paint(Paint.DITHER_FLAG);

mPaint = new Paint();

mPaint.setAntiAlias(true);

mPaint.setStyle(Paint.Style.STROKE);

mPaint.setStrokeJoin(Paint.Join.ROUND);// 设置外边缘

mPaint.setStrokeCap(Paint.Cap.SQUARE);// 形状

mPaint.setStrokeWidth(8);// 画笔宽度

mPaint.setColor(0xFF2145FF);// 画笔颜色

savePath = new ArrayList();

}

@Override

public void onDraw(Canvas canvas) {

canvas.drawColor(Color.TRANSPARENT);

// 将前面已经画过得显示出来

canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

if (mPath != null) {

// 实时的显示

canvas.drawPath(mPath, mPaint);

}

}

private void touch_start(float x, float y) {

mPath.moveTo(x, y);

mX = x;

mY = y;

}

private void touch_move(float x, float y) {

float dx = Math.abs(x - mX);

float dy = Math.abs(mY - y);

if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {

// 从x1,y1到x2,y2画一条贝塞尔曲线,更平滑(直接用mPath.lineTo也是可以的)

// 由此就可以制作各种画笔

mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);

mX = x;

mY = y;

}

}

private void touch_up() {

mPath.lineTo(mX, mY);

mCanvas.drawPath(mPath, mPaint);

// 将一条完整的路径保存下来(相当于入栈操作)

savePath.add(dp);

mPath = null;// 重新置空

}

/**

* 撤销的核心思想就是将画布清空, 将保存下来的Path路径最后一个移除掉, 重新将路径画在画布上面。

*/

public void undo() {

mBitmap = Bitmap.createBitmap(screenWidth, screenHeight,

Bitmap.Config.ARGB_8888);

mCanvas.setBitmap(mBitmap);// 重新设置画布,相当于清空画布

// 清空画布,但是如果图片有背景的话,则使用上面的重新初始化的方法,用该方法会将背景清空掉...

if (savePath != null && savePath.size() > 0) {

// 移除最后一个path,相当于出栈操作

savePath.remove(savePath.size() - 1);

Iterator iter = savePath.iterator();

while (iter.hasNext()) {

DrawPath drawPath = iter.next();

mCanvas.drawPath(drawPath.path, drawPath.paint);

}

invalidate();// 刷新

/* 在这里保存图片纯粹是为了方便,保存图片进行验证 */

String fileUrl = Environment.getExternalStorageDirectory()

.toString() + "/android/data/test.png";

try {

FileOutputStream fos = new FileOutputStream(new File(fileUrl));

mBitmap.compress(CompressFormat.PNG, 100, fos);

fos.flush();

fos.close();

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

}

/**

* 重做的核心思想就是将撤销的路径保存到另外一个集合里面(栈), 然后从redo的集合里面取出最顶端对象, 画在画布上面即可。

*/

public void redo() {

// TODO

}

@Override

public boolean onTouchEvent(MotionEvent event) {

float x = event.getX();

float y = event.getY();

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

// 每次down下去重新new一个Path

mPath = new Path();

// 每一次记录的路径对象是不一样的

dp = new DrawPath();

dp.path = mPath;

dp.paint = mPaint;

touch_start(x, y);

invalidate();

break;

case MotionEvent.ACTION_MOVE:

touch_move(x, y);

invalidate();

break;

case MotionEvent.ACTION_UP:

touch_up();

invalidate();

break;

}

return true;

}

}

Activity 类:

package com.example.activity;

import com.example.views.TuyaView;

import android.app.Activity;

import android.os.Bundle;

import android.util.DisplayMetrics;

import android.view.KeyEvent;

/**

*

* @category: View实现涂鸦、撤销以及重做功能

* @author LuoYong

* @date: 2013-11-25

*

*/

public class TuyaActivity extends Activity {

private TuyaView tuyaView = null;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

DisplayMetrics dm = new DisplayMetrics();

getWindowManager().getDefaultDisplay().getMetrics(dm);

tuyaView = new TuyaView(this, dm.widthPixels, dm.heightPixels);

setContentView(tuyaView);

}

@Override

public boolean onKeyDown(int keyCode, KeyEvent event) {

if (keyCode == KeyEvent.KEYCODE_BACK) {// 返回键

//tuyaView.undo();

this.finish();

return true;

}

return super.onKeyDown(keyCode, event);

}

}

都是一些非常简单的例子,画三角形,四边形 等的原理都是一样,希望对初学者有点作用。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值