为什么编辑 LayoutParams 大小没有 canvas 大小的效果

Why editing LayoutParams size doesn't have the effect of a canvas size

我正在处理扩展 SurfaceView 的幻灯片菜单视图,但是当我尝试更改视图大小时,canvas 没有改变。

出于调试目的,我正在更改视图调用方法的大小:

public void changeSize() {
    width += 10;
    getLayoutParams().width = width;
    this.setLayoutParams(getLayoutParams());
}

然后在绘图函数中,我将 canvas 绘制为白色,并在视图对角线上绘制红线:

public void draw() throws Exception {
  SurfaceHolder surfaceHolder = getHolder();
  if (surfaceHolder.getSurface().isValid()) {
    Canvas canvas = surfaceHolder.lockCanvas();
    Log.i(TAG, "draw > canvas size: " + canvas.getWidth() + " " + canvas.getHeight() );
    paint.setColor(Color.rgb(255,0,0));
    paint.setStrokeWidth(5);
    canvas.drawColor(Color.rgb(255, 255, 255));
    canvas.drawLine(0, getLayoutParams().height, getLayoutParams().width, 0, paint);

    surfaceHolder.unlockCanvasAndPost(canvas);
  }
}

我看到的是一个固定大小的白色矩形和部分红线: demo.

此外,当我调用 this.getWidth() 时,我得到的宽度不变。 为什么视图大小没有改变? canvas 没有改变的原因是一样的吗?我能做些什么来修复它?

通过执行 getLayoutParams().width = width;,您正在更改 View 的布局参数。但是你是在拥有 SurfaceHolderCanvas 上进行绘图,而不是普通的 View 会提供给你的

因此,为了更改 SurfaceView 的大小,您必须与 SurfaceHolder:

进行交互
surfaceView.getHolder().setFixedSize(width, height);

我为自己找到了理由。

我没有提到一些事情 - 我认为不重要 - 我通过其他线程调用 changeSize() 而不是创建视图,这是不允许的,因为:Only the original thread that created a view hierarchy can touch its views。这个问题已经解决了很多次,例如here

我可以像这样在 changeSize() 中使用 Activity.runOnUiThread() method but I did not want to pass the Activity to the view so I use View.post() 方法:

Runnable changeParams = new Runnable() {
  @Override
  public void run() {
    getLayoutParams().width = width;
    setLayoutParams(getLayoutParams());
  }
};
this.post(changeParams);

更新:

也许我不知道使用 UI 线程的正确方法,但无论我尝试过什么,我都无法顺利更改视图参数。

实现滑动菜单的一些解决方法:

  1. 做[Android导航抽屉][4]——你可以用限制来定制它,例如你不能让导航抽屉从顶部移动。
  2. 使用 [Android 动画][5] -- 使用它您可以移动或缩放视图但不能调整它的大小。

我的声誉链接不能超过 2 个:

(4): developer.android.com/training/implementing-navigation/nav-drawer.html

(5): developer.android.com/training/animation/index.html