parent
0c7726d5c5
commit
7603a0f11b
@ -1,6 +1,8 @@ |
|||||||
package com.otaliastudios.cameraview; |
package com.otaliastudios.cameraview.controls; |
||||||
|
|
||||||
|
|
||||||
|
import com.otaliastudios.cameraview.CameraView; |
||||||
|
|
||||||
import androidx.annotation.Nullable; |
import androidx.annotation.Nullable; |
||||||
|
|
||||||
/** |
/** |
@ -1,4 +1,4 @@ |
|||||||
package com.otaliastudios.cameraview; |
package com.otaliastudios.cameraview.controls; |
||||||
|
|
||||||
/** |
/** |
||||||
* Base interface for controls like {@link Audio}, |
* Base interface for controls like {@link Audio}, |
@ -0,0 +1,72 @@ |
|||||||
|
package com.otaliastudios.cameraview.controls; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.content.res.TypedArray; |
||||||
|
|
||||||
|
import com.otaliastudios.cameraview.R; |
||||||
|
|
||||||
|
import androidx.annotation.NonNull; |
||||||
|
|
||||||
|
/** |
||||||
|
* Parses controls from XML attributes. |
||||||
|
*/ |
||||||
|
public class ControlParser { |
||||||
|
|
||||||
|
private int preview; |
||||||
|
private int facing; |
||||||
|
private int flash; |
||||||
|
private int grid; |
||||||
|
private int whiteBalance; |
||||||
|
private int mode; |
||||||
|
private int hdr; |
||||||
|
private int audio; |
||||||
|
private int videoCodec; |
||||||
|
|
||||||
|
public ControlParser(@NonNull Context context, @NonNull TypedArray array) { |
||||||
|
this.preview = array.getInteger(R.styleable.CameraView_cameraPreview, Preview.DEFAULT.value()); |
||||||
|
this.facing = array.getInteger(R.styleable.CameraView_cameraFacing, Facing.DEFAULT(context).value()); |
||||||
|
this.flash = array.getInteger(R.styleable.CameraView_cameraFlash, Flash.DEFAULT.value()); |
||||||
|
this.grid = array.getInteger(R.styleable.CameraView_cameraGrid, Grid.DEFAULT.value()); |
||||||
|
this.whiteBalance = array.getInteger(R.styleable.CameraView_cameraWhiteBalance, WhiteBalance.DEFAULT.value()); |
||||||
|
this.mode = array.getInteger(R.styleable.CameraView_cameraMode, Mode.DEFAULT.value()); |
||||||
|
this.hdr = array.getInteger(R.styleable.CameraView_cameraHdr, Hdr.DEFAULT.value()); |
||||||
|
this.audio = array.getInteger(R.styleable.CameraView_cameraAudio, Audio.DEFAULT.value()); |
||||||
|
this.videoCodec = array.getInteger(R.styleable.CameraView_cameraVideoCodec, VideoCodec.DEFAULT.value()); |
||||||
|
} |
||||||
|
|
||||||
|
public Preview getPreview() { |
||||||
|
return Preview.fromValue(preview); |
||||||
|
} |
||||||
|
|
||||||
|
public Facing getFacing() { |
||||||
|
return Facing.fromValue(facing); |
||||||
|
} |
||||||
|
|
||||||
|
public Flash getFlash() { |
||||||
|
return Flash.fromValue(flash); |
||||||
|
} |
||||||
|
|
||||||
|
public Grid getGrid() { |
||||||
|
return Grid.fromValue(grid); |
||||||
|
} |
||||||
|
|
||||||
|
public Mode getMode() { |
||||||
|
return Mode.fromValue(mode); |
||||||
|
} |
||||||
|
|
||||||
|
public WhiteBalance getWhiteBalance() { |
||||||
|
return WhiteBalance.fromValue(whiteBalance); |
||||||
|
} |
||||||
|
|
||||||
|
public Hdr getHdr() { |
||||||
|
return Hdr.fromValue(hdr); |
||||||
|
} |
||||||
|
|
||||||
|
public Audio getAudio() { |
||||||
|
return Audio.fromValue(audio); |
||||||
|
} |
||||||
|
|
||||||
|
public VideoCodec getVideoCodec() { |
||||||
|
return VideoCodec.fromValue(videoCodec); |
||||||
|
} |
||||||
|
} |
@ -1,7 +1,11 @@ |
|||||||
package com.otaliastudios.cameraview; |
package com.otaliastudios.cameraview.controls; |
||||||
|
|
||||||
|
|
||||||
import android.content.Context; |
import android.content.Context; |
||||||
|
|
||||||
|
import com.otaliastudios.cameraview.CameraUtils; |
||||||
|
import com.otaliastudios.cameraview.CameraView; |
||||||
|
|
||||||
import androidx.annotation.NonNull; |
import androidx.annotation.NonNull; |
||||||
import androidx.annotation.Nullable; |
import androidx.annotation.Nullable; |
||||||
|
|
@ -1,6 +1,9 @@ |
|||||||
package com.otaliastudios.cameraview; |
package com.otaliastudios.cameraview.controls; |
||||||
|
|
||||||
|
|
||||||
|
import com.otaliastudios.cameraview.CameraOptions; |
||||||
|
import com.otaliastudios.cameraview.CameraView; |
||||||
|
|
||||||
import androidx.annotation.Nullable; |
import androidx.annotation.Nullable; |
||||||
|
|
||||||
/** |
/** |
@ -1,6 +1,8 @@ |
|||||||
package com.otaliastudios.cameraview; |
package com.otaliastudios.cameraview.controls; |
||||||
|
|
||||||
|
|
||||||
|
import com.otaliastudios.cameraview.CameraView; |
||||||
|
|
||||||
import androidx.annotation.Nullable; |
import androidx.annotation.Nullable; |
||||||
|
|
||||||
/** |
/** |
@ -1,6 +1,8 @@ |
|||||||
package com.otaliastudios.cameraview; |
package com.otaliastudios.cameraview.controls; |
||||||
|
|
||||||
|
|
||||||
|
import com.otaliastudios.cameraview.CameraView; |
||||||
|
|
||||||
import androidx.annotation.Nullable; |
import androidx.annotation.Nullable; |
||||||
|
|
||||||
/** |
/** |
@ -1,6 +1,8 @@ |
|||||||
package com.otaliastudios.cameraview; |
package com.otaliastudios.cameraview.controls; |
||||||
|
|
||||||
|
|
||||||
|
import com.otaliastudios.cameraview.CameraView; |
||||||
|
|
||||||
import androidx.annotation.Nullable; |
import androidx.annotation.Nullable; |
||||||
|
|
||||||
import java.io.File; |
import java.io.File; |
@ -1,6 +1,8 @@ |
|||||||
package com.otaliastudios.cameraview; |
package com.otaliastudios.cameraview.controls; |
||||||
|
|
||||||
|
|
||||||
|
import com.otaliastudios.cameraview.CameraView; |
||||||
|
|
||||||
import androidx.annotation.Nullable; |
import androidx.annotation.Nullable; |
||||||
|
|
||||||
/** |
/** |
@ -1,7 +1,8 @@ |
|||||||
package com.otaliastudios.cameraview; |
package com.otaliastudios.cameraview.controls; |
||||||
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull; |
import com.otaliastudios.cameraview.CameraView; |
||||||
|
|
||||||
import androidx.annotation.Nullable; |
import androidx.annotation.Nullable; |
||||||
|
|
||||||
/** |
/** |
@ -1,6 +1,9 @@ |
|||||||
package com.otaliastudios.cameraview; |
package com.otaliastudios.cameraview.controls; |
||||||
|
|
||||||
|
|
||||||
|
import com.otaliastudios.cameraview.CameraOptions; |
||||||
|
import com.otaliastudios.cameraview.CameraView; |
||||||
|
|
||||||
import androidx.annotation.Nullable; |
import androidx.annotation.Nullable; |
||||||
|
|
||||||
/** |
/** |
@ -0,0 +1,159 @@ |
|||||||
|
package com.otaliastudios.cameraview.gesture; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.graphics.PointF; |
||||||
|
import androidx.annotation.NonNull; |
||||||
|
import android.view.MotionEvent; |
||||||
|
import android.widget.FrameLayout; |
||||||
|
|
||||||
|
/** |
||||||
|
* Base class for gesture layouts, that is, layouts that will capture |
||||||
|
* gestures. |
||||||
|
*/ |
||||||
|
public abstract class GestureLayout extends FrameLayout { |
||||||
|
|
||||||
|
// The number of possible values between minValue and maxValue, for the getValue method.
|
||||||
|
// We could make this non-static (e.g. larger granularity for exposure correction).
|
||||||
|
private final static int GRANULARITY = 50; |
||||||
|
private boolean mActive; |
||||||
|
private Gesture mType; |
||||||
|
private PointF[] mPoints; |
||||||
|
|
||||||
|
GestureLayout(@NonNull Context context, int points) { |
||||||
|
super(context); |
||||||
|
mPoints = new PointF[points]; |
||||||
|
for (int i = 0; i < points; i++) { |
||||||
|
mPoints[i] = new PointF(0, 0); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Makes this instance active, which means, listening to events. |
||||||
|
* @param active whether this should be active or not |
||||||
|
*/ |
||||||
|
public void setActive(boolean active) { |
||||||
|
mActive = active; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Whether this instance is active, which means, it is listening |
||||||
|
* to events and identifying new gestures. |
||||||
|
* @return true if active |
||||||
|
*/ |
||||||
|
public boolean isActive() { |
||||||
|
return mActive; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Called when new events are available. |
||||||
|
* If true is returned, users will call {@link #getGesture()}, {@link #getPoints()} |
||||||
|
* and maybe {@link #getValue(float, float, float)} to know more about the gesture. |
||||||
|
* |
||||||
|
* @param event the new event |
||||||
|
* @return true if a gesture was detected |
||||||
|
*/ |
||||||
|
public final boolean onTouchEvent(@NonNull MotionEvent event) { |
||||||
|
if (!mActive) return false; |
||||||
|
return handleTouchEvent(event); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Called when new events are available. |
||||||
|
* If true is returned, users will call {@link #getGesture()}, {@link #getPoints()} |
||||||
|
* and maybe {@link #getValue(float, float, float)} to know more about the gesture. |
||||||
|
* |
||||||
|
* @param event the new event |
||||||
|
* @return true if a gesture was detected |
||||||
|
*/ |
||||||
|
protected abstract boolean handleTouchEvent(@NonNull MotionEvent event); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the gesture that this instance is currently detecting. |
||||||
|
* This is mutable - for instance, a scroll layout can detect both |
||||||
|
* horizontal and vertical scroll gestures. |
||||||
|
* |
||||||
|
* @return the current gesture |
||||||
|
*/ |
||||||
|
@NonNull |
||||||
|
public final Gesture getGesture() { |
||||||
|
return mType; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the currently detected gesture. |
||||||
|
* @see #getGesture() |
||||||
|
* |
||||||
|
* @param gesture the current gesture |
||||||
|
*/ |
||||||
|
protected final void setGesture(Gesture gesture) { |
||||||
|
mType = gesture; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns an array of points that identify the currently |
||||||
|
* detected gesture. If no gesture was detected, this returns |
||||||
|
* an array of points with x and y set to 0. |
||||||
|
* |
||||||
|
* @return array of gesture points |
||||||
|
*/ |
||||||
|
@NonNull |
||||||
|
public final PointF[] getPoints() { |
||||||
|
return mPoints; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Utility function to access an item in the |
||||||
|
* {@link #getPoints()} array. |
||||||
|
* |
||||||
|
* @param which the array position |
||||||
|
* @return the point |
||||||
|
*/ |
||||||
|
@NonNull |
||||||
|
protected final PointF getPoint(int which) { |
||||||
|
return mPoints[which]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* For {@link GestureType#CONTINUOUS} gestures, returns the float value at the current |
||||||
|
* gesture state. This means, for example, scaling the old value with a pinch factor, |
||||||
|
* taking into account the minimum and maximum values. |
||||||
|
* |
||||||
|
* @param currValue the last value |
||||||
|
* @param minValue the min possible value |
||||||
|
* @param maxValue the max possible value |
||||||
|
* @return the new continuous value |
||||||
|
*/ |
||||||
|
public final float computeValue(float currValue, float minValue, float maxValue) { |
||||||
|
return capValue(currValue, getValue(currValue, minValue, maxValue), minValue, maxValue); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* For {@link GestureType#CONTINUOUS} gestures, returns the float value at the current |
||||||
|
* gesture state. This means, for example, scaling the old value with a pinch factor, |
||||||
|
* taking into account the minimum and maximum values. |
||||||
|
* |
||||||
|
* @param currValue the last value |
||||||
|
* @param minValue the min possible value |
||||||
|
* @param maxValue the max possible value |
||||||
|
* @return the new continuous value |
||||||
|
*/ |
||||||
|
protected abstract float getValue(float currValue, float minValue, float maxValue); |
||||||
|
|
||||||
|
/** |
||||||
|
* Checks for newValue to be between minValue and maxValue, |
||||||
|
* and checks that it is 'far enough' from the oldValue, in order |
||||||
|
* to reduce useless updates. |
||||||
|
*/ |
||||||
|
private static float capValue(float oldValue, float newValue, float minValue, float maxValue) { |
||||||
|
if (newValue < minValue) newValue = minValue; |
||||||
|
if (newValue > maxValue) newValue = maxValue; |
||||||
|
|
||||||
|
float distance = (maxValue - minValue) / (float) GRANULARITY; |
||||||
|
float half = distance / 2; |
||||||
|
if (newValue >= oldValue - half && newValue <= oldValue + half) { |
||||||
|
// Too close! Return the oldValue.
|
||||||
|
return oldValue; |
||||||
|
} |
||||||
|
return newValue; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,53 @@ |
|||||||
|
package com.otaliastudios.cameraview.gesture; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.content.res.TypedArray; |
||||||
|
|
||||||
|
import com.otaliastudios.cameraview.R; |
||||||
|
|
||||||
|
import androidx.annotation.NonNull; |
||||||
|
|
||||||
|
/** |
||||||
|
* Parses gestures from XML attributes. |
||||||
|
*/ |
||||||
|
public class GestureParser { |
||||||
|
|
||||||
|
private int tapAction; |
||||||
|
private int longTapAction; |
||||||
|
private int pinchAction; |
||||||
|
private int horizontalScrollAction; |
||||||
|
private int verticalScrollAction; |
||||||
|
|
||||||
|
public GestureParser(@NonNull TypedArray array) { |
||||||
|
this.tapAction = array.getInteger(R.styleable.CameraView_cameraGestureTap, GestureAction.DEFAULT_TAP.value()); |
||||||
|
this.longTapAction = array.getInteger(R.styleable.CameraView_cameraGestureLongTap, GestureAction.DEFAULT_LONG_TAP.value()); |
||||||
|
this.pinchAction = array.getInteger(R.styleable.CameraView_cameraGesturePinch, GestureAction.DEFAULT_PINCH.value()); |
||||||
|
this.horizontalScrollAction = array.getInteger(R.styleable.CameraView_cameraGestureScrollHorizontal, GestureAction.DEFAULT_SCROLL_HORIZONTAL.value()); |
||||||
|
this.verticalScrollAction = array.getInteger(R.styleable.CameraView_cameraGestureScrollVertical, GestureAction.DEFAULT_SCROLL_VERTICAL.value()); |
||||||
|
} |
||||||
|
|
||||||
|
private GestureAction get(int which) { |
||||||
|
return GestureAction.fromValue(which); |
||||||
|
} |
||||||
|
|
||||||
|
public GestureAction getTapAction() { |
||||||
|
return get(tapAction); |
||||||
|
} |
||||||
|
|
||||||
|
public GestureAction getLongTapAction() { |
||||||
|
return get(longTapAction); |
||||||
|
} |
||||||
|
|
||||||
|
public GestureAction getPinchAction() { |
||||||
|
return get(pinchAction); |
||||||
|
} |
||||||
|
|
||||||
|
public GestureAction getHorizontalScrollAction() { |
||||||
|
return get(horizontalScrollAction); |
||||||
|
} |
||||||
|
|
||||||
|
public GestureAction getVerticalScrollAction() { |
||||||
|
return get(verticalScrollAction); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
package com.otaliastudios.cameraview.gesture; |
||||||
|
|
||||||
|
|
||||||
|
import com.otaliastudios.cameraview.CameraView; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import androidx.annotation.NonNull; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Gestures and gesture actions can both have a type. For a gesture to be able to be mapped to |
||||||
|
* a certain {@link GestureAction}, both of them might be of the same type. |
||||||
|
*/ |
||||||
|
public enum GestureType { |
||||||
|
|
||||||
|
/** |
||||||
|
* Defines gestures or gesture actions that consist of a single operation. |
||||||
|
* Gesture example: a tap. |
||||||
|
* Gesture action example: taking a picture. |
||||||
|
*/ |
||||||
|
ONE_SHOT, |
||||||
|
|
||||||
|
/** |
||||||
|
* Defines gestures or gesture actions that consist of a continuous operation. |
||||||
|
* Gesture example: pinching. |
||||||
|
* Gesture action example: controlling zoom. |
||||||
|
*/ |
||||||
|
CONTINUOUS |
||||||
|
} |
@ -1,4 +1,6 @@ |
|||||||
package com.otaliastudios.cameraview; |
package com.otaliastudios.cameraview.size; |
||||||
|
|
||||||
|
import com.otaliastudios.cameraview.size.Size; |
||||||
|
|
||||||
import androidx.annotation.NonNull; |
import androidx.annotation.NonNull; |
||||||
|
|
@ -0,0 +1,102 @@ |
|||||||
|
package com.otaliastudios.cameraview.size; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.content.res.TypedArray; |
||||||
|
|
||||||
|
import com.otaliastudios.cameraview.R; |
||||||
|
import com.otaliastudios.cameraview.controls.Audio; |
||||||
|
import com.otaliastudios.cameraview.controls.Facing; |
||||||
|
import com.otaliastudios.cameraview.controls.Flash; |
||||||
|
import com.otaliastudios.cameraview.controls.Grid; |
||||||
|
import com.otaliastudios.cameraview.controls.Hdr; |
||||||
|
import com.otaliastudios.cameraview.controls.Mode; |
||||||
|
import com.otaliastudios.cameraview.controls.Preview; |
||||||
|
import com.otaliastudios.cameraview.controls.VideoCodec; |
||||||
|
import com.otaliastudios.cameraview.controls.WhiteBalance; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import androidx.annotation.NonNull; |
||||||
|
|
||||||
|
/** |
||||||
|
* Parses size selectors from XML attributes. |
||||||
|
*/ |
||||||
|
public class SizeSelectorParser { |
||||||
|
|
||||||
|
private SizeSelector pictureSizeSelector; |
||||||
|
private SizeSelector videoSizeSelector; |
||||||
|
|
||||||
|
public SizeSelectorParser(@NonNull TypedArray array) { |
||||||
|
List<SizeSelector> pictureConstraints = new ArrayList<>(3); |
||||||
|
if (array.hasValue(R.styleable.CameraView_cameraPictureSizeMinWidth)) { |
||||||
|
pictureConstraints.add(SizeSelectors.minWidth(array.getInteger(R.styleable.CameraView_cameraPictureSizeMinWidth, 0))); |
||||||
|
} |
||||||
|
if (array.hasValue(R.styleable.CameraView_cameraPictureSizeMaxWidth)) { |
||||||
|
pictureConstraints.add(SizeSelectors.maxWidth(array.getInteger(R.styleable.CameraView_cameraPictureSizeMaxWidth, 0))); |
||||||
|
} |
||||||
|
if (array.hasValue(R.styleable.CameraView_cameraPictureSizeMinHeight)) { |
||||||
|
pictureConstraints.add(SizeSelectors.minHeight(array.getInteger(R.styleable.CameraView_cameraPictureSizeMinHeight, 0))); |
||||||
|
} |
||||||
|
if (array.hasValue(R.styleable.CameraView_cameraPictureSizeMaxHeight)) { |
||||||
|
pictureConstraints.add(SizeSelectors.maxHeight(array.getInteger(R.styleable.CameraView_cameraPictureSizeMaxHeight, 0))); |
||||||
|
} |
||||||
|
if (array.hasValue(R.styleable.CameraView_cameraPictureSizeMinArea)) { |
||||||
|
pictureConstraints.add(SizeSelectors.minArea(array.getInteger(R.styleable.CameraView_cameraPictureSizeMinArea, 0))); |
||||||
|
} |
||||||
|
if (array.hasValue(R.styleable.CameraView_cameraPictureSizeMaxArea)) { |
||||||
|
pictureConstraints.add(SizeSelectors.maxArea(array.getInteger(R.styleable.CameraView_cameraPictureSizeMaxArea, 0))); |
||||||
|
} |
||||||
|
if (array.hasValue(R.styleable.CameraView_cameraPictureSizeAspectRatio)) { |
||||||
|
//noinspection ConstantConditions
|
||||||
|
pictureConstraints.add(SizeSelectors.aspectRatio(AspectRatio.parse(array.getString(R.styleable.CameraView_cameraPictureSizeAspectRatio)), 0)); |
||||||
|
} |
||||||
|
|
||||||
|
if (array.getBoolean(R.styleable.CameraView_cameraPictureSizeSmallest, false)) pictureConstraints.add(SizeSelectors.smallest()); |
||||||
|
if (array.getBoolean(R.styleable.CameraView_cameraPictureSizeBiggest, false)) pictureConstraints.add(SizeSelectors.biggest()); |
||||||
|
pictureSizeSelector = !pictureConstraints.isEmpty() ? |
||||||
|
SizeSelectors.and(pictureConstraints.toArray(new SizeSelector[0])) : |
||||||
|
SizeSelectors.biggest(); |
||||||
|
|
||||||
|
// Video size selector
|
||||||
|
List<SizeSelector> videoConstraints = new ArrayList<>(3); |
||||||
|
if (array.hasValue(R.styleable.CameraView_cameraVideoSizeMinWidth)) { |
||||||
|
videoConstraints.add(SizeSelectors.minWidth(array.getInteger(R.styleable.CameraView_cameraVideoSizeMinWidth, 0))); |
||||||
|
} |
||||||
|
if (array.hasValue(R.styleable.CameraView_cameraVideoSizeMaxWidth)) { |
||||||
|
videoConstraints.add(SizeSelectors.maxWidth(array.getInteger(R.styleable.CameraView_cameraVideoSizeMaxWidth, 0))); |
||||||
|
} |
||||||
|
if (array.hasValue(R.styleable.CameraView_cameraVideoSizeMinHeight)) { |
||||||
|
videoConstraints.add(SizeSelectors.minHeight(array.getInteger(R.styleable.CameraView_cameraVideoSizeMinHeight, 0))); |
||||||
|
} |
||||||
|
if (array.hasValue(R.styleable.CameraView_cameraVideoSizeMaxHeight)) { |
||||||
|
videoConstraints.add(SizeSelectors.maxHeight(array.getInteger(R.styleable.CameraView_cameraVideoSizeMaxHeight, 0))); |
||||||
|
} |
||||||
|
if (array.hasValue(R.styleable.CameraView_cameraVideoSizeMinArea)) { |
||||||
|
videoConstraints.add(SizeSelectors.minArea(array.getInteger(R.styleable.CameraView_cameraVideoSizeMinArea, 0))); |
||||||
|
} |
||||||
|
if (array.hasValue(R.styleable.CameraView_cameraVideoSizeMaxArea)) { |
||||||
|
videoConstraints.add(SizeSelectors.maxArea(array.getInteger(R.styleable.CameraView_cameraVideoSizeMaxArea, 0))); |
||||||
|
} |
||||||
|
if (array.hasValue(R.styleable.CameraView_cameraVideoSizeAspectRatio)) { |
||||||
|
//noinspection ConstantConditions
|
||||||
|
videoConstraints.add(SizeSelectors.aspectRatio(AspectRatio.parse(array.getString(R.styleable.CameraView_cameraVideoSizeAspectRatio)), 0)); |
||||||
|
} |
||||||
|
if (array.getBoolean(R.styleable.CameraView_cameraVideoSizeSmallest, false)) videoConstraints.add(SizeSelectors.smallest()); |
||||||
|
if (array.getBoolean(R.styleable.CameraView_cameraVideoSizeBiggest, false)) videoConstraints.add(SizeSelectors.biggest()); |
||||||
|
videoSizeSelector = !videoConstraints.isEmpty() ? |
||||||
|
SizeSelectors.and(videoConstraints.toArray(new SizeSelector[0])) : |
||||||
|
SizeSelectors.biggest(); |
||||||
|
} |
||||||
|
|
||||||
|
@NonNull |
||||||
|
public SizeSelector getPictureSizeSelector() { |
||||||
|
return pictureSizeSelector; |
||||||
|
} |
||||||
|
|
||||||
|
@NonNull |
||||||
|
public SizeSelector getVideoSizeSelector() { |
||||||
|
return videoSizeSelector; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -1,4 +1,8 @@ |
|||||||
package com.otaliastudios.cameraview; |
package com.otaliastudios.cameraview.size; |
||||||
|
|
||||||
|
import com.otaliastudios.cameraview.size.AspectRatio; |
||||||
|
import com.otaliastudios.cameraview.size.Size; |
||||||
|
import com.otaliastudios.cameraview.size.SizeSelector; |
||||||
|
|
||||||
import androidx.annotation.NonNull; |
import androidx.annotation.NonNull; |
||||||
|
|
@ -1,70 +0,0 @@ |
|||||||
package com.otaliastudios.cameraview; |
|
||||||
|
|
||||||
import android.content.Context; |
|
||||||
import android.graphics.PointF; |
|
||||||
import androidx.annotation.NonNull; |
|
||||||
import android.view.MotionEvent; |
|
||||||
import android.widget.FrameLayout; |
|
||||||
|
|
||||||
abstract class GestureLayout extends FrameLayout { |
|
||||||
|
|
||||||
// The number of possible values between minValue and maxValue, for the scaleValue method.
|
|
||||||
// We could make this non-static (e.g. larger granularity for exposure correction).
|
|
||||||
private final static int GRANULARITY = 50; |
|
||||||
|
|
||||||
protected boolean mEnabled; |
|
||||||
protected Gesture mType; |
|
||||||
protected PointF[] mPoints; |
|
||||||
|
|
||||||
public GestureLayout(@NonNull Context context) { |
|
||||||
super(context); |
|
||||||
onInitialize(context); |
|
||||||
} |
|
||||||
|
|
||||||
protected void onInitialize(@NonNull Context context) { |
|
||||||
} |
|
||||||
|
|
||||||
public void enable(boolean enable) { |
|
||||||
mEnabled = enable; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean enabled() { |
|
||||||
return mEnabled; |
|
||||||
} |
|
||||||
|
|
||||||
public abstract boolean onTouchEvent(MotionEvent event); |
|
||||||
|
|
||||||
@NonNull |
|
||||||
public final Gesture getGestureType() { |
|
||||||
return mType; |
|
||||||
} |
|
||||||
|
|
||||||
// For tests.
|
|
||||||
void setGestureType(@NonNull Gesture type) { |
|
||||||
mType = type; |
|
||||||
} |
|
||||||
|
|
||||||
@NonNull |
|
||||||
public final PointF[] getPoints() { |
|
||||||
return mPoints; |
|
||||||
} |
|
||||||
|
|
||||||
// Implementors should call capValue at the end.
|
|
||||||
public abstract float scaleValue(float currValue, float minValue, float maxValue); |
|
||||||
|
|
||||||
// Checks for newValue to be between minValue and maxValue,
|
|
||||||
// and checks that it is 'far enough' from the oldValue, in order
|
|
||||||
// to reduce useless updates.
|
|
||||||
protected static float capValue(float oldValue, float newValue, float minValue, float maxValue) { |
|
||||||
if (newValue < minValue) newValue = minValue; |
|
||||||
if (newValue > maxValue) newValue = maxValue; |
|
||||||
|
|
||||||
float distance = (maxValue - minValue) / (float) GRANULARITY; |
|
||||||
float half = distance / 2; |
|
||||||
if (newValue >= oldValue - half && newValue <= oldValue + half) { |
|
||||||
// Too close! Return the oldValue.
|
|
||||||
return oldValue; |
|
||||||
} |
|
||||||
return newValue; |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue