• android_SurfaceView 画图


    有这样一种view类,可以让人在其上面画动画,画图片,它的全名叫做surfaceview。名称就包含两层意思,一层是surface,一层是view。前一层提供一个面可以让人画画,后一层是个view,可以将画画显示出来。

    一般view类也有个draw方法,但是不能用来画画。上网找了很多资料,说的啰嗦,都没有说明白。我总结了下,其实网上说的意思是,主线程,也就是跑activity活动的线程,它要先在界面把几个view显示出来(也就是绘出来),而且是后,然后与用户交互。如果在几个普通view画画的话,如果画画时间很长的话,你想,activity就一直在画画,都不理用户的,谁吃得消,所以就出现surfaceView。这个玩意儿就是activity用一个holder来控制,activity一边与用户交互,一边用holder在上面画画,两者都不耽误。

    引用网上一句话:

    SurfaceView它用于显示,SurfaceHolder就是用于用来管理这个显示的SurfaceView对象的,但在SurfaceHolder是怎么样去管理这个对象的呢?这就用到了SurfceHolder.addCallback()方法添加一个SurfaceHolder接口的内部接口的三个抽象方法用于管理或者说是用于监听SurfaceView。这样就达到了管理SurfaceView的目的。

    主文件

    package cn.com.sxp;

    import android.app.Activity;
    import android.os.Bundle;

    public class SurfaceViewActivity extends Activity {
    private sxpView sv= null;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    sv =(cn.com.sxp.sxpView)findViewById(R.id.sxpView);
    }
    }

    以前用自带的控件用多了,都习惯写上(Button)find....其实也可以自己定义控件,将xml文件布局控件与程序控件联系起来,只是要写上自定义控件的全路径。

    surfaceView文件

    package cn.com.sxp;

    import java.util.Vector;

    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Paint.Style;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;

    public class sxpView extends SurfaceView implements SurfaceHolder.Callback {
    // 实现SurfaceHolder.Callback接口,到时候surfaceView被创建、销毁什么的,都会调用这个接口的回调方法.
    // A client may implement this interface to receive information about changes to the surface. When used with a SurfaceView, the Surface being held is only
    // available between calls to surfaceCreated(SurfaceHolder) and surfaceDestroyed(SurfaceHolder). The Callback is set with SurfaceHolder.addCallback method.
    // 每个surfaceView都要有surfaceHolder这么个组件,这个组件用来控制和访问surfaceView
    private SurfaceHolder sh = null; // 专门用于控制surfaceView的
    private Vector<Float> xAxis = new Vector<Float>();
    private Vector<Float> yAxis = new Vector<Float>();

    // XML文件解析需要调用View的构造函数View(Context , AttributeSet)因此自定义SurfaceView中也需要该构造函数
    public sxpView(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO Auto-generated constructor stub
    // 是surfaceView的一个方法. Return the SurfaceHolder providing access and control over this SurfaceView's underlying surface.
    sh = getHolder();
    // Add a Callback interface for this holder. There can several Callback interfaces associated with a holder.
    // addCallback方法就是指定了surfaceChanged等方法称为回调函数; 而所谓的实现SurfaceHolder.Callback接口就是让你实现surfaceChanged等接口
    sh.addCallback(this);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
    int height) {
    // TODO Auto-generated method stub

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    // TODO Auto-generated method stub
    new Thread(new sxpLoop()).start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    // TODO Auto-generated method stub

    }

    public void doDraw(Canvas canvas) {
    // TODO Auto-generated method stub
    super.onDraw(canvas);
    canvas.drawColor(Color.GRAY);// 这里是绘制背景
    Paint p = new Paint(); // 笔触
    p.setAntiAlias(true); // 反锯齿
    p.setColor(Color.BLUE);
    p.setStyle(Style.STROKE);
    for (int i = 0; i < xAxis.size(); i++)
    canvas.drawCircle(xAxis.elementAt(i), yAxis.elementAt(i), 10, p);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
    // TODO Auto-generated method stub
    // Implement this method to handle touch screen motion events.
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
    xAxis.add(event.getX());
    yAxis.add(event.getY());
    }
    return true;
    }

    class sxpLoop implements Runnable {
    @Override
    public void run() {
    // TODO Auto-generated method stub
    while (true) {
    try {
    // 在绘图时,必须首先用Canvas c=holder.lockCanvas();锁定并获得画布,随后进行绘制,再调用holder.unlockCanvasAndPost(c);将绘制内容进行呈现
    Canvas c = sh.lockCanvas();
    doDraw(c);
    sh.unlockCanvasAndPost(c);
    Thread.sleep(20);
    } catch (Exception e) {

    }
    }
    }
    }

    }

    自定义的控件必须要继承surfaceView类,同时实现surfaceHolder.Callback接口。surfaceView就是通过这个接口来控制的,什么接口,就是类似于onCreated...等。代码中还有个addCallback(this),就是增加这个自定义类作为参数,学术上叫做添加接口,个人呢理解就是onCreated...几个接口在自定义类中实现,所以就添加这个类作为参数了。

    布局文件

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width
    ="fill_parent"
    android:layout_height
    ="fill_parent"
    android:orientation
    ="vertical" >
    <!-- 这种用法应该学习,布局中摆放的是控件,也可以摆放我自定义的控件. 但是我要指明我的控件的包名与空间名. 系统自带的控件不需要指定包名 -->
    <cn.com.sxp.sxpView
    android:id="@+id/sxpView"
    android:layout_width
    ="fill_parent"
    android:layout_height
    ="fill_parent"
    />

    </LinearLayout>

    布局文件中不但可以用自带控件,还可以使用自定义控件,那叫一个爽~~~

    运行结果




  • 相关阅读:
    zoj3430Detect the Virus(ac自动机)
    zoj3494BCD Code(ac自动机+数位dp)
    hdu3247Resource Archiver(ac自动机+spfa)
    hdu3341Lost's revenge(ac自动机+dp)
    hdu4511小明系列故事——女友的考验(ac自动机+最短路)
    hdu4758Walk Through Squares(ac自动机+dp)
    数论一
    母函数专题
    KMP专题
    3级算法题
  • 原文地址:https://www.cnblogs.com/itblog/p/2313645.html
Copyright © 2020-2023  润新知