Name: Password: Sign in
Android Canvas 的力学仿真(实验) 中的文章

本文在 署名-非商业性使用-相同方式共享 3.0 版权协议下发布, 转载请注明出自 kyleslight.net

Android Canvas 的绘图准备

这个系列的文章是关于在 Android 设备上进行力学仿真实验,与毕设项目同步,它随时记录了实验其间的一些想法与实践。

注意,这不是一篇 Tutorial,可能会包含非常多 Bad practice 、混乱的编排甚至错误的尝试。因而可能无法给大家提供有效的信息,希望大家能够谅解。当然如果你有更好的想法望帮助指出:)

这是第一次准备实验,主要用来创建 Android 的 Canvas 的绘图环境与按照自己想法绘图的可能性;它实验了在一段区域内的点以及在其上(伪)轨迹的绘制。

1 PointActivity

首先是创建一个 Activity,没什么好说的,它调用了 PointView 作为主要呈现的视图。

// in PointActivity

public class PointActivity extends Activity {
    PointView pointView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        pointView = new PointView(this);
        setContentView(pointView);
    }

    @Override
    protected void onPause() {
        super.onPause();
        pointView.pause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        pointView.resume();
    }
}

2 PointView

PointView 继承自 SurfaceView,这样它可以利用第二个线程来绘图,绘图逻辑与视图的逻辑之间不冲突,当 PointView 中的状态更新的时候会实现重绘。

// in PointView

public class PointView extends SurfaceView implements Runnable {
    Points somePoints;
    Thread t;
    SurfaceHolder holder;
    boolean isCanDraw = false;

    public PointView(Context context) {
        super(context);
        holder = getHolder();
    }

    public PointView(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        somePoints = new Points(w, h);
    }

    @Override
    public void run() {
        while (isCanDraw) {
            if (!holder.getSurface().isValid()) continue;

            Canvas canvas = holder.lockCanvas();

            // Draw logic

            somePoints.draw(canvas);
            holder.unlockCanvasAndPost(canvas);
        }
    }

    public void pause() {
        isCanDraw = false;
        while (true) {
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            break;
        }
        t = null;
    }

    public void resume() {
        isCanDraw = true;
        t = new Thread(this);
        t.start();
    }
}

3 Points

Ponits 是绘图的主逻辑,它包含有各种信息,以及全局坐标转换,元素处理与绘图。

// in Points

public class Points {
    ArrayList<Point> _points;
    float viewWidth, viewHeight;
    final float lineLength = 20;
    final float RADIUS = 3;
    final float grid = 20;
    public Points(float width, float height) {
        viewWidth = width;
        viewHeight = height;
        _points = new ArrayList<>();
        for (int i = -20; i < 20; i++) {
            for (int j = -10; j < 10; j++) {
                _points.add(new Point(i * grid, j * grid));
            }
        }
    }

    public void draw(Canvas canvas) {
        for (int i = 0; i < _points.size(); i++) {
            Paint paint = new Paint();
            paint.setStyle(Paint.Style.FILL);
            float slope = _points.get(i).getSlope();
            Point tempPoint = standardPoint(_points.get(i));
            float tempX = tempPoint.get_x();
            float tempY = tempPoint.get_y();

            canvas.drawCircle(tempX, tempY, RADIUS, paint);
            float startX = tempX - lineLength;
            float startY = tempY + lineLength * slope;
            float stopX = tempX + lineLength;
            float stopY = tempY - lineLength * slope;
            paint.setColor(Color.RED);
            canvas.drawLine(startX, startY, stopX, stopY, paint);
        }
    }

    private Point standardPoint(Point p) {
        float standardX = viewWidth/2 + p.get_x();
        float standardY = viewHeight/2 - p.get_y();
        return new Point(standardX, standardY);
    }
}

4 Point

Point 提供每个点所包含的信息。

// in Point

public class Point {
    private float _x, _y;
    public Point(float x, float y) {
        _x = x;
        _y = y;
    }
    public float get_x(){
        return _x;
    }
    public float get_y(){
        return _y;
    }
    public float getSlope() {
        return (float) Math.sin(_x/400 * 3.1415 / 2);
    }
}

效果如下:

从这个结果来看(不要在意画的是什么= =),使用类似的方法是可行的:)

Copyright (c) 2014-2016 Kyles Light.
Powered by Tornado.
鄂 ICP 备 15003296 号