my solution is more like creating a square mask and then placing it on top of the preview surface.
You will need 3 things basically, first the square component of the frame. I created a custom component:
package com.example.squaredviewer; import android.content.Context; import android.util.AttributeSet; import android.view.Display; import android.view.WindowManager; import android.widget.RelativeLayout; public class SquaredFrame extends RelativeLayout{ public SquaredFrame(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int size = Math.min(getMeasuredWidth(), getMeasuredHeight()); setMeasuredDimension(size, size); } }
Depending on the version of the Android API you are developing for, you may need to add another constructor overload. For Kitkat, this is wonderful.
The second step is to create a layout:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:visibility="visible"> <RelativeLayout android:id="@+id/camera_preview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="false" android:layout_alignParentTop="false" android:layout_centerInParent="true" android:background="#ffffff"> </RelativeLayout> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:background="#131008"> </LinearLayout> <com.example.squaredviewer.SquaredFrame android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true"></com.example.squaredviewer.SquaredFrame> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:background="#131008" /> </LinearLayout> </RelativeLayout>
Note that the RelativeLayout "camera_preview" is the one used to render the preview, it is centered and has a LinearLayout that contains the square of the component. This is actually a “mask” and it covers the preview of the camera. Also note that besides the transparent SquaredFrame, the other two are the background color with black.
Now a surface view for a camera preview in which the surface size matches the format.
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { private final String TAG = "PIC-FRAME"; private SurfaceHolder mHolder; private Camera mCamera; private Display display; public CameraPreview(Activity context, Camera camera) { super(context); mCamera = camera; display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
Now everything should be connected with the activity class.
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_picture_taker); mDecorView = getWindow().getDecorView(); //mCamera = a camera instance; // Create our Preview view and set it as the content of our activity. mPreview = new CameraPreview(this, mCamera); //Layout where camera preview is shown. RelativeLayout preview = (RelativeLayout) findViewById(R.id.camera_preview); //FrameLayout stack controllers inside and superpose them. preview.addView(mPreview, 0); // TODO }
A little long, but I hope it will be useful for a few. :-)