Add README info

pull/99/head
Mattia Iavarone 8 years ago
parent 135423f974
commit 6c26a3aa85
  1. 150
      README.md
  2. 5
      cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java
  3. 11
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java
  4. 6
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java
  5. 4
      cameraview/src/main/java/com/otaliastudios/cameraview/SizeSelectors.java
  6. 4
      cameraview/src/main/options/com/otaliastudios/cameraview/SessionType.java
  7. 4
      cameraview/src/main/res/values/attrs.xml
  8. 5
      cameraview/src/test/java/com/otaliastudios/cameraview/SizeSelectorsTest.java
  9. 1
      demo/src/main/res/layout/activity_camera.xml

@ -8,7 +8,8 @@
# CameraView # CameraView
CameraView is a well documented, high-level library that makes capturing pictures and videos easy, CameraView is a well documented, high-level library that makes capturing pictures and videos easy,
addressing most of the common issues and needs, and still leaving you with flexibility where needed. See [CHANGELOG](https://github.com/natario1/CameraView/blob/master/CHANGELOG.md). addressing most of the common issues and needs, and still leaving you with flexibility where needed.
See [CHANGELOG](https://github.com/natario1/CameraView/blob/master/CHANGELOG.md).
```groovy ```groovy
compile 'com.otaliastudios:cameraview:1.3.2' compile 'com.otaliastudios:cameraview:1.3.2'
@ -30,10 +31,11 @@ See below for a [list of what was done](#roadmap) and [licensing info](#contribu
- Seamless image and video capturing - Seamless image and video capturing
- **Gestures** support (tap to focus, pinch to zoom and much more) - **Gestures** support (tap to focus, pinch to zoom and much more)
- System permission handling - System permission handling
- Dynamic sizing behavior - Smart sizing behavior
- Create a `CameraView` of **any size** - Preview: Create a `CameraView` of **any size**
- Center inside or center crop behaviors - Preview: Center inside or center crop behaviors
- Automatic output cropping to match your `CameraView` bounds - Output: Handy utilities to set the output size
- Output: Automatic cropping to match your `CameraView` preview bounds
- Built-in **grid drawing** - Built-in **grid drawing**
- Multiple capture methods - Multiple capture methods
- Take high-resolution pictures with `capturePicture` - Take high-resolution pictures with `capturePicture`
@ -55,9 +57,9 @@ See below for a [list of what was done](#roadmap) and [licensing info](#contribu
- [Capturing Video](#capturing-video) - [Capturing Video](#capturing-video)
- [Other camera events](#other-camera-events) - [Other camera events](#other-camera-events)
- [Gestures](#gestures) - [Gestures](#gestures)
- [Dynamic Sizing Behavior](#dynamic-sizing-behavior) - [Sizing Behavior](#sizing-behavior)
- [Center Inside](#center-inside) - [Preview Size](#preview-size)
- [Center Crop](#center-crop) - [Picture Size](#picture-size)
- [Camera Controls](#camera-controls) - [Camera Controls](#camera-controls)
- [Frame Processing](#frame-processing) - [Frame Processing](#frame-processing)
- [Other APIs](#other-apis) - [Other APIs](#other-apis)
@ -78,7 +80,9 @@ To use the CameraView engine, simply add a `CameraView` to your layout:
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
``` ```
`CameraView` has lots of XML attributes, so keep reading. Make sure you override `onResume`, `onPause` and `onDestroy` in your activity or fragment, and call `CameraView.start()`, `stop()` and `destroy()`. `CameraView` has lots of XML attributes, so keep reading. Make sure you override `onResume`,
`onPause` and `onDestroy` in your activity or fragment, and call `CameraView.start()`, `stop()`
and `destroy()`.
```java ```java
@Override @Override
@ -102,7 +106,8 @@ protected void onDestroy() {
### Capturing Images ### Capturing Images
To capture an image just call `CameraView.capturePicture()`. Make sure you setup a `CameraListener` to handle the image callback. To capture an image just call `CameraView.capturePicture()`. Make sure you setup a `CameraListener`
to handle the image callback.
```java ```java
camera.addCameraListener(new CameraListener() { camera.addCameraListener(new CameraListener() {
@ -117,11 +122,14 @@ camera.addCameraListener(new CameraListener() {
camera.capturePicture(); camera.capturePicture();
``` ```
You can also use `camera.captureSnapshot()` to capture a preview frame. This is faster, though will ensure lower quality output. You can also use `camera.captureSnapshot()` to capture a preview frame. This is faster, though will
ensure lower quality output.
### Capturing Video ### Capturing Video
To capture video just call `CameraView.startRecordingVideo(file)` to start, and `CameraView.stopRecordingVideo()` to finish. Make sure you setup a `CameraListener` to handle the video callback. To capture video just call `CameraView.startRecordingVideo(file)` to start, and
`CameraView.stopRecordingVideo()` to finish. Make sure you setup a `CameraListener` to handle
the video callback.
```java ```java
camera.addCameraListener(new CameraListener() { camera.addCameraListener(new CameraListener() {
@ -152,7 +160,8 @@ camera.postDelayed(new Runnable() {
### Other camera events ### Other camera events
Make sure you can react to different camera events by setting up one or more `CameraListener` instances. All these are executed on the UI thread. Make sure you can react to different camera events by setting up one or more `CameraListener`
instances. All these are executed on the UI thread.
```java ```java
camera.addCameraListener(new CameraListener() { camera.addCameraListener(new CameraListener() {
@ -239,7 +248,9 @@ camera.addCameraListener(new CameraListener() {
## Gestures ## Gestures
`CameraView` listen to lots of different gestures inside its bounds. You have the chance to map these gestures to particular actions or camera controls, using `mapGesture()`. This lets you emulate typical behaviors in a single line: `CameraView` listen to lots of different gestures inside its bounds. You have the chance to map
these gestures to particular actions or camera controls, using `mapGesture()`.
This lets you emulate typical behaviors in a single line:
```java ```java
cameraView.mapGesture(Gesture.PINCH, GestureAction.ZOOM); // Pinch to zoom! cameraView.mapGesture(Gesture.PINCH, GestureAction.ZOOM); // Pinch to zoom!
@ -261,19 +272,25 @@ Simple as that. More gestures are coming. There are two things to be noted:
|`SCROLL_VERTICAL` (`cameraGestureScrollVertical`)|Vertical movement gesture.|`zoom` `exposureCorrection` `none`| |`SCROLL_VERTICAL` (`cameraGestureScrollVertical`)|Vertical movement gesture.|`zoom` `exposureCorrection` `none`|
## Dynamic Sizing Behavior ## Sizing Behavior
`CameraView` has a smart measuring behavior that will let you do what you want with a few flags. Measuring is controlled simply by `layout_width` and `layout_height` attributes, with this meaning: ### Preview Size
`CameraView` has a smart measuring behavior that will let you do what you want with a few flags.
Measuring is controlled simply by `layout_width` and `layout_height` attributes, with this meaning:
- `WRAP_CONTENT` : try to stretch this dimension to respect the preview aspect ratio. - `WRAP_CONTENT` : try to stretch this dimension to respect the preview aspect ratio.
- `MATCH_PARENT` : fill this dimension, even if this means ignoring the aspect ratio. - `MATCH_PARENT` : fill this dimension, even if this means ignoring the aspect ratio.
- Fixed values (e.g. `500dp`) : respect this dimension. - Fixed values (e.g. `500dp`) : respect this dimension.
You can have previews of all sizes, not just the supported presets. Whaterever you do, the preview will never be distorted. You can have previews of all sizes, not just the supported presets. Whaterever you do,
the preview will never be distorted.
### Center inside #### Center Inside
You can emulate a **center inside** behavior (like the `ImageView` scaletype) by setting both dimensions to `wrap_content`. The camera will get the biggest possible size that fits into your bounds, just like what happens with image views. You can emulate a **center inside** behavior (like the `ImageView` scaletype) by setting
both dimensions to `wrap_content`. The camera will get the biggest possible size that fits
into your bounds, just like what happens with image views.
```xml ```xml
@ -282,11 +299,15 @@ You can emulate a **center inside** behavior (like the `ImageView` scaletype) by
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
``` ```
This means that the whole preview is visible, and the image output matches what was visible during the capture. This means that the whole preview is visible, and the image output matches what was visible
during the capture.
### Center crop #### Center Crop
You can emulate a **center crop** behavior by setting both dimensions to fixed values or to `MATCH_PARENT`. The camera view will fill the rect. If your dimensions don't match the aspect ratio of the internal preview surface, the surface will be cropped to fill the view, just like `android:scaleType="centerCrop"` on an `ImageView`. You can emulate a **center crop** behavior by setting both dimensions to fixed values or to
`MATCH_PARENT`. The camera view will fill the rect. If your dimensions don't match the aspect ratio
of the internal preview surface, the surface will be cropped to fill the view,
just like `android:scaleType="centerCrop"` on an `ImageView`.
```xml ```xml
<com.otaliastudios.cameraview.CameraView <com.otaliastudios.cameraview.CameraView
@ -294,7 +315,64 @@ You can emulate a **center crop** behavior by setting both dimensions to fixed v
android:layout_height="match_parent" /> android:layout_height="match_parent" />
``` ```
This means that part of the preview is hidden, and the image output will contain parts of the scene that were not visible during the capture. If this is a problem, see [cameraCropOutput](#cameracropoutput). This means that part of the preview is hidden, and the image output will contain parts of the scene
that were not visible during the capture. If this is a problem, see [cameraCropOutput](#cameracropoutput).
### Picture Size
On top of this, you can control the actual size of the output picture, among the list of available sizes.
It is the size of the final JPEG picture. This can be achieved directly through XML, or
using the `SizeSelector` class:
```java
cameraView.setPictureSize(new SizeSelector() {
@Override
public List<Size> select(List<Size> source) {
// Receives a list of available sizes.
// Must return a list of acceptable sizes.
}
});
```
In practice, this is way easier using XML attributes or leveraging the `SizeSelectors` utilities:
|Constraint|XML attr|SizeSelector|
|----------|--------|------------|
|min. width|`app:cameraPictureSizeMinWidth="100"`|`SizeSelectors.minWidth(100)`|
|min. height|`app:cameraPictureSizeMinHeight="100"`|`SizeSelectors.minHeight(100)`|
|max. width|`app:cameraPictureSizeMaxWidth="3000"`|`SizeSelectors.maxWidth(3000)`|
|max. height|`app:cameraPictureSizeMaxHeight="3000"`|`SizeSelectors.maxHeight(3000)`|
|min. area|`app:cameraPictureSizeMinArea="1000000"`|`SizeSelectors.minArea(1000000)`|
|max. area|`app:cameraPictureSizeMaxArea="5000000"`|`SizeSelectors.maxArea(5000000)`|
|aspect ratio|`app:cameraPictureSizeAspectRatio="1:1"`|`SizeSelectors.aspectRatio(AspectRatio.of(1,1), 0)`|
|smallest|`app:cameraPictureSizeSmallest="true"`|`SizeSelectors.smallest()`|
|biggest (**default**)|`app:cameraPictureSizeBiggest="true"`|`SizeSelectors.biggest()`|
If you declare more than one XML constraint, the resulting selector will try to match **all** the
constraints. Be careful - it is very likely that applying lots of constraints will give
empty results.
#### SizeSelectors utilities
For more versatility, or to address selection issues with multiple constraints,
we encourage you to use `SizeSelectors` utilities, that will let you merge different selectors.
This selector will try to find square sizes bigger than 1000x2000. If none is found, it falls back
to just square sizes:
```java
SizeSelector width = SizeSelectors.minWidth(1000);
SizeSelector height = SizeSelectors.minWidth(2000);
SizeSelector dimensions = SizeSelectors.and(width, height); // Matches sizes bigger than 1000x2000.
SizeSelector ratio = SizeSelectors.aspectRatio(AspectRatio.of(1, 1), 0); // Matches 1:1 sizes.
SizeSelector result = SizeSelectors.or(
SizeSelectors.and(ratio, dimensions), // Try to match both constraints
ratio, // If none is found, at least try to match the aspect ratio
SizeSelectors.biggest() // If none is found, take the biggest
);
camera.setPictureSize(result);
```
## Camera controls ## Camera controls
@ -337,10 +415,16 @@ Most camera parameters can be controlled through XML attributes or linked method
What to capture - either picture or video. This has a couple of consequences: What to capture - either picture or video. This has a couple of consequences:
- Sizing: capture and preview size are chosen among the available picture or video sizes, depending on the flag. When `picture`, we choose the max possible picture size and adapt the preview. When `video`, we respect the `videoQuality` choice and adapt the picture and the preview size. - Sizing: picture and preview size are chosen among the available picture or video sizes,
- Picture capturing: due to sizing behavior, capturing pictures in `video` mode might lead to inconsistent results. In this case it is encouraged to use `captureSnapshot` instead, which will capture preview frames. This is fast and thus works well with slower camera sensors. depending on the flag. The picture size is chosen according to the given [size selector](#picture-size).
- Picture capturing: while recording a video, image capturing might work, but it is not guaranteed (it's device dependent) When `video`, in addition, we try to match the `videoQuality` aspect ratio.
- Permission behavior: when requesting a `video` session, the record audio permission will be requested. If this is needed, the audio permission should be added to your manifest or the app will crash. - Picture capturing: due to sizing behavior, capturing pictures in `video` mode might lead to
inconsistent results. In this case it is encouraged to use `captureSnapshot` instead, which will
capture preview frames. This is fast and thus works well with slower camera sensors.
- Picture capturing: while recording a video, image capturing might work, but it is not guaranteed
(it's device dependent)
- Permission behavior: when requesting a `video` session, the record audio permission will be requested.
If this is needed, the audio permission should be added to your manifest or the app will crash.
```java ```java
cameraView.setSessionType(SessionType.PICTURE); cameraView.setSessionType(SessionType.PICTURE);
@ -369,7 +453,8 @@ cameraView.setFlash(Flash.TORCH);
#### cameraGrid #### cameraGrid
Lets you draw grids over the camera preview. Supported values are `off`, `draw3x3` and `draw4x4` for regular grids, and `drawPhi` for a grid based on the golden ratio constant, often used in photography. Lets you draw grids over the camera preview. Supported values are `off`, `draw3x3` and `draw4x4`
for regular grids, and `drawPhi` for a grid based on the golden ratio constant, often used in photography.
```java ```java
cameraView.setGrid(Grid.OFF); cameraView.setGrid(Grid.OFF);
@ -381,7 +466,8 @@ cameraView.setGrid(Grid.DRAW_PHI);
#### cameraCropOutput #### cameraCropOutput
Whether the output picture should be cropped to fit the aspect ratio of the preview surface. Whether the output picture should be cropped to fit the aspect ratio of the preview surface.
This can guarantee consistency between what the user sees and the final output, if you fixed the camera view dimensions. This does not support videos. This can guarantee consistency between what the user sees and the final output, if you fixed
the camera view dimensions. This does not support videos.
#### cameraJpegQuality #### cameraJpegQuality
@ -438,8 +524,8 @@ cameraView.setAudio(Audio.ON);
#### cameraPlaySounds #### cameraPlaySounds
Controls whether we should play platform-provided sounds during certain events (shutter click, focus completed). Controls whether we should play platform-provided sounds during certain events
Please note that: (shutter click, focus completed). Please note that:
- on API < 16, this flag is always set to `false` - on API < 16, this flag is always set to `false`
- the Camera1 engine will always play shutter sounds regardless of this flag - the Camera1 engine will always play shutter sounds regardless of this flag
@ -501,7 +587,6 @@ Other APIs not mentioned above are provided, and are well documented and comment
|`setZoom(float)`, `getZoom()`|Sets a zoom value, where 0 means camera zoomed out and 1 means zoomed in. No-op if zoom is not supported, or camera not started.| |`setZoom(float)`, `getZoom()`|Sets a zoom value, where 0 means camera zoomed out and 1 means zoomed in. No-op if zoom is not supported, or camera not started.|
|`setExposureCorrection(float)`, `getExposureCorrection()`|Sets exposure compensation EV value, in camera stops. No-op if this is not supported. Should be between the bounds returned by CameraOptions.| |`setExposureCorrection(float)`, `getExposureCorrection()`|Sets exposure compensation EV value, in camera stops. No-op if this is not supported. Should be between the bounds returned by CameraOptions.|
|`toggleFacing()`|Toggles the facing value between `Facing.FRONT` and `Facing.BACK`.| |`toggleFacing()`|Toggles the facing value between `Facing.FRONT` and `Facing.BACK`.|
|`toggleFlash()`|Toggles the flash value between `Flash.OFF`, `Flash.ON`, and `Flash.AUTO`.|
|`setLocation(Location)`|Sets location data to be appended to picture/video metadata.| |`setLocation(Location)`|Sets location data to be appended to picture/video metadata.|
|`setLocation(double, double)`|Sets latitude and longitude to be appended to picture/video metadata.| |`setLocation(double, double)`|Sets latitude and longitude to be appended to picture/video metadata.|
|`getLocation()`|Retrieves location data previously applied with setLocation().| |`getLocation()`|Retrieves location data previously applied with setLocation().|
@ -617,6 +702,7 @@ all the code was changed.
- *Frame processor support* - *Frame processor support*
- *inject external loggers* - *inject external loggers*
- *error handling* - *error handling*
- *capture size selectors*
These are still things that need to be done, off the top of my head: These are still things that need to be done, off the top of my head:

@ -887,9 +887,10 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera
if (sizes == null) return null; if (sizes == null) return null;
List<Size> result = new ArrayList<>(sizes.size()); List<Size> result = new ArrayList<>(sizes.size());
for (Camera.Size size : sizes) { for (Camera.Size size : sizes) {
result.add(new Size(size.width, size.height)); Size add = new Size(size.width, size.height);
if (!result.contains(add)) result.add(add);
} }
LOG.i("size:", "previewSizes:", result); LOG.i("size:", "sizesFromList:", result);
return result; return result;
} }
} }

@ -1,7 +1,6 @@
package com.otaliastudios.cameraview; package com.otaliastudios.cameraview;
import android.graphics.PointF; import android.graphics.PointF;
import android.hardware.Camera;
import android.location.Location; import android.location.Location;
@ -14,8 +13,6 @@ import android.support.annotation.Nullable;
import android.support.annotation.WorkerThread; import android.support.annotation.WorkerThread;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
abstract class CameraController implements abstract class CameraController implements
@ -393,6 +390,7 @@ abstract class CameraController implements
// The external selector is expecting stuff in the view world, not in the sensor world. // The external selector is expecting stuff in the view world, not in the sensor world.
// Flip before starting, and then flip again. // Flip before starting, and then flip again.
boolean flip = shouldFlipSizes(); boolean flip = shouldFlipSizes();
LOG.i("computePictureSize:", "flip:", flip);
if (flip) { if (flip) {
for (Size size : captureSizes) { for (Size size : captureSizes) {
size.flip(); size.flip();
@ -402,11 +400,11 @@ abstract class CameraController implements
if (mSessionType == SessionType.PICTURE) { if (mSessionType == SessionType.PICTURE) {
selector = SizeSelectors.or( selector = SizeSelectors.or(
mPictureSizeSelector, mPictureSizeSelector,
SizeSelectors.max() // Fallback to max. SizeSelectors.biggest() // Fallback to biggest.
); );
} else { } else {
// The Camcorder internally checks for cameraParameters.getSupportedVideoSizes() etc. // The Camcorder internally checks for cameraParameters.getSupportedVideoSizes() etc.
// And we want the picture size to be the max picture consistent with the video aspect ratio. // And we want the picture size to be the biggest picture consistent with the video aspect ratio.
// -> Use the external picture selector, but enforce the ratio constraint. // -> Use the external picture selector, but enforce the ratio constraint.
CamcorderProfile profile = getCamcorderProfile(); CamcorderProfile profile = getCamcorderProfile();
AspectRatio targetRatio = AspectRatio.of(profile.videoFrameWidth, profile.videoFrameHeight); AspectRatio targetRatio = AspectRatio.of(profile.videoFrameWidth, profile.videoFrameHeight);
@ -421,6 +419,7 @@ abstract class CameraController implements
} }
Size result = selector.select(captureSizes).get(0); Size result = selector.select(captureSizes).get(0);
LOG.i("computePictureSize:", "result:", result);
if (flip) result.flip(); if (flip) result.flip();
return result; return result;
} }
@ -436,7 +435,7 @@ abstract class CameraController implements
SizeSelector matchAll = SizeSelectors.or( SizeSelector matchAll = SizeSelectors.or(
SizeSelectors.and(matchRatio, matchSize), SizeSelectors.and(matchRatio, matchSize),
matchRatio, // If couldn't match both, match ratio. matchRatio, // If couldn't match both, match ratio.
SizeSelectors.max() // If couldn't match any, take the biggest. SizeSelectors.biggest() // If couldn't match any, take the biggest.
); );
return matchAll.select(previewSizes).get(0); return matchAll.select(previewSizes).get(0);
} }

@ -132,11 +132,11 @@ public class CameraView extends FrameLayout {
//noinspection ConstantConditions //noinspection ConstantConditions
constraints.add(SizeSelectors.aspectRatio(AspectRatio.parse(a.getString(R.styleable.CameraView_cameraPictureSizeAspectRatio)), 0)); constraints.add(SizeSelectors.aspectRatio(AspectRatio.parse(a.getString(R.styleable.CameraView_cameraPictureSizeAspectRatio)), 0));
} }
if (a.getBoolean(R.styleable.CameraView_cameraPictureSizeMin, false)) constraints.add(SizeSelectors.min()); if (a.getBoolean(R.styleable.CameraView_cameraPictureSizeSmallest, false)) constraints.add(SizeSelectors.smallest());
if (a.getBoolean(R.styleable.CameraView_cameraPictureSizeMax, false)) constraints.add(SizeSelectors.max()); if (a.getBoolean(R.styleable.CameraView_cameraPictureSizeBiggest, false)) constraints.add(SizeSelectors.biggest());
SizeSelector selector = !constraints.isEmpty() ? SizeSelector selector = !constraints.isEmpty() ?
SizeSelectors.and(constraints.toArray(new SizeSelector[constraints.size()])) : SizeSelectors.and(constraints.toArray(new SizeSelector[constraints.size()])) :
SizeSelectors.max(); SizeSelectors.biggest();
// Gestures // Gestures
GestureAction tapGesture = GestureAction.fromValue(a.getInteger(R.styleable.CameraView_cameraGestureTap, GestureAction.DEFAULT_TAP.value())); GestureAction tapGesture = GestureAction.fromValue(a.getInteger(R.styleable.CameraView_cameraGestureTap, GestureAction.DEFAULT_TAP.value()));

@ -120,7 +120,7 @@ public class SizeSelectors {
* *
* @return a new selector * @return a new selector
*/ */
public static SizeSelector max() { public static SizeSelector biggest() {
return new SizeSelector() { return new SizeSelector() {
@NonNull @NonNull
@Override @Override
@ -138,7 +138,7 @@ public class SizeSelectors {
* *
* @return a new selector * @return a new selector
*/ */
public static SizeSelector min() { public static SizeSelector smallest() {
return new SizeSelector() { return new SizeSelector() {
@NonNull @NonNull
@Override @Override

@ -16,7 +16,7 @@ public enum SessionType {
* *
* - Trying to take videos in this session will throw an exception * - Trying to take videos in this session will throw an exception
* - Only the camera permission is requested * - Only the camera permission is requested
* - Preview and capture size is chosen as the max available size * - Capture size is chosen according to the current picture size selector
*/ */
PICTURE(0), PICTURE(0),
@ -26,7 +26,7 @@ public enum SessionType {
* - Trying to take pictures in this session will work, though with lower quality * - Trying to take pictures in this session will work, though with lower quality
* - Trying to take pictures while recording a video will work if supported * - Trying to take pictures while recording a video will work if supported
* - Camera and audio record permissions are requested * - Camera and audio record permissions are requested
* - Preview and capture size are chosen to respect the {@link VideoQuality} aspect ratio * - Capture size is chosen trying to respect the {@link VideoQuality} aspect ratio
* *
* @see CameraOptions#isVideoSnapshotSupported() * @see CameraOptions#isVideoSnapshotSupported()
*/ */

@ -14,9 +14,9 @@
<attr name="cameraPictureSizeMaxArea" format="integer|reference" /> <attr name="cameraPictureSizeMaxArea" format="integer|reference" />
<attr name="cameraPictureSizeMin" format="boolean"/> <attr name="cameraPictureSizeSmallest" format="boolean"/>
<attr name="cameraPictureSizeMax" format="boolean"/> <attr name="cameraPictureSizeBiggest" format="boolean"/>
<attr name="cameraPictureSizeAspectRatio" format="string|reference"/> <attr name="cameraPictureSizeAspectRatio" format="string|reference"/>

@ -3,7 +3,6 @@ package com.otaliastudios.cameraview;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mockito;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -96,7 +95,7 @@ public class SizeSelectorsTest {
@Test @Test
public void testMax() { public void testMax() {
SizeSelector selector = SizeSelectors.max(); SizeSelector selector = SizeSelectors.biggest();
List<Size> list = selector.select(input); List<Size> list = selector.select(input);
assertEquals(list.size(), input.size()); assertEquals(list.size(), input.size());
assertEquals(list.get(0), new Size(2000, 4000)); assertEquals(list.get(0), new Size(2000, 4000));
@ -104,7 +103,7 @@ public class SizeSelectorsTest {
@Test @Test
public void testMin() { public void testMin() {
SizeSelector selector = SizeSelectors.min(); SizeSelector selector = SizeSelectors.smallest();
List<Size> list = selector.select(input); List<Size> list = selector.select(input);
assertEquals(list.size(), input.size()); assertEquals(list.size(), input.size());
assertTrue(list.get(0).equals(new Size(30, 40)) || list.get(0).equals(new Size(40, 30))); assertTrue(list.get(0).equals(new Size(30, 40)) || list.get(0).equals(new Size(40, 30)));

@ -15,6 +15,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="center" android:layout_gravity="center"
android:keepScreenOn="true" android:keepScreenOn="true"
app:cameraPlaySounds="true"
app:cameraGrid="off" app:cameraGrid="off"
app:cameraCropOutput="false" app:cameraCropOutput="false"
app:cameraFacing="back" app:cameraFacing="back"

Loading…
Cancel
Save