fix preview and capture resolutions
- adjust the preview so the image captured is what the user sees - add method MySize.isSupported; current support is for full, 16:9, 4:3 and 1:1 of the highest resolution - cleanup ImageQualityManager, add method to get the full screen resolution which is just the resolution with the largest width - change the UI to move settings to the top and remove the auto fading
This commit is contained in:
parent
f6235e3b96
commit
d9193f7494
|
@ -10,7 +10,7 @@ import android.os.Handler
|
|||
import android.os.Looper
|
||||
import android.provider.MediaStore
|
||||
import android.view.*
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
|
||||
|
@ -32,7 +32,6 @@ import kotlinx.android.synthetic.main.activity_main.*
|
|||
|
||||
class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, CameraXPreviewListener {
|
||||
companion object {
|
||||
private const val FADE_DELAY = 5000L
|
||||
private const val CAPTURE_ANIMATION_DURATION = 100L
|
||||
}
|
||||
|
||||
|
@ -84,7 +83,6 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
|||
if (hasStorageAndCameraPermissions()) {
|
||||
resumeCameraItems()
|
||||
setupPreviewImage(mIsInPhotoMode)
|
||||
scheduleFadeOut()
|
||||
mFocusCircleView.setStrokeColor(getProperPrimaryColor())
|
||||
|
||||
if (isVideoCaptureIntent() && mIsInPhotoMode) {
|
||||
|
@ -216,11 +214,11 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
|||
setContentView(R.layout.activity_main)
|
||||
initButtons()
|
||||
|
||||
(btn_holder.layoutParams as RelativeLayout.LayoutParams).setMargins(
|
||||
(video_rec_curr_timer.layoutParams as ConstraintLayout.LayoutParams).setMargins(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
(navigationBarHeight + resources.getDimension(R.dimen.activity_margin)).toInt()
|
||||
(navigationBarHeight + resources.getDimension(R.dimen.big_margin)).toInt()
|
||||
)
|
||||
|
||||
checkVideoCaptureIntent()
|
||||
|
@ -310,12 +308,8 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
|||
}
|
||||
|
||||
private fun launchSettings() {
|
||||
if (settings.alpha == 1f) {
|
||||
val intent = Intent(applicationContext, SettingsActivity::class.java)
|
||||
startActivity(intent)
|
||||
} else {
|
||||
fadeInButtons()
|
||||
}
|
||||
val intent = Intent(applicationContext, SettingsActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
private fun handleTogglePhotoVideo() {
|
||||
|
@ -415,34 +409,6 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
|||
}
|
||||
}
|
||||
|
||||
private fun scheduleFadeOut() {
|
||||
if (!config.keepSettingsVisible) {
|
||||
mFadeHandler.postDelayed({
|
||||
fadeOutButtons()
|
||||
}, FADE_DELAY)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fadeOutButtons() {
|
||||
fadeAnim(settings, .5f)
|
||||
fadeAnim(toggle_photo_video, .0f)
|
||||
fadeAnim(change_resolution, .0f)
|
||||
fadeAnim(last_photo_video_preview, .0f)
|
||||
}
|
||||
|
||||
private fun fadeInButtons() {
|
||||
fadeAnim(settings, 1f)
|
||||
fadeAnim(toggle_photo_video, 1f)
|
||||
fadeAnim(change_resolution, 1f)
|
||||
fadeAnim(last_photo_video_preview, 1f)
|
||||
scheduleFadeOut()
|
||||
}
|
||||
|
||||
private fun fadeAnim(view: View, value: Float) {
|
||||
view.animate().alpha(value).start()
|
||||
view.isClickable = value != .0f
|
||||
}
|
||||
|
||||
private fun showTimer() {
|
||||
video_rec_curr_timer.beVisible()
|
||||
setupTimer()
|
||||
|
|
|
@ -47,7 +47,12 @@ class ChangeResolutionDialogX(
|
|||
val items = photoResolutions.mapIndexed { index, resolution ->
|
||||
val megapixels = resolution.megaPixels
|
||||
val aspectRatio = resolution.getAspectRatio(activity)
|
||||
RadioItem(index, "${resolution.width} x ${resolution.height} ($megapixels MP, $aspectRatio)")
|
||||
if (resolution.isFullScreen) {
|
||||
//TODO: Extract to string resource
|
||||
RadioItem(index, "Full")
|
||||
} else {
|
||||
RadioItem(index, "${resolution.width} x ${resolution.height} ($megapixels MP, $aspectRatio)")
|
||||
}
|
||||
}
|
||||
var selectionIndex = if (isFrontCamera) config.frontPhotoResIndex else config.backPhotoResIndex
|
||||
selectionIndex = selectionIndex.coerceAtLeast(0)
|
||||
|
|
|
@ -66,6 +66,7 @@ class Config(context: Context) : BaseConfig(context) {
|
|||
get() = prefs.getInt(FRONT_VIDEO_RESOLUTION_INDEX, 0)
|
||||
set(frontVideoResIndex) = prefs.edit().putInt(FRONT_VIDEO_RESOLUTION_INDEX, frontVideoResIndex).apply()
|
||||
|
||||
//TODO: Remove keepSettingsVisible since the view has moved to the top
|
||||
var keepSettingsVisible: Boolean
|
||||
get() = prefs.getBoolean(KEEP_SETTINGS_VISIBLE, false)
|
||||
set(keepSettingsVisible) = prefs.edit().putBoolean(KEEP_SETTINGS_VISIBLE, keepSettingsVisible).apply()
|
||||
|
|
|
@ -28,13 +28,12 @@ class ImageQualityManager(
|
|||
for (cameraId in cameraManager.cameraIdList) {
|
||||
try {
|
||||
val characteristics = cameraManager.getCameraCharacteristics(cameraId)
|
||||
for (lens in CAMERA_LENS) {
|
||||
if (characteristics.get(CameraCharacteristics.LENS_FACING) == lens) {
|
||||
val configMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) ?: continue
|
||||
val imageSizes = configMap.getOutputSizes(ImageFormat.JPEG).map { MySize(it.width, it.height) }
|
||||
val cameraSelector = lens.toCameraSelector()
|
||||
imageQualities.add(CameraSelectorImageQualities(cameraSelector, imageSizes))
|
||||
}
|
||||
val lensFacing = characteristics.get(CameraCharacteristics.LENS_FACING) ?: continue
|
||||
if (lensFacing in CAMERA_LENS) {
|
||||
val configMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) ?: continue
|
||||
val imageSizes = configMap.getOutputSizes(ImageFormat.JPEG).map { MySize(it.width, it.height) }
|
||||
val cameraSelector = lensFacing.toCameraSelector()
|
||||
imageQualities.add(CameraSelectorImageQualities(cameraSelector, imageSizes))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
activity.showErrorToast(e)
|
||||
|
@ -52,19 +51,26 @@ class ImageQualityManager(
|
|||
}
|
||||
|
||||
fun getUserSelectedResolution(cameraSelector: CameraSelector): MySize {
|
||||
val index = if (cameraSelector == CameraSelector.DEFAULT_FRONT_CAMERA) config.frontPhotoResIndex else config.backPhotoResIndex
|
||||
return imageQualities.filter { it.camSelector == cameraSelector }
|
||||
.flatMap { it.qualities }
|
||||
.sortedWith(compareByDescending<MySize> { it.ratio }.thenByDescending { it.pixels })
|
||||
.distinctBy { it.pixels }
|
||||
.filter { it.megaPixels != "0.0" }[index]
|
||||
val resolutions = getSupportedResolutions(cameraSelector)
|
||||
var index = if (cameraSelector == CameraSelector.DEFAULT_FRONT_CAMERA) config.frontPhotoResIndex else config.backPhotoResIndex
|
||||
index = index.coerceAtMost(resolutions.lastIndex)
|
||||
return resolutions[index]
|
||||
}
|
||||
|
||||
fun getSupportedResolutions(cameraSelector: CameraSelector): List<MySize> {
|
||||
val fullScreenSize = getFullScreenResolution(cameraSelector)
|
||||
return listOf(fullScreenSize) + imageQualities.filter { it.camSelector == cameraSelector }
|
||||
.flatMap { it.qualities }
|
||||
.sortedByDescending { it.pixels }
|
||||
.distinctBy { it.getAspectRatio(activity) }
|
||||
.filter { it.isSupported() }
|
||||
}
|
||||
|
||||
private fun getFullScreenResolution(cameraSelector: CameraSelector): MySize {
|
||||
return imageQualities.filter { it.camSelector == cameraSelector }
|
||||
.flatMap { it.qualities }
|
||||
.sortedWith(compareByDescending<MySize> { it.ratio }.thenByDescending { it.pixels })
|
||||
.distinctBy { it.pixels }
|
||||
.filter { it.megaPixels != "0.0" }
|
||||
.sortedByDescending { it.width }
|
||||
.first { it.isSupported() }
|
||||
.copy(isFullScreen = true)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.annotation.SuppressLint
|
|||
import android.content.Context
|
||||
import android.hardware.SensorManager
|
||||
import android.hardware.display.DisplayManager
|
||||
import android.util.Rational
|
||||
import android.util.Size
|
||||
import android.view.*
|
||||
import android.view.GestureDetector.SimpleOnGestureListener
|
||||
|
@ -14,10 +15,12 @@ import androidx.camera.lifecycle.ProcessCameraProvider
|
|||
import androidx.camera.video.*
|
||||
import androidx.camera.video.VideoCapture
|
||||
import androidx.camera.view.PreviewView
|
||||
import androidx.camera.view.PreviewView.ScaleType
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.doOnLayout
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.window.layout.WindowMetricsCalculator
|
||||
import com.bumptech.glide.load.ImageHeaderParser.UNKNOWN_ORIENTATION
|
||||
import com.simplemobiletools.camera.R
|
||||
import com.simplemobiletools.camera.dialogs.ChangeResolutionDialogX
|
||||
|
@ -49,6 +52,7 @@ class CameraXPreview(
|
|||
private val mainExecutor = ContextCompat.getMainExecutor(activity)
|
||||
private val displayManager = activity.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
|
||||
private val mediaSoundHelper = MediaSoundHelper()
|
||||
private val windowMetricsCalculator = WindowMetricsCalculator.getOrCreate()
|
||||
private val videoQualityManager = VideoQualityManager(activity)
|
||||
private val imageQualityManager = ImageQualityManager(activity)
|
||||
private val exifRemover = ExifRemover(contentResolver)
|
||||
|
@ -120,7 +124,7 @@ class CameraXPreview(
|
|||
|
||||
private fun bindCameraUseCases() {
|
||||
val cameraProvider = cameraProvider ?: throw IllegalStateException("Camera initialization failed.")
|
||||
val rotation = previewView.display.rotation
|
||||
|
||||
val resolution = if (isPhotoCapture) {
|
||||
imageQualityManager.getUserSelectedResolution(cameraSelector)
|
||||
} else {
|
||||
|
@ -128,22 +132,94 @@ class CameraXPreview(
|
|||
MySize(selectedQuality.width, selectedQuality.height)
|
||||
}
|
||||
|
||||
val isFullSize = resolution.isFullScreen
|
||||
previewView.scaleType = if (isFullSize) ScaleType.FILL_CENTER else ScaleType.FIT_CENTER
|
||||
val rotation = previewView.display.rotation
|
||||
val rotatedResolution = getRotatedResolution(resolution, rotation)
|
||||
|
||||
preview = buildPreview(rotatedResolution, rotation)
|
||||
val previewUseCase = buildPreview(rotatedResolution, rotation)
|
||||
val captureUseCase = getCaptureUseCase(rotatedResolution, rotation)
|
||||
cameraProvider.unbindAll()
|
||||
camera = cameraProvider.bindToLifecycle(
|
||||
activity,
|
||||
cameraSelector,
|
||||
preview,
|
||||
captureUseCase,
|
||||
)
|
||||
|
||||
preview?.setSurfaceProvider(previewView.surfaceProvider)
|
||||
cameraProvider.unbindAll()
|
||||
camera = if (isFullSize) {
|
||||
val metrics = windowMetricsCalculator.computeCurrentWindowMetrics(activity).bounds
|
||||
val screenWidth = metrics.width()
|
||||
val screenHeight = metrics.height()
|
||||
val viewPort = ViewPort.Builder(Rational(screenWidth, screenHeight), rotation).build()
|
||||
|
||||
val useCaseGroup = UseCaseGroup.Builder()
|
||||
.addUseCase(previewUseCase)
|
||||
.addUseCase(captureUseCase)
|
||||
.setViewPort(viewPort)
|
||||
.build()
|
||||
|
||||
cameraProvider.bindToLifecycle(
|
||||
activity,
|
||||
cameraSelector,
|
||||
useCaseGroup,
|
||||
)
|
||||
} else {
|
||||
cameraProvider.bindToLifecycle(
|
||||
activity,
|
||||
cameraSelector,
|
||||
previewUseCase,
|
||||
captureUseCase,
|
||||
)
|
||||
}
|
||||
|
||||
previewUseCase.setSurfaceProvider(previewView.surfaceProvider)
|
||||
preview = previewUseCase
|
||||
setupZoomAndFocus()
|
||||
}
|
||||
|
||||
private fun getRotatedResolution(resolution: MySize, rotationDegrees: Int): Size {
|
||||
return if (rotationDegrees == Surface.ROTATION_0 || rotationDegrees == Surface.ROTATION_180) {
|
||||
Size(resolution.height, resolution.width)
|
||||
} else {
|
||||
Size(resolution.width, resolution.height)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildPreview(resolution: Size, rotation: Int): Preview {
|
||||
return Preview.Builder()
|
||||
.setTargetRotation(rotation)
|
||||
.setTargetResolution(resolution)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun getCaptureUseCase(resolution: Size, rotation: Int): UseCase {
|
||||
return if (isPhotoCapture) {
|
||||
buildImageCapture(resolution, rotation).also {
|
||||
imageCapture = it
|
||||
}
|
||||
} else {
|
||||
buildVideoCapture().also {
|
||||
videoCapture = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildImageCapture(resolution: Size, rotation: Int): ImageCapture {
|
||||
return Builder()
|
||||
.setCaptureMode(CAPTURE_MODE_MAXIMIZE_QUALITY)
|
||||
.setFlashMode(flashMode)
|
||||
.setJpegQuality(config.photoQuality)
|
||||
.setTargetRotation(rotation)
|
||||
.setTargetResolution(resolution)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun buildVideoCapture(): VideoCapture<Recorder> {
|
||||
val qualitySelector = QualitySelector.from(
|
||||
videoQualityManager.getUserSelectedQuality(cameraSelector).toCameraXQuality(),
|
||||
FallbackStrategy.higherQualityOrLowerThan(Quality.SD),
|
||||
)
|
||||
val recorder = Recorder.Builder()
|
||||
.setQualitySelector(qualitySelector)
|
||||
.build()
|
||||
return VideoCapture.withOutput(recorder)
|
||||
}
|
||||
|
||||
private fun setupCameraObservers() {
|
||||
listener.setFlashAvailable(camera?.cameraInfo?.hasFlashUnit() ?: false)
|
||||
listener.onChangeCamera(isFrontCameraInUse())
|
||||
|
@ -166,56 +242,6 @@ class CameraXPreview(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getCaptureUseCase(resolution: Size, rotation: Int): UseCase {
|
||||
return if (isPhotoCapture) {
|
||||
cameraProvider?.unbind(videoCapture)
|
||||
buildImageCapture(resolution, rotation).also {
|
||||
imageCapture = it
|
||||
}
|
||||
} else {
|
||||
cameraProvider?.unbind(imageCapture)
|
||||
buildVideoCapture().also {
|
||||
videoCapture = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildImageCapture(resolution: Size, rotation: Int): ImageCapture {
|
||||
return Builder()
|
||||
.setCaptureMode(CAPTURE_MODE_MAXIMIZE_QUALITY)
|
||||
.setFlashMode(flashMode)
|
||||
.setJpegQuality(config.photoQuality)
|
||||
.setTargetRotation(rotation)
|
||||
.setTargetResolution(resolution)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun getRotatedResolution(resolution: MySize, rotationDegrees: Int): Size {
|
||||
return if (rotationDegrees == Surface.ROTATION_0 || rotationDegrees == Surface.ROTATION_180) {
|
||||
Size(resolution.height, resolution.width)
|
||||
} else {
|
||||
Size(resolution.width, resolution.height)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildPreview(resolution: Size, rotation: Int): Preview {
|
||||
return Preview.Builder()
|
||||
.setTargetRotation(rotation)
|
||||
.setTargetResolution(resolution)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun buildVideoCapture(): VideoCapture<Recorder> {
|
||||
val qualitySelector = QualitySelector.from(
|
||||
videoQualityManager.getUserSelectedQuality(cameraSelector).toCameraXQuality(),
|
||||
FallbackStrategy.higherQualityOrLowerThan(Quality.SD),
|
||||
)
|
||||
val recorder = Recorder.Builder()
|
||||
.setQualitySelector(qualitySelector)
|
||||
.build()
|
||||
return VideoCapture.withOutput(recorder)
|
||||
}
|
||||
|
||||
private fun hasBackCamera(): Boolean {
|
||||
return cameraProvider?.hasCamera(CameraSelector.DEFAULT_BACK_CAMERA) ?: false
|
||||
}
|
||||
|
|
|
@ -4,18 +4,19 @@ import android.content.Context
|
|||
import android.util.Size
|
||||
import com.simplemobiletools.camera.R
|
||||
|
||||
data class MySize(val width: Int, val height: Int) {
|
||||
data class MySize(val width: Int, val height: Int, val isFullScreen: Boolean = false) {
|
||||
companion object {
|
||||
private const val ONE_MEGA_PIXEL = 1000000
|
||||
private const val ZERO_MEGA_PIXEL = "0.0"
|
||||
}
|
||||
|
||||
val ratio = width / height.toFloat()
|
||||
private val ratio = width / height.toFloat()
|
||||
|
||||
val pixels: Int = width * height
|
||||
|
||||
val megaPixels: String = String.format("%.1f", (width * height.toFloat()) / ONE_MEGA_PIXEL)
|
||||
val megaPixels: String = String.format("%.1f", (width * height.toFloat()) / ONE_MEGA_PIXEL)
|
||||
|
||||
fun isSixteenToNine() = ratio == 16 / 9f
|
||||
private fun isSixteenToNine() = ratio == 16 / 9f
|
||||
|
||||
private fun isFiveToThree() = ratio == 5 / 3f
|
||||
|
||||
|
@ -37,6 +38,10 @@ data class MySize(val width: Int, val height: Int) {
|
|||
|
||||
private fun isSquare() = width == height
|
||||
|
||||
fun isSupported(): Boolean {
|
||||
return (isFourToThree() || isSixteenToNine() || isSquare()) && megaPixels != ZERO_MEGA_PIXEL
|
||||
}
|
||||
|
||||
fun getAspectRatio(context: Context) = when {
|
||||
isSixteenToNine() -> "16:9"
|
||||
isFiveToThree() -> "5:3"
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<gradient
|
||||
android:angle="90"
|
||||
android:endColor="@android:color/transparent"
|
||||
android:startColor="@color/gradient_grey_start"/>
|
||||
</shape>
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<gradient
|
||||
android:angle="270"
|
||||
android:endColor="@android:color/transparent"
|
||||
android:startColor="@color/gradient_grey_start"/>
|
||||
</shape>
|
|
@ -1,17 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/view_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black">
|
||||
android:background="@android:color/black"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<androidx.camera.view.PreviewView
|
||||
android:id="@+id/preview_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:scaleType="fitStart" />
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<View
|
||||
android:id="@+id/capture_black_screen"
|
||||
|
@ -20,24 +20,28 @@
|
|||
android:alpha="0"
|
||||
android:background="@color/md_grey_black" />
|
||||
|
||||
<View
|
||||
android:id="@+id/top_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:background="@drawable/gradient_background_flipped"
|
||||
app:layout_constraintBottom_toBottomOf="@id/settings"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/settings"
|
||||
android:layout_width="@dimen/icon_size"
|
||||
android:layout_height="@dimen/icon_size"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:contentDescription="@string/settings"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_settings_cog_vector" />
|
||||
android:src="@drawable/ic_settings_cog_vector"
|
||||
app:layout_constraintEnd_toStartOf="@id/change_resolution"
|
||||
app:layout_constraintHorizontal_chainStyle="spread"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/toggle_photo_video"
|
||||
android:layout_width="@dimen/icon_size"
|
||||
android:layout_height="@dimen/icon_size"
|
||||
android:layout_below="@+id/settings"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:contentDescription="@string/toggle_photo_video"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_video_vector" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/change_resolution"
|
||||
|
@ -47,61 +51,106 @@
|
|||
android:layout_alignParentEnd="true"
|
||||
android:contentDescription="@string/resolution"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_resolution_vector" />
|
||||
android:src="@drawable/ic_resolution_vector"
|
||||
app:layout_constraintEnd_toStartOf="@id/toggle_flash"
|
||||
app:layout_constraintStart_toEndOf="@id/settings"
|
||||
app:layout_constraintTop_toTopOf="@id/settings" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/toggle_flash"
|
||||
android:layout_width="@dimen/icon_size"
|
||||
android:layout_height="@dimen/icon_size"
|
||||
android:layout_weight="1"
|
||||
android:contentDescription="@string/toggle_flash"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_flash_off_vector"
|
||||
app:layout_constraintEnd_toStartOf="@id/toggle_photo_video"
|
||||
app:layout_constraintStart_toEndOf="@id/change_resolution"
|
||||
app:layout_constraintTop_toTopOf="@id/settings" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/toggle_photo_video"
|
||||
android:layout_width="@dimen/icon_size"
|
||||
android:layout_height="@dimen/icon_size"
|
||||
android:contentDescription="@string/toggle_photo_video"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_video_vector"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/toggle_flash"
|
||||
app:layout_constraintTop_toTopOf="@id/settings" />
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/top_barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="settings,change_resolution,toggle_flash,toggle_photo_video" />
|
||||
|
||||
|
||||
<View
|
||||
android:id="@+id/bottom_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:background="@drawable/gradient_background"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/shutter" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/toggle_camera"
|
||||
android:layout_width="@dimen/icon_size"
|
||||
android:layout_height="@dimen/icon_size"
|
||||
android:contentDescription="@string/toggle_camera"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_camera_front_vector"
|
||||
app:layout_constraintBottom_toBottomOf="@id/shutter"
|
||||
app:layout_constraintEnd_toStartOf="@id/shutter"
|
||||
app:layout_constraintHorizontal_chainStyle="spread"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/shutter" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/shutter"
|
||||
android:layout_width="@dimen/icon_size"
|
||||
android:layout_height="@dimen/icon_size"
|
||||
android:layout_marginBottom="@dimen/small_margin"
|
||||
android:contentDescription="@string/shutter"
|
||||
android:src="@drawable/ic_shutter_vector"
|
||||
app:layout_constraintBottom_toTopOf="@id/video_rec_curr_timer"
|
||||
app:layout_constraintEnd_toStartOf="@id/last_photo_video_preview"
|
||||
app:layout_constraintStart_toEndOf="@id/toggle_camera"
|
||||
|
||||
app:layout_constraintVertical_bias="1"
|
||||
app:layout_goneMarginBottom="@dimen/big_margin" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/last_photo_video_preview"
|
||||
android:layout_width="@dimen/icon_size"
|
||||
android:layout_height="@dimen/icon_size"
|
||||
android:layout_below="@+id/change_resolution"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:contentDescription="@string/view_last_media"
|
||||
android:padding="@dimen/medium_margin" />
|
||||
android:padding="@dimen/medium_margin"
|
||||
app:layout_constraintBottom_toBottomOf="@id/shutter"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/shutter"
|
||||
app:layout_constraintTop_toTopOf="@id/shutter"
|
||||
tools:src="@tools:sample/backgrounds/scenic" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/btn_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:layout_alignParentBottom="true"
|
||||
android:gravity="center_horizontal|bottom">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/toggle_camera"
|
||||
android:layout_width="@dimen/icon_size"
|
||||
android:layout_height="@dimen/icon_size"
|
||||
android:layout_weight="1"
|
||||
android:contentDescription="@string/toggle_camera"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_camera_front_vector" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/shutter"
|
||||
android:layout_width="@dimen/icon_size"
|
||||
android:layout_height="@dimen/icon_size"
|
||||
android:layout_weight="1"
|
||||
android:contentDescription="@string/shutter"
|
||||
android:src="@drawable/ic_shutter_vector" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/toggle_flash"
|
||||
android:layout_width="@dimen/icon_size"
|
||||
android:layout_height="@dimen/icon_size"
|
||||
android:layout_weight="1"
|
||||
android:contentDescription="@string/toggle_flash"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_flash_off_vector" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/video_rec_curr_timer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/btn_holder"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="@dimen/small_margin"
|
||||
android:layout_marginBottom="@dimen/big_margin"
|
||||
android:textColor="@android:color/white"
|
||||
android:visibility="gone"
|
||||
tools:text="00:00" />
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="00:00"
|
||||
tools:visibility="gone" />
|
||||
|
||||
</RelativeLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
Loading…
Reference in New Issue