2

I am working on slide menu view which extends SurfaceView but when I try to change size of the view a canvas does not change.

For debug purpose, I am changing size of the view calling method:

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

Then in a draw function I paint the canvas white and draw red line diagonally across the view:

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);
  }
}

What I see is a white rectangle with fixed size and part of red line: demo.

Also, when I call this.getWidth() I get unchanged width. Why view size is not changing? Is it the same reason that the canvas is not changing? What can I do to fix it?

lvl7
  • 31
  • 6

2 Answers2

1

I found reason for myself.

I did not mention about something - that I thought was not important - I called changeSize() via other thread than created the view and this is not allowed because: Only the original thread that created a view hierarchy can touch its views. And this problem was many time solved, e.g. here

I could use Activity.runOnUiThread() method but I did not want to pass the Activity to the view so I use View.post() method in the changeSize() like this:

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

Update:

Maybe I do not know about proper way of using the UI Thread but whatever I tried I can not change view parameters smoothly.

Some workarounds to implement a slide menu:

  1. Do [Android navigation Drawer][4] -- you can custiomize it with restictions e.g. you can not do the navigation drawer moving from top.
  2. Use [Android animations][5] -- with it you can move or scale a view but can not resizing it.

I can not put more than 2 links with my reputation:

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

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

Community
  • 1
  • 1
lvl7
  • 31
  • 6
0

By doing getLayoutParams().width = width; you are changing layout params of the View. But you are performing drawing on a Canvas that owns SurfaceHolder, and not the one an ordinary View will provide you.

So, in order to change the size of the SurfaceView, you have to interact with SurfaceHolder:

surfaceView.getHolder().setFixedSize(width, height);
azizbekian
  • 60,783
  • 13
  • 169
  • 249
  • I tried it before in two places: 1) in `changeSize()` after `setLayoutParams(...)`, and 2) in `draw()` method. Both do not work as same as [setSizeFromLayout()](https://developer.android.com/reference/android/view/SurfaceHolder.html#setSizeFromLayout()) which could provide same size like layout. – lvl7 Apr 19 '17 at 14:23
  • `SurfaceHolder` will be accessible as soon as [SurfaceHolder#Callback#surfaceCreated(SurfaceHolder)](https://developer.android.com/reference/android/view/SurfaceHolder.Callback.html) is fired. Have you tried from there? – azizbekian Apr 19 '17 at 14:27