Android surfaceChanged宽度/高度值不正确

时间:2012-02-07 16:20:08

标签: android rotation

我在表面上绘制了一个位图,每次旋转设备时都需要调整大小。由于软按钮,我使用此代码获取当前尺寸(似乎工作正常):

public void getCanvasXY(){
    int currentapiVersion = android.os.Build.VERSION.SDK_INT;
    if (currentapiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB_MR2){
         // HoneyComb 3.2 and up
         DisplayMetrics metrics = new DisplayMetrics();
         ((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(metrics);
         Global.CanvasX = metrics.widthPixels;
         Global.CanvasY = metrics.heightPixels;
    } else{
         // before HoneyComb
         Global.CanvasX = getWidth();
         Global.CanvasY = getHeight();
    }
}

我认为重新计算尺寸和创建位图的最佳位置是在surfaceChanged()中。

@Override
    public void surfaceChanged(SurfaceHolder holder1, int format, int width, int height) {
                getCanvasXY();
                LoadBMP();
    }

我看到这不止一次被调用,当设备旋转时,CanvasX和CanvasY会得到不同的值。它的最后一次调用工作正常,但我看到onDraw()是如何绘制我的位图,精灵调整大小,最后确定。这是一个丑陋的效果。 怎么解决这个? 感谢

1 个答案:

答案 0 :(得分:0)

这里我假设您的意思是SurfaceView,您使用背景线程绘制到曲面,并且您正在使用SurfaceHolder.CallBack()。这不是一个完整的答案,但是,这个问题也困扰了我一段时间。在我的深夜故障排除中,我设法整理了一个可能比你的更优雅的解决方法。结果是没有任何东西被绘制,直到surfacechanged已经稳定到它的最后状态,所以用户不知道发生了什么。

在你的表格中,你会注意到你的身高或宽度没有变化到正确的值,换句话说,如果绘制的结果面是MalFormed。你需要的是你的身高和宽度应该是什么的参考值,你可以通过在主活动中的SetContentView()之前放置以下代码来获得它:

WindowManager w = getWindowManager();
   Display d = w.getDefaultDisplay();
   int Meausredwidth = d.getWidth();
   int Measuredheight = d.getHeight(); 

现在,从您测量的高度和宽度,计算出您为surfaceView分配的数量,并将这些值作为全局变量传递给SurfaceView。并确保在主活动中调用onconfigurationchanged()中的上述代码,以便每次重新计算这些值。现在在你的SurfaceView上应该以某种方式实现SurfaceHolder.Callback,将你的surfacechanged更改为如下所示:

@Override
public void surfaceChanged(SurfaceHolder mholder, int format, int width,
        int height) {

    if (width != mWidth) {
        MalFormed = true;
        thread.setRunning(false);
        count++;

    } else if (width == mWidth) {

        if (MalFormed) {
            MalFormed = false;

            Log.d("ROTATE", "ReDraw");

            thread = new DrawingThread(this, holder, mHandler);
            thread.setRunning(true);
            thread.start();

        }

    }

}

其中mWidth是所需的宽度。在这里,您可能需要根据具体问题更改if语句。 MalFormed是表面视图中的全局布尔值。

现在重要的是要记住,如果发生更改,SurfaceChanged()会在SurfaceCreated之前被调用,这意味着我们可以轻松修改任何尝试与线程交互的代码以适应我们的上述更改。

因此,在您尝试加入或启动背景绘制线程的任何其他地方,您必须首先检查表面是否为MalFormed。 E.g。

if (thread.getState() == State.TERMINATED){

            if(!MalFormed){
               holder.removeCallback(this);
               holder = getHolder();
               holder.addCallback(this);


               thread = new DrawingThread(this, holder,mHandler);
               thread.setRunning(true);

               thread.start();
            }



        }else{
            if(!MalFormed){
                thread.setRunning(true);

                try {
                    thread.join();
                } catch (InterruptedException e) {

                    e.printStackTrace();
                }
            }


        }

希望我在某个地方的球场。一切顺利。