Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/181.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 使用“曲面视图”时闪烁_Android_Android Canvas_Surfaceview_Doublebuffered - Fatal编程技术网

Android 使用“曲面视图”时闪烁

Android 使用“曲面视图”时闪烁,android,android-canvas,surfaceview,doublebuffered,Android,Android Canvas,Surfaceview,Doublebuffered,我使用surface view来显示一些图形,问题是当我在屏幕上移动图形时会出现闪烁效果,我知道这是由于双缓冲问题造成的,尽管我读了很多文章,但我无法解决问题,请查看我的代码并帮我解决这个问题 public class CustomSurfaceView extends SurfaceView implements Runnable{ Thread mThread = null; SurfaceHolder mSurfaceHolder;

我使用surface view来显示一些图形,问题是当我在屏幕上移动图形时会出现闪烁效果,我知道这是由于双缓冲问题造成的,尽管我读了很多文章,但我无法解决问题,请查看我的代码并帮我解决这个问题

public class CustomSurfaceView  extends SurfaceView implements Runnable{

      Thread mThread             =  null;
      SurfaceHolder mSurfaceHolder;
      volatile boolean mRunning  =  false;
      Bitmap mBitmap;
      boolean mTouched;
      float mTouched_x,mTouched_y;
      Context mContext;
      float mCurrentPosOfRect1x1,mCurrentPosOfRect1y1,mCurrentPosOfRect1x2,mCurrentPosOfRect1y2;
      float mCurrentPosOfRect2x1,mCurrentPosOfRect2y1,mCurrentPosOfRect2x2,mCurrentPosOfRect2y2;

      private Paint mPaint   =  new Paint(Paint.ANTI_ALIAS_FLAG);
      boolean isInitialized  =  false;

      /**
       * Constructor..
       */
      public CustomSurfaceView(Context context) {
          super(context);
          mSurfaceHolder = getHolder();
          mBitmap   =   BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
          mContext  =   context;

          mCurrentPosOfRect1x1  =   100;
          mCurrentPosOfRect1y1  =   100;
          mCurrentPosOfRect1x2  =   300;
          mCurrentPosOfRect1y2  =   300;

          mCurrentPosOfRect2x1  =   300;
          mCurrentPosOfRect2y1  =   300;
          mCurrentPosOfRect2x2  =   500;
          mCurrentPosOfRect2y2  =   500;
      }

      public void onResumeMySurfaceView(){
          mRunning  =   true;
          mThread       =   new Thread(this);
          mThread.start();
      }

      public void onPauseMySurfaceView(){
          boolean retry = true;
          mRunning = false;
          while(retry){
              try {
                  mThread.join();
                  retry = false;
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }
      }

      @Override
      public void run() {
       while(mRunning){
           if(mSurfaceHolder.getSurface().isValid()){
               Canvas canvas = mSurfaceHolder.lockCanvas();
               //... actual drawing on canvas

               mPaint.setStyle(Paint.Style.STROKE);

               if(mTouched){
                      canvas.drawColor(Color.BLACK); 

                      mPaint.setColor(Color.BLACK);
                      mPaint.setStrokeWidth(3);
                      mPaint.setStrokeWidth(0);
                      mPaint.setColor(Color.CYAN);
                      //Left,top 
                      //Right bottom.
                      if(!isInitialized){
                          canvas.drawRect(mCurrentPosOfRect1x1, mCurrentPosOfRect1y1,mCurrentPosOfRect1x2, mCurrentPosOfRect1y2,mPaint);
                          isInitialized =   true;

                      }

                      mPaint.setColor(Color.BLACK);
                      mPaint.setStrokeWidth(3);
                      mPaint.setStrokeWidth(0);
                      mPaint.setColor(Color.BLUE);
                      //Left,top 
                      //Right bottom.
                      if(!isInitialized){
                          canvas.drawRect(mCurrentPosOfRect2x1, mCurrentPosOfRect2y1,mCurrentPosOfRect2x2, mCurrentPosOfRect2y2,mPaint);
                          isInitialized = true;

                      }

                      if(isInitialized){
                          //Check whether the touch points are inside the rectangle & then move...
                          if((mTouched_x>mCurrentPosOfRect1x1) && (mTouched_x<mCurrentPosOfRect1x2) && (mTouched_y>mCurrentPosOfRect1y1) && (mTouched_y<mCurrentPosOfRect1y2)){
                              mCurrentPosOfRect1x1  =   mTouched_x-100;
                              mCurrentPosOfRect1x2  =   mTouched_x+100;
                              mCurrentPosOfRect1y1  =   mTouched_y-100;
                              mCurrentPosOfRect1y2  =   mTouched_y+100;
                          }else if((mTouched_x>mCurrentPosOfRect2x1) && (mTouched_x<mCurrentPosOfRect2x2) && (mTouched_y>mCurrentPosOfRect2y1) && (mTouched_y<mCurrentPosOfRect2y2)){
                              mCurrentPosOfRect2x1  =   mTouched_x-100;
                              mCurrentPosOfRect2x2  =   mTouched_x+100;
                              mCurrentPosOfRect2y1  =   mTouched_y-100;
                              mCurrentPosOfRect2y2  =   mTouched_y+100;

                          }
                      }

                      canvas.drawRect(mCurrentPosOfRect1x1, mCurrentPosOfRect1y1,mCurrentPosOfRect1x2, mCurrentPosOfRect1y2, mPaint);
                      mPaint.setColor(Color.RED);
                      canvas.drawRect(mCurrentPosOfRect2x1,  mCurrentPosOfRect2y1,mCurrentPosOfRect2x2, mCurrentPosOfRect2y2, mPaint);
                      mPaint.setColor(Color.BLUE);


                      Paint paint = new Paint() {
                            {
                                setStyle(Paint.Style.STROKE);
                                setStrokeCap(Paint.Cap.ROUND);
                                setStrokeWidth(3.0f);
                                setAntiAlias(true);
                            }
                        };

                        paint.setColor(Color.YELLOW);

                        final Path path = new Path();
                        final float x1 = mCurrentPosOfRect1x1+ 100;
                        final float y1 = mCurrentPosOfRect1y1 + 100;



                        final float x3 = (mCurrentPosOfRect2x1+ 100) ;
                        final float y3 = (mCurrentPosOfRect2y1 + 100);

                        final float x2 = (x1 +200);
                        final float y2 = (y1 -100);

                        final float x4  = (x3-100);
                        final float y4  = (y3+200);

                        path.moveTo(x1, y1);

                        path.cubicTo(x2,y2,x4,y4,x3,y3);
                        canvas.drawPath(path, paint);

                }

               mSurfaceHolder.unlockCanvasAndPost(canvas);
        }

      }

    }
      @Override
       public boolean onTouchEvent(MotionEvent event){

          mTouched_x = event.getX();
           mTouched_y = event.getY();
          int action = event.getAction();
           switch(action){
           case MotionEvent.ACTION_DOWN:
            mTouched = true;
            break;
           case MotionEvent.ACTION_MOVE:
            mTouched = true;
            break;
           case MotionEvent.ACTION_UP:
            mTouched = false;
            break;
           case MotionEvent.ACTION_CANCEL:
            mTouched = false;
            break;
           case MotionEvent.ACTION_OUTSIDE:
            mTouched = false;
            break;
           default:
           }
           return true; //processed
       }
}
公共类CustomSurfaceView扩展了SurfaceView实现可运行{
线程mThread=null;
表面支架;
易失性布尔mRunning=false;
位图mBitmap;
布尔触摸;
浮动mTouched_x,mTouched_y;
语境;
浮点数MCurrentPosOfRet1x1、MCurrentPosOfRet1x1、MCurrentPosOfRet1x2、MCurrentPosOfRet1x2;
浮动mCurrentPosOfRect2x1、mCurrentPosOfRect2y1、mCurrentPosOfRect2x2、mCurrentPosOfRect2y2;
私有油漆mPaint=新油漆(油漆.防油漆别名标志);
布尔isInitialized=false;
/**
*建造师。。
*/
公共CustomSurfaceView(上下文){
超级(上下文);
mSurfaceHolder=getHolder();
mBitmap=BitmapFactory.decodeResource(getResources(),R.drawable.ic_启动器);
mContext=上下文;
mCurrentPosOfRect1x1=100;
mCurrentPosOfRect1y1=100;
mCurrentPosOfRect1x2=300;
mCurrentPosOfRect1y2=300;
mCurrentPosOfRect2x1=300;
mCurrentPosOfRect2y1=300;
mCurrentPosOfRect2x2=500;
mCurrentPosOfRect2y2=500;
}
在ResumeMySurfaceView()上公开作废{
mRunning=真;
mThread=新线程(此线程);
mThread.start();
}
public void onPauseMySurfaceView(){
布尔重试=真;
mRunning=假;
while(重试){
试一试{
mThread.join();
重试=错误;
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}
@凌驾
公开募捐{
同时(运行){
if(mSurfaceHolder.getSurface().isValid()){
Canvas Canvas=mSurfaceHolder.lockCanvas();
//…画布上的实际绘图
mPaint.setStyle(油漆、样式、笔划);
如果(触摸){
画布。drawColor(颜色。黑色);
mPaint.setColor(Color.BLACK);
mPaint.设定行程宽度(3);
mPaint.设定行程宽度(0);
mPaint.setColor(Color.CYAN);
//左上角
//右下角。
如果(!i初始化){
canvas.drawRect(mCurrentPosOfRect1x1、mCurrentPosOfRect1y1、mCurrentPosOfRect1x2、mCurrentPosOfRect1y2、mPaint);
isInitialized=true;
}
mPaint.setColor(Color.BLACK);
mPaint.设定行程宽度(3);
mPaint.设定行程宽度(0);
mPaint.setColor(Color.BLUE);
//左上角
//右下角。
如果(!i初始化){
canvas.drawRect(mCurrentPosOfRect2x1、mCurrentPosOfRect2y1、mCurrentPosOfRect2x2、mCurrentPosOfRect2y2、mPaint);
isInitialized=true;
}
如果(已初始化){
//检查触摸点是否在矩形内,然后移动。。。

如果((mTouched_x>mccurrentposofrect1x1)和&(mTouched_xmCurrentPosOfRect1y1)和&(mTouched_ymcurrentposofrect2y1)和&(mTouched_xmCurrentPosOfRect2y1)闪烁通常是一个奇怪的问题,因此这是我关于如何解决您的具体情况的最佳猜测

我可以从您的代码中看到,您正在声明一系列不同的命令以应用于画布,这些命令在画布中一次一个地绘制,按照代码的顺序,此时您的代码
lockCanvas
以及我认为这些元素的组合是您闪烁的原因

因为:

  • 在系统VSYNC期间,不会执行这些绘制(因为SurfaceViews)
  • 它是按顺序一次完成的(这需要时间并使闪烁变得明显)
我可以想出两种解决方案:

  • 我可以看到您在视图上只调用了
    drawColor
    drawRect
    。而且,您没有对其执行任何耗时的操作。因此我真的看不出使用
    SurfaceView
    的原因。将类重构为正常的
    扩展视图
    ,并在
    onDraw
    中执行它们的绘制,然后调用invalidate()
  • 只要需要重新绘制(我相信它会在触摸事件中)

  • 如果您为了简洁而忽略了一些代码,而这些代码确实使
    SurfaceView
    变得非常必要,那么您可以使用与屏幕画布相同大小的位图分配一个临时画布。在这个临时画布上绘制所有图形,并且仅在屏幕画布上使用
    drawBitmap
    调用。一个小示例代码f或者是这样


  • 请记住,这只是一个示例代码,不是一个完整的解决方案,您必须执行画布有效性的所有常规检查,等等。

    如果调用
    lockCanvas()
    ,则需要绘制脏矩形中的每一个像素。因为您调用它时没有脏矩形,这意味着更新画布上的每一个像素

    我相信你的代码的问题是,当
    mtoutched
    false
    时,你根本没有画任何东西。因为表面是双缓冲或三缓冲的,你显示的是前一帧的内容,这将导致振动效应

    我想你都需要
     // init your objects inside the `surfaceCreated` callback
     Bitmap tempBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
     Canvas tempCanvas = new Canvas(tempBitmap);
    
    
    // then on your thread.
     while(mRunning){
        tempCanvas. // ... do all your drawing operations here
        Canvas canvas = mSurfaceHolder.lockCanvas();
        canvas.drawBitmap(tempBitmap, 0, 0, null);
        mSurfaceHolder.unlockCanvasAndPost(canvas);
     }
    
    Canvas canvas = mSurfaceHolder.lockCanvas();
    canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
    // Draw someting
    mSurfaceHolder.unlockCanvasAndPost(canvas);
    mSurfaceHolder.setFormat(PixelFormat.TRANSPARENT);
    mSurfaceHolder.setFormat(PixelFormat.OPAQUE);
    
    mSurfaceHolder.setFormat(PixelFormat.TRANSLUCENT);