android中Surface View的用法

SurfaceView与普通的View的区别就是View视图必须在当前UI线程中进行,这也是在更新View组件时总要采用Handler处理的原因;但SurfeceView不会存在这个问题,它的绘图是由SurfaceHolder来完成的,SurfaceHolder会启动新的线程去更新SurfaceView的绘制,不会阻塞主UI线程。一般而言,如果程序中或游戏界面中的动画元素较多,而且很多动画元素都需要通过定时器来控制,就可以考虑使用SurfaceView而不是View。

使用SurfaceView时,需要在新建线程去更新UI。其使用步骤如下:

1.用findViewById获取SurfaceView实例

2.用其getHolder方法取得holder实例

3.利用holder的holder.lockCanvas()封锁并获取Canvas实例

4.在Canvas上绘制相应图形

5.用holder.unlockCanvasAndPost(canvas)方法解锁并将Canvas显示到SurfaceView上面


下面是一个绘制正弦余弦的实例(不断地获取x所对应的正弦余弦的y值并将其绘制出来)

maiin.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
   android:layout_width="match_parent"
   android:layout_height="match_parent">
<LinearLayout android:orientation="horizontal"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:gravity="center"
   >
<Button android:id="@+id/sin"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="@string/sin"
   />
<Button android:id="@+id/cos"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="@string/cos"
   /> 
</LinearLayout>
<SurfaceView android:id="@+id/show"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:gravity="center"
   />
</LinearLayout>

MainActivity.java
package com.example.wanglunhui.showware;

import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;

import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends Activity
{
    private SurfaceHolder holder;
    private Paint paint;
    final int HEIGHT = 320;
    final int WIDTH = 768;
    final int X_OFFSET = 5;
    private int cx = X_OFFSET;
    // 实际的Y轴的位置
    int centerY = HEIGHT / 2;
    Timer timer = new Timer();
    TimerTask task = null;
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        final SurfaceView surface = (SurfaceView)
                findViewById(R.id.show);
        // 初始化SurfaceHolder对象
        holder = surface.getHolder();
        paint = new Paint();
        paint.setColor(Color.GREEN);
        paint.setStrokeWidth(3);
        Button sin = (Button)findViewById(R.id.sin);
        Button cos = (Button)findViewById(R.id.cos);
        View.OnClickListener listener = (new View.OnClickListener()
        {
            @Override
            public void onClick(final View source)
            {
                drawBack(holder);
                cx = X_OFFSET;
                if(task != null)
                {
                    task.cancel();
                }
                task = new TimerTask()
                {
                    public void run()
                    {
                        int cy = source.getId() == R.id.sin ? centerY
                                - (int)(100 * Math.sin((cx - 5) * 2
                                * Math.PI / 150))
                                : centerY - (int)(100 * Math.cos ((cx - 5)
                                * 2 * Math.PI / 150));
                        Canvas canvas = holder.lockCanvas(new Rect(cx ,//锁定一个区域来绘制,其余部分都未变,这样的性能更好
                                cy - 2  , cx + 2, cy + 2));
                        canvas.drawPoint(cx , cy , paint);
                        cx ++;
                        if (cx > WIDTH)
                        {
                            task.cancel();
                            task = null;
                        }
                        holder.unlockCanvasAndPost(canvas);
                    }
                };
                timer.schedule(task , 0 , 30);
            }
        });
        sin.setOnClickListener(listener);
        cos.setOnClickListener(listener);
        holder.addCallback(new SurfaceHolder.Callback()
        {
            @Override
            public void surfaceChanged(SurfaceHolder holder, int format,
                                       int width, int height)
            {
                drawBack(holder);
            }
            @Override
            public void surfaceCreated(final SurfaceHolder myHolder){ }
            @Override
            public void surfaceDestroyed(SurfaceHolder holder)
            {
                timer.cancel();
            }
        });
    }
    private void drawBack(SurfaceHolder holder)
    {
        Canvas canvas = holder.lockCanvas();
        // 绘制白色背景
        canvas.drawColor(Color.WHITE);
        Paint p = new Paint();
        p.setColor(Color.BLACK);
        p.setStrokeWidth(2);
        // 绘制坐标轴
        canvas.drawLine(X_OFFSET , centerY , WIDTH , centerY , p);
        canvas.drawLine(X_OFFSET , 40 , X_OFFSET , HEIGHT , p);
        holder.unlockCanvasAndPost(canvas);
        holder.lockCanvas(new Rect(0 , 0 , 0 , 0));
        holder.unlockCanvasAndPost(canvas);
    }
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值