SurfaceView的一些简单记录

1.surfaceView是继承之View,与普通的Button、TextView的区别是surfaceView在非UI线程上刷新View

2.surfaceView内部实现了SurfaceHolder接口,提供getHolder方法来获取SurfaceHolder,使用者通过surfaceView对象获取SurfaceHolder来用来操纵surface。处理它的Canvas上画的效果和动画,控制表面,大小,像素等。

3.surfaceView实现了SurfaceHolder,SurfaceHolder提供addCallback(Callback callback)方法,添加回调接口来通知使用者surfaceView的创建、销毁、尺寸改变。

4.SurfaceView不需要通过线程来更新视图,但是再绘制前需要使用locakCanvas锁定画布,并且得到画布,然后再画布上绘制你需要的图像。绘制完成后需要使用lockCanvasAndPost方法来解锁画布。于是才能显示在屏幕上。事件的处理规则和View是一样的。

5.整个实现过程: 
继承SurfaceView并实现SurfaceHolder.Callback接口------>SurfaceView.getHolder()获得SurfaceHolder对象----->SurfaceHolder.addCallback(callback)添加回调函数----->
  surfaceHolder.lockCanvas()获得Canvas对象并锁定画布------>Canvas绘画------->SurfaceHolder.unlockCanvasAndPost(Canvas canvas)结束锁定画图,并提交改变,将图形显示。


使用例子:

  import android.app.Activity;
  import android.content.Context;
  import android.graphics.Canvas;
  import android.graphics.Color;
  import android.graphics.Paint;
  import android.graphics.Rect;
  import android.os.Bundle;
  import android.view.SurfaceHolder;
  import android.view.SurfaceView;
  
  public class ViewTest extends Activity {
      /** Called when the activity is first created. */
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(new MyView(this));
      }
      //视图内部类
      class MyView extends SurfaceView implements SurfaceHolder.Callback
      {
          private SurfaceHolder holder;
          private MyThread myThread; 
          public MyView(Context context) {
              super(context);
              // TODO Auto-generated constructor stub
              holder = this.getHolder();
              holder.addCallback(this);
              myThread = new MyThread(holder);//创建一个绘图线程
          }
  
          @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
              myThread.isRun = true;
              myThread.start();
          }
  
          @Override
          public void surfaceDestroyed(SurfaceHolder holder) {
              // TODO Auto-generated method stub
              myThread.isRun = false;
          }
          
      }
      //线程内部类
      class MyThread extends Thread
      {
          private SurfaceHolder holder;
          public boolean isRun ;
          public  MyThread(SurfaceHolder holder)
          {
              this.holder =holder; 
              isRun = true;
         }
         @Override
          public void run()
          {
             int count = 0;
             while(isRun)
              {
                  Canvas c = null;
                  try
                  {
                      synchronized (holder)
                      {
                          c = holder.lockCanvas();//锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。
                          c.drawColor(Color.BLACK);//设置画布背景颜色
                          Paint p = new Paint(); //创建画笔
                          p.setColor(Color.WHITE);
                          Rect r = new Rect(100, 50, 300, 250);
                          c.drawRect(r, p);
                          c.drawText("这是第"+(count++)+"秒", 100, 310, p);
                          Thread.sleep(1000);//睡眠时间为1秒
 }
                  }
                  catch (Exception e) {
                      // TODO: handle exception
                      e.printStackTrace();
                  }
                  finally
                  {
                      if(c!= null)
                     {
                          holder.unlockCanvasAndPost(c);//结束锁定画图,并提交改变。
  
                    }
                  }
              }
         }
      }
 }




public SurfaceHolder getHolder() {
    return mSurfaceHolder;
}
 
private final SurfaceHolder mSurfaceHolder = new SurfaceHolder() {

    private static final String LOG_TAG = "SurfaceHolder";

    @Override
    public boolean isCreating() {
        return mIsCreating;
    }

    @Override
    public void addCallback(Callback callback) {
        synchronized (mCallbacks) {
            // This is a linear search, but in practice we'll
            // have only a couple callbacks, so it doesn't matter.
            if (mCallbacks.contains(callback) == false) {
                mCallbacks.add(callback);
            }
        }
    }

    @Override
    public void removeCallback(Callback callback) {
        synchronized (mCallbacks) {
            mCallbacks.remove(callback);
        }
    }

    @Override
    public void setFixedSize(int width, int height) {
        if (mRequestedWidth != width || mRequestedHeight != height) {
            mRequestedWidth = width;
            mRequestedHeight = height;
            requestLayout();
        }
    }

    @Override
    public void setSizeFromLayout() {
        if (mRequestedWidth != -1 || mRequestedHeight != -1) {
            mRequestedWidth = mRequestedHeight = -1;
            requestLayout();
        }
    }

    @Override
    public void setFormat(int format) {

        // for backward compatibility reason, OPAQUE always
        // means 565 for SurfaceView
        if (format == PixelFormat.OPAQUE)
            format = PixelFormat.RGB_565;

        mRequestedFormat = format;
        if (mWindow != null) {
            updateWindow(false, false);
        }
    }

    /**
     * @deprecated setType is now ignored.
     */
    @Override
    @Deprecated
    public void setType(int type) { }

    @Override
    public void setKeepScreenOn(boolean screenOn) {
        Message msg = mHandler.obtainMessage(KEEP_SCREEN_ON_MSG);
        msg.arg1 = screenOn ? 1 : 0;
        mHandler.sendMessage(msg);
    }

    /**
     * Gets a {@link Canvas} for drawing into the SurfaceView's Surface
     *
     * After drawing into the provided {@link Canvas}, the caller must
     * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
     *
     * The caller must redraw the entire surface.
     * @return A canvas for drawing into the surface.
     */
    @Override
    public Canvas lockCanvas() {
        return internalLockCanvas(null);
    }

    /**
     * Gets a {@link Canvas} for drawing into the SurfaceView's Surface
     *
     * After drawing into the provided {@link Canvas}, the caller must
     * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
     *
     * @param inOutDirty A rectangle that represents the dirty region that the caller wants
     * to redraw.  This function may choose to expand the dirty rectangle if for example
     * the surface has been resized or if the previous contents of the surface were
     * not available.  The caller must redraw the entire dirty region as represented
     * by the contents of the inOutDirty rectangle upon return from this function.
     * The caller may also pass <code>null</code> instead, in the case where the
     * entire surface should be redrawn.
     * @return A canvas for drawing into the surface.
     */
    @Override
    public Canvas lockCanvas(Rect inOutDirty) {
        return internalLockCanvas(inOutDirty);
    }

    private final Canvas internalLockCanvas(Rect dirty) {
        mSurfaceLock.lock();

        if (DEBUG) Log.i(TAG, "Locking canvas... stopped="
                + mDrawingStopped + ", win=" + mWindow);

        Canvas c = null;
        if (!mDrawingStopped && mWindow != null) {
            try {
                c = mSurface.lockCanvas(dirty);
            } catch (Exception e) {
                Log.e(LOG_TAG, "Exception locking surface", e);
            }
        }

        if (DEBUG) Log.i(TAG, "Returned canvas: " + c);
        if (c != null) {
            mLastLockTime = SystemClock.uptimeMillis();
            return c;
        }

        // If the Surface is not ready to be drawn, then return null,
        // but throttle calls to this function so it isn't called more
        // than every 100ms.
        long now = SystemClock.uptimeMillis();
        long nextTime = mLastLockTime + 100;
        if (nextTime > now) {
            try {
                Thread.sleep(nextTime-now);
            } catch (InterruptedException e) {
            }
            now = SystemClock.uptimeMillis();
        }
        mLastLockTime = now;
        mSurfaceLock.unlock();

        return null;
    }

    /**
     * Posts the new contents of the {@link Canvas} to the surface and
     * releases the {@link Canvas}.
     *
     * @param canvas The canvas previously obtained from {@link #lockCanvas}.
     */
    @Override
    public void unlockCanvasAndPost(Canvas canvas) {
        mSurface.unlockCanvasAndPost(canvas);
        mSurfaceLock.unlock();
    }

    @Override
    public Surface getSurface() {
        return mSurface;
    }

    @Override
    public Rect getSurfaceFrame() {
        return mSurfaceFrame;
    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值