I'm trying to set the picture preview in my app to be square, and have the resulting picture exactly match the preview. However, the picture and preview are turning out as shown in the screenshots below.
Preview screenshot
Picture screenshot
The screenshots are from a Nexus 5 running Android 5.0. I've also tested on a Samsung S3 running 4.4.2, and it seems that, whereas with the Nexus the picture captures more than the preview does, on the S3 it seems that the picture is just offset (to the upper left) from the preview. I can post pictures from the S3, if desired.
Here's my code:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends CameraFragment {
private FrameLayout cameraPreviewLayout;
private Camera camera;
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
SimpleCameraHost.Builder builder=
new SimpleCameraHost.Builder(new TestCameraHost(getActivity()));
setHost(builder.useFullBleedPreview(true).build());
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View cameraView=
super.onCreateView(inflater, container, savedInstanceState);
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
cameraPreviewLayout = ((FrameLayout)rootView.findViewById(R.id.camera_layout));
cameraPreviewLayout.addView(cameraView);
ImageButton changeLayout = (ImageButton) rootView.findViewById(R.id.pick_existing);
changeLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
Button takePicture = (Button) rootView.findViewById(R.id.shutter_button);
takePicture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PictureTransaction xact = new PictureTransaction(getHost());
takePicture(xact);
}
});
return(rootView);
}
@Override
public void onResume() {
// Get the window width to make the camera preview window square
DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
final int windowWidth = metrics.widthPixels;
cameraPreviewLayout.post(new Runnable() {
@Override
public void run() {
ViewGroup.LayoutParams params = cameraPreviewLayout.getLayoutParams();
params.height = windowWidth;
cameraPreviewLayout.setLayoutParams(params);
}
});
super.onResume();
}
@Override
public void onPause() {
if (camera != null) {
camera.release();
}
super.onPause();
}
private class TestCameraHost extends SimpleCameraHost {
public TestCameraHost(Context context) {
super(context);
}
@Override
public void saveImage(PictureTransaction xact, byte[] image) {
DisplayActivity.imageToShow = image;
DisplayActivity.x = (int) cameraPreviewLayout.getX();
DisplayActivity.y = (int) cameraPreviewLayout.getY();
DisplayActivity.height = (int) cameraPreviewLayout.getHeight();
DisplayActivity.width = (int) cameraPreviewLayout.getWidth();
startActivity(new Intent(getActivity(), DisplayActivity.class));
}
}
}
}
public class DisplayActivity extends Activity {
static byte[] imageToShow=null;
static int x = 0;
static int y = 0;
static int width = 0;
static int height = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (imageToShow == null) {
Toast.makeText(this, "no image!", Toast.LENGTH_LONG).show();
finish();
}
else {
ImageView iv=new ImageView(this);
BitmapFactory.Options opts=new BitmapFactory.Options();
opts.inPurgeable=true;
opts.inInputShareable=true;
opts.inMutable=false;
opts.inSampleSize=2;
Bitmap bitmap = BitmapFactory.decodeByteArray(imageToShow,
0, imageToShow.length, opts);
Bitmap croppedBitmap = Bitmap.createBitmap(bitmap, x, y, width, height);
iv.setImageBitmap(croppedBitmap);
imageToShow=null;
iv.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
setContentView(iv);
}
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity$PlaceholderFragment">
<FrameLayout
android:id="@+id/camera_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<RelativeLayout
android:id="@+id/footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:padding="16dp"
android:background="#ffffff">
<ImageButton
android:id="@+id/pick_existing"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:src="@drawable/ic_launcher"/>
<Button
android:id="@+id/shutter_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Take picture"/>
<ToggleButton
android:id="@+id/flash_toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:padding="20dp"
android:layout_centerVertical="true"
android:textOff=""
android:textOn=""/>
</RelativeLayout>
</RelativeLayout>
I've experimented with adjustPreviewParameters, but there doesn't seem to be any choice that allows me to set the preview to be square.
Can I do what I'm trying to do?