I'm currently developing an Android application that uses the device camera for both taking photos and recording videos. This application must work on API level >= 8 (Froyo).
Until now, I have implemented the camera code based on Android samples. It can be found in <ADT folder>/sdk/samples/<android_version>/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java
- I'm following the "android 11" example to switch between cameras and "android 8" for the rest. This means that my camera preview is held by a SurfaceView
which is contained in a ViewGroup
(CameraPreview
class) which is in turn attached as the content view in the main activity.
The problem is that I don't want the camera preview to be shown as Android does. I mean: I want the preview to fit one of the screen dimensions and overflow the other. Android samples fit one of the screen dimensions and keep the other inside the screen boundaries.
For example: let's take an Android device whose screen dimensions are 480x800. We select a preview size of 480x640. Android would keep this preview size as it fits within the device's screen: it would exactly fit the screen width, while it would show two black rectangles up and down (letterbox). In my case, I'd upscale that preview by 1.25, so as to resize it to 600x800 (that is, making the longest side of both the preview and the camera 800 long). Then I try to center this preview by moving that preview surface (surfaceView
) slightly to the left. In this case, the leftmost horizontal coordinate would be -60 and topmost 0.
My problem is that I'm not able to correctly move the SurfaceView
. It is correctly resized but I cannot move it to the left (out of the screen). Searching on SO, I've found lots of possible solutions but none worked for me. I'm sure that this shouldn't be so difficult and I must be doing something wrong.
Until now, I've tried some solutions such as:
- Following the Android example , I changed it's resizing code -
onMeasure
function - to:
if (width * previewHeight < height * previewWidth) {
final int scaledChildWidth = previewWidth * height / previewHeight;
child.layout( (width - scaledChildWidth) / 2, 0, (width + scaledChildWidth) / 2, height);
} else {
final int scaledChildHeight = previewHeight * width / previewWidth;
child.layout(0, (height - scaledChildHeight) / 2, width, (height + scaledChildHeight) / 2);
}
This correctly resizes the preview to the dimensions I look for but, although leftmost coordinate is supposed to be -60, it continues to be rendered from the upper left corner of the screen. I'm just pasting here the change in onMeasure
function as it the rest of the code is the same as the one in the Android sample folder I said before.
Changing the parent container of the
SurfaceView
into aScrollView
and scrolling the preview.Using negative margins or paddings with
ViewGroup
/RelativeLayout
/FrameLayout
/LinearLayout
/etc. In this case, I was able to move some interface elements (other button I added to the layout) but not theSurfaceView
.Trying to set
clipChildren
andclipToPadding
to false.Trying to play with
centerInParent
option.Creating a new parent layout whose size is the same as that of the
SurfaceView
(scaled preview size) and centering it. It also resizes correctly but doesn't center on the screen.Using
AbsoluteLayout
(yes, I know it's deprecated ;) )
I can't remember now other solutions I tried, but I think these are the main ones.
It seems that I could not prevent elements from starting at the upper left corner of the screen.
Of course, any further details needed can be requested and I'll try to answer ASAP. I got really stuck at this point and I'd be very grateful for any help provided. Thanks to all for spending time on reading this :)
Edit 1
I am testing this application in Android 2.3.6.