6

I am wondering in which way Android draws views on the screen inside layout views with defined android:layout_width and android:layout_height values in pixels.

I am using Android class view extends android.view.SurfaceView. It is just MjpegView to display MJPEG stream from the camera on the Android app. I am working with this code (with some small changes): Android ICS and MJPEG using AsyncTask

This MjpegView class is placed inside the RelativeLayout. MjpegView object is added programmatically and this RelativeLayout has attributes defined in this way:

android:layout_width="800px"
android:layout_height="600px"

This size values is necessary for this application so I can't change them. Application is working only in landscape orientation. My MjpegView need to be set 320 x 240 pixels size inside RelativeLayout (800 x 600 px). My application enlarges this RealtiveLayout to fill the screen on the current device. And this is a problem connected also with the streaming MJPEG. I am working on Nexus 7 (2012 version), which has 1280 x 800 resolution.

To get the real size of this view inside layout I have to measured the height of the Nexus 7 screen without action and navigation bars. To get this I have used this method inside one Activity:

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    RelativeLayout parentLayout = (RelativeLayout) findViewById(R.id.parent_layout);
    if (parentLayout != null && isLandscape) {
        this.measuredActivityHeight = parentLayout.getBottom();
    }
}

I am getting 703 value as the measuredActivityHeight of the running Activity. So to get the ratio in which Android translates 320 x 240 px inside 800 x 600 px to the dp value on the screen I have written this method:

 public int calculateForCurrentScreen(float pixelValue) {
    float ratio = PageActivity.measuredActivityHeight / 600f;
    int result = (int) (pixelValue * ratio);
    return result;
}

So for the 320 x 240 px on the Nexus 7 I am getting 374 x 281. And to get MjpegView in this size I need to use this method inside the MjpegView class:

public void setResolution(int width, int height) {
    holder.setFixedSize(width, height);
}

And the size of the streaming view is in the wanted size. But this view has additional black areas. So in fact the whole view (camera stream + black areas on the its bottom and right side) has 440 x 328 size.

I have checked that Rect object in MjpegView is drawing with 374 x 281 size so it is OK. SurfaceHolder and Canvas also have this size. Bitmap object has 320 x 240 size, but this is OK because Bitmap object is from camera stream. And it is resized to the wanted size.

Problem disappear (there is no black areas and MjpegView is in correct position and size relative to other views) when I have switched RelativeLayout to the 800dp x 600dp size and invoke setResolution(320, 240) for the MjpegView object. But the whole layout is in this moment too big.

EDIT

Thanks @mathiash for your comment. I have just uploaded screenshot from Nexus 7 (2012 edition) to show you my problem.

As you can see, the green area is the RelativeLayout with defined 800 x 600 px size. To get MJPEG stream from the http://trackfield.webcam.oregonstate.edu/. I have used this URL: http://trackfield.webcam.oregonstate.edu/axis-cgi/mjpg/video.cgi?resolution=320x240.

For this screenshot I have invoked setResolution(320, 240) method. And black area has 374 x 281 and video stream 320 x 240.

320x240

For this screenshot I have invoked setResolution(374, 281) method. And black area is much bigger and video stream is 374 x 281. And in this case video stream has correct size but this black area is unnecessary.

374x281

Community
  • 1
  • 1
woyaru
  • 5,544
  • 13
  • 54
  • 92
  • sorry i missed your question – pskink Jun 09 '14 at 15:38
  • 1
    This question is interesting, but, I'm sorry to say, rather hard to understand. :/ Perhaps a screenshot would be useful? – matiash Jun 12 '14 at 23:38
  • @matiash thanks for your comment, I have updated my question with the sreenshots – woyaru Jun 13 '14 at 08:03
  • 2
    Well, one thing Android teaches you is to never use concrete pixel values. Use ratios and dp. – Levente Kurusa Jun 15 '14 at 07:38
  • @LeventeKurusa Well I have tried with `800 x 600 dp`. And it looks OK, but my app supports zooming in with two fingers gesture, and zooming in causes that this black area is also appearing... – woyaru Jun 15 '14 at 21:21

3 Answers3

2

As Levente Kurusa suggested, using a virtual pixel unit such as dp may solve your problem. We should avoid using px diretly.

  • As I have mentioned in the comment to mu question: I have tried with `800 x 600 dp` size also. And it looks OK (without black area), but my app supports zooming in with two fingers gesture, and zooming in causes that this black area is also appearing... – so using dp or pixel is not a solution. I am looking for a solution how to complex set the size of the view extending `SurfaceView` – woyaru Jun 18 '14 at 11:46
1

dont use dp, even dp changes with different screens. Instead i learned to use my own value times density. So use DisplayMetrics metrics = getResources().getDisplayMetrics(); and metrics.getDensity() * 50 for example. Also try to use weights to keep them relative in different screens.

Elgert
  • 470
  • 2
  • 5
  • 19
0

You can try with

whateveryourvideoname.setDisplayMode(MjpegView.SIZE_BEST_FIT)

in order to make the best fitting of your inputstream (with the resolution you set up previously) within the layout view.


But all this doesn't make sense if you have defined your Mjpegview in the layout.xml file with the same size as the resolution of your source image, so the best way is to skip the setResolution command and just use

whateveryourvideoname.setDisplayMode(MjpegView.SIZE_FULLSCREEN)

and your image will fit perfectly inside your MjpegView display.

GameDroids
  • 5,584
  • 6
  • 40
  • 59