in react-native-pytorch-core/android/src/main/java/org/pytorch/rn/core/camera/CameraView.java [82:170]
private void init() {
cameraProviderFuture = ProcessCameraProvider.getInstance(mReactContext.getCurrentActivity());
// Initialize our background executor
cameraExecutor = Executors.newSingleThreadExecutor();
View mLayout = inflate(mReactContext, R.layout.activity_camera, this);
mPreviewView = mLayout.findViewById(R.id.preview_view);
mCaptureButton = mLayout.findViewById(R.id.capture_button);
mFlipButton = mLayout.findViewById(R.id.flip_button);
// Initialize drawables to change (inner circle stroke)
mCaptureButtonLayerDrawable =
(LayerDrawable)
mReactContext
.getResources()
.getDrawable(R.drawable.camera_button, mReactContext.getTheme())
.mutate();
mCaptureButtonInnerCircle =
(GradientDrawable)
mCaptureButtonLayerDrawable.findDrawableByLayerId(R.id.camera_button_inner_circle);
// Calculate pixel values of borders
float density = mReactContext.getResources().getDisplayMetrics().density;
int cameraButtonInnerBorderNormal = (int) (density * 18);
int cameraButtonInnerBorderPressed = (int) (density * 24);
// Initialize Value Animators and Listeners
// grow means grow border so the circle shrinks
pressAnimation =
ValueAnimator.ofInt(cameraButtonInnerBorderNormal, cameraButtonInnerBorderPressed)
.setDuration(DURATION);
releaseAnimation =
ValueAnimator.ofInt(cameraButtonInnerBorderPressed, cameraButtonInnerBorderNormal)
.setDuration(DURATION);
ValueAnimator.AnimatorUpdateListener animatorUpdateListener =
new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator updatedAnimation) {
int animatedValue = (int) updatedAnimation.getAnimatedValue();
mCaptureButtonInnerCircle.setStroke(animatedValue, Color.TRANSPARENT);
mCaptureButton.setBackground(mCaptureButtonLayerDrawable);
}
};
pressAnimation.addUpdateListener(animatorUpdateListener);
releaseAnimation.addUpdateListener(animatorUpdateListener);
mCaptureButton.setOnTouchListener(
(v, e) -> {
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
pressAnimation.start();
mCaptureButton.animate().scaleX(SCALE_BUTTON_BY).setDuration(DURATION);
mCaptureButton.animate().scaleY(SCALE_BUTTON_BY).setDuration(DURATION);
takePicture();
break;
case MotionEvent.ACTION_UP:
releaseAnimation.start();
mCaptureButton.animate().scaleX(1f).setDuration(DURATION);
mCaptureButton.animate().scaleY(1f).setDuration(DURATION);
}
return false;
});
mFlipButton.setOnTouchListener(
(v, e) -> {
if (e.getAction() == MotionEvent.ACTION_DOWN) {
flipCamera();
}
return false;
});
// The PreviewView has a width/height of 0/0. This was reported as an issue in the CameraX
// issue tracker and is supposedly a bug in how React Native calculates children dimension.
// A manual remeasure of the layout fixes this.
// Link to issue: https://issuetracker.google.com/issues/177245493#comment8
mPreviewView.setOnHierarchyChangeListener(new CameraView.ReactNativeCameraPreviewRemeasure());
if (allPermissionsGranted()) {
startCamera(); // start camera if permission has been granted by user
} else {
int REQUEST_CODE_PERMISSIONS = 200;
ActivityCompat.requestPermissions(
mReactContext.getCurrentActivity(), REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS);
}
}