Merge pull request #348 from KryptKode/feat/camera-x

Camera UI fixes
This commit is contained in:
Tibor Kaputa 2022-10-06 18:27:53 +02:00 committed by GitHub
commit 879251e8cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 186 additions and 149 deletions

View File

@ -69,7 +69,7 @@ dependencies {
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.1"
implementation 'androidx.window:window:1.1.0-alpha03'
def camerax_version = '1.1.0'
def camerax_version = '1.2.0-beta02'
implementation "androidx.camera:camera-core:$camerax_version"
implementation "androidx.camera:camera-camera2:$camerax_version"
implementation "androidx.camera:camera-video:$camerax_version"

View File

@ -19,7 +19,13 @@
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission
android:name="android.permission.USE_FINGERPRINT"
tools:node="remove" />

View File

@ -11,7 +11,6 @@ import android.os.Handler
import android.os.Looper
import android.provider.MediaStore
import android.view.*
import android.view.animation.OvershootInterpolator
import android.widget.LinearLayout
import androidx.appcompat.content.res.AppCompatResources
import androidx.constraintlayout.widget.ConstraintLayout
@ -23,6 +22,7 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.request.RequestOptions
import com.google.android.material.button.MaterialButton
import com.google.android.material.button.MaterialButtonToggleGroup
import com.google.android.material.tabs.TabLayout
import com.simplemobiletools.camera.BuildConfig
import com.simplemobiletools.camera.R
@ -44,7 +44,6 @@ import kotlinx.android.synthetic.main.layout_flash.flash_auto
import kotlinx.android.synthetic.main.layout_flash.flash_off
import kotlinx.android.synthetic.main.layout_flash.flash_on
import kotlinx.android.synthetic.main.layout_flash.flash_toggle_group
import kotlinx.android.synthetic.main.layout_media_size.media_size_toggle_group
import kotlinx.android.synthetic.main.layout_top.change_resolution
import kotlinx.android.synthetic.main.layout_top.default_icons
import kotlinx.android.synthetic.main.layout_top.settings
@ -59,12 +58,12 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
lateinit var mTimerHandler: Handler
private lateinit var defaultScene: Scene
private lateinit var mediaSizeScene: Scene
private lateinit var flashModeScene: Scene
private lateinit var mOrientationEventListener: OrientationEventListener
private lateinit var mFocusCircleView: FocusCircleView
private lateinit var mCameraImpl: MyCameraImpl
private var mPreview: MyPreview? = null
private var mediaSizeToggleGroup: MaterialButtonToggleGroup? = null
private var mPreviewUri: Uri? = null
private var mIsInPhotoMode = true
private var mIsCameraAvailable = false
@ -223,7 +222,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
private fun tryInitCamera() {
handlePermission(PERMISSION_CAMERA) { grantedCameraPermission ->
if (grantedCameraPermission) {
handlePermission(PERMISSION_WRITE_STORAGE) { grantedStoragePermission ->
handleStoragePermission { grantedStoragePermission ->
if (grantedStoragePermission) {
if (mIsInPhotoMode) {
initializeCamera()
@ -250,6 +249,20 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
}
}
private fun handleStoragePermission(callback: (granted: Boolean) -> Unit) {
if (isTiramisuPlus()) {
handlePermission(PERMISSION_READ_MEDIA_IMAGES) { grantedReadImages ->
if (grantedReadImages) {
handlePermission(PERMISSION_READ_MEDIA_VIDEO) { grantedReadVideos ->
callback.invoke(grantedReadVideos)
}
}
}
} else {
handlePermission(PERMISSION_WRITE_STORAGE, callback)
}
}
private fun is3rdPartyIntent() = isVideoCaptureIntent() || isImageCaptureIntent()
private fun isImageCaptureIntent(): Boolean = intent?.action == MediaStore.ACTION_IMAGE_CAPTURE || intent?.action == MediaStore.ACTION_IMAGE_CAPTURE_SECURE
@ -274,12 +287,17 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
}
}
private fun createToggleGroup(): MaterialButtonToggleGroup {
return MaterialButtonToggleGroup(this).apply {
isSingleSelection = true
layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}
}
private fun initializeCamera() {
setContentView(R.layout.activity_main)
initButtons()
defaultScene = Scene(top_options, default_icons)
mediaSizeScene = Scene(top_options, media_size_toggle_group)
flashModeScene = Scene(top_options, flash_toggle_group)
ViewCompat.setOnApplyWindowInsetsListener(view_holder) { _, windowInsets ->
@ -389,7 +407,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
FLASH_ON -> R.drawable.ic_flash_on_vector
else -> R.drawable.ic_flash_auto_vector
}
toggle_flash.setImageResource(flashDrawable)
toggle_flash.icon = AppCompatResources.getDrawable(this, flashDrawable)
toggle_flash.transitionName = "${getString(R.string.toggle_flash)}$state"
}
@ -542,8 +560,20 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
}
private fun hasStorageAndCameraPermissions(): Boolean {
return if (mIsInPhotoMode) {
return if (mIsInPhotoMode) hasPhotoModePermissions() else hasVideoModePermissions()
}
private fun hasPhotoModePermissions(): Boolean {
return if (isTiramisuPlus()) {
hasPermission(PERMISSION_READ_MEDIA_IMAGES) && hasPermission(PERMISSION_CAMERA)
} else {
hasPermission(PERMISSION_WRITE_STORAGE) && hasPermission(PERMISSION_CAMERA)
}
}
private fun hasVideoModePermissions(): Boolean {
return if (isTiramisuPlus()) {
hasPermission(PERMISSION_READ_MEDIA_VIDEO) && hasPermission(PERMISSION_CAMERA) && hasPermission(PERMISSION_RECORD_AUDIO)
} else {
hasPermission(PERMISSION_WRITE_STORAGE) && hasPermission(PERMISSION_CAMERA) && hasPermission(PERMISSION_RECORD_AUDIO)
}
@ -606,7 +636,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
toggle_flash.beVisible()
} else {
toggle_flash.beInvisible()
toggle_flash.setImageResource(R.drawable.ic_flash_off_vector)
toggle_flash.icon = AppCompatResources.getDrawable(this, R.drawable.ic_flash_off_vector)
mPreview?.setFlashlightState(FLASH_OFF)
}
}
@ -700,11 +730,14 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
}
private fun closeOptions(): Boolean {
if (media_size_toggle_group.isVisible() ||
if (mediaSizeToggleGroup?.isVisible() == true ||
flash_toggle_group.isVisible()
) {
val transitionSet = createTransition(isClosing = true)
val transitionSet = createTransition()
TransitionManager.go(defaultScene, transitionSet)
mediaSizeToggleGroup?.beGone()
flash_toggle_group.beGone()
default_icons.beVisible()
return true
}
@ -713,7 +746,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
override fun displaySelectedResolution(resolutionOption: ResolutionOption) {
val imageRes = resolutionOption.imageDrawableResId
change_resolution.setImageResource(imageRes)
change_resolution.icon = AppCompatResources.getDrawable(this, imageRes)
change_resolution.transitionName = "${resolutionOption.buttonViewId}"
}
@ -725,8 +758,11 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
onSelect: (index: Int, changed: Boolean) -> Unit
) {
media_size_toggle_group.removeAllViews()
media_size_toggle_group.clearChecked()
top_options.removeView(mediaSizeToggleGroup)
val mediaSizeToggleGroup = createToggleGroup().apply {
mediaSizeToggleGroup = this
}
top_options.addView(mediaSizeToggleGroup)
val onItemClick = { clickedViewId: Int ->
closeOptions()
@ -737,11 +773,17 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
resolutions.map {
createButton(it, onItemClick)
}.forEach { button ->
media_size_toggle_group.addView(button)
mediaSizeToggleGroup.addView(button)
}
media_size_toggle_group.check(selectedResolution.buttonViewId)
showResolutionOptions()
mediaSizeToggleGroup.check(selectedResolution.buttonViewId)
val transitionSet = createTransition()
val mediaSizeScene = Scene(top_options, mediaSizeToggleGroup)
TransitionManager.go(mediaSizeScene, transitionSet)
default_icons.beGone()
mediaSizeToggleGroup.beVisible()
mediaSizeToggleGroup.children.map { it as MaterialButton }.forEach(::setButtonColors)
}
private fun createButton(resolutionOption: ResolutionOption, onClick: (clickedViewId: Int) -> Unit): MaterialButton {
@ -759,21 +801,9 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
}
}
private fun showResolutionOptions() {
val transitionSet = createTransition()
TransitionManager.go(mediaSizeScene, transitionSet)
media_size_toggle_group.children.map { it as MaterialButton }.forEach(::setButtonColors)
}
private fun createTransition(isClosing: Boolean = false): Transition {
private fun createTransition(): Transition {
val fadeTransition = Fade()
val changeBounds = ChangeBounds().apply {
interpolator = OvershootInterpolator()
}
return TransitionSet().apply {
if (!isClosing) {
addTransition(changeBounds)
}
addTransition(fadeTransition)
this.duration = resources.getInteger(R.integer.icon_anim_duration).toLong()
}

View File

@ -34,52 +34,62 @@ class MediaOutputHelper(
private val contentResolver = activity.contentResolver
fun getImageMediaOutput(): MediaOutput {
return if (is3rdPartyIntent) {
if (outputUri != null) {
val outputStream = openOutputStream(outputUri)
if (outputStream != null) {
MediaOutput.OutputStreamMediaOutput(outputStream, outputUri)
return try {
if (is3rdPartyIntent) {
if (outputUri != null) {
val outputStream = openOutputStream(outputUri)
if (outputStream != null) {
MediaOutput.OutputStreamMediaOutput(outputStream, outputUri)
} else {
errorHandler.showSaveToInternalStorage()
getMediaStoreOutput(isPhoto = true)
}
} else {
errorHandler.showSaveToInternalStorage()
getMediaStoreOutput(isPhoto = true)
MediaOutput.BitmapOutput
}
} else {
MediaOutput.BitmapOutput
getOutputStreamMediaOutput() ?: getMediaStoreOutput(isPhoto = true)
}
} else {
getOutputStreamMediaOutput() ?: getMediaStoreOutput(isPhoto = true)
} catch (e: Exception) {
errorHandler.showSaveToInternalStorage()
getMediaStoreOutput(isPhoto = true)
}
}
fun getVideoMediaOutput(): MediaOutput {
return if (is3rdPartyIntent) {
if (outputUri != null) {
if (isOreoPlus()) {
val fileDescriptor = openFileDescriptor(outputUri)
if (fileDescriptor != null) {
MediaOutput.FileDescriptorMediaOutput(fileDescriptor, outputUri)
return try {
if (is3rdPartyIntent) {
if (outputUri != null) {
if (isOreoPlus()) {
val fileDescriptor = openFileDescriptor(outputUri)
if (fileDescriptor != null) {
MediaOutput.FileDescriptorMediaOutput(fileDescriptor, outputUri)
} else {
errorHandler.showSaveToInternalStorage()
getMediaStoreOutput(isPhoto = false)
}
} else {
errorHandler.showSaveToInternalStorage()
getMediaStoreOutput(isPhoto = false)
val path = activity.getRealPathFromURI(outputUri)
if (path != null) {
MediaOutput.FileMediaOutput(File(path), outputUri)
} else {
errorHandler.showSaveToInternalStorage()
getMediaStoreOutput(isPhoto = false)
}
}
} else {
val path = activity.getRealPathFromURI(outputUri)
if (path != null) {
MediaOutput.FileMediaOutput(File(path), outputUri)
} else {
errorHandler.showSaveToInternalStorage()
getMediaStoreOutput(isPhoto = false)
}
getMediaStoreOutput(isPhoto = false)
}
} else {
getMediaStoreOutput(isPhoto = false)
}
} else {
if (isOreoPlus()) {
getFileDescriptorMediaOutput() ?: getMediaStoreOutput(isPhoto = false)
} else {
getFileMediaOutput() ?: getMediaStoreOutput(isPhoto = false)
if (isOreoPlus()) {
getFileDescriptorMediaOutput() ?: getMediaStoreOutput(isPhoto = false)
} else {
getFileMediaOutput() ?: getMediaStoreOutput(isPhoto = false)
}
}
} catch (e: Exception) {
errorHandler.showSaveToInternalStorage()
getMediaStoreOutput(isPhoto = false)
}
}

View File

@ -373,18 +373,19 @@ class CameraXPreview(
}
private fun toggleResolutions(resolutions: List<ResolutionOption>) {
val currentIndex = mediaSizeStore.getCurrentSizeIndex(isPhotoCapture, isFrontCameraInUse())
if (resolutions.size >= 2) {
val currentIndex = mediaSizeStore.getCurrentSizeIndex(isPhotoCapture, isFrontCameraInUse())
val nextIndex = if (currentIndex >= resolutions.lastIndex) {
0
} else {
currentIndex + 1
val nextIndex = if (currentIndex >= resolutions.lastIndex) {
0
} else {
currentIndex + 1
}
mediaSizeStore.storeSize(isPhotoCapture, isFrontCameraInUse(), nextIndex)
currentRecording?.stop()
startCamera()
}
mediaSizeStore.storeSize(isPhotoCapture, isFrontCameraInUse(), nextIndex)
currentRecording?.stop()
startCamera()
}
override fun toggleFrontBackCamera() {
@ -438,14 +439,20 @@ class CameraXPreview(
val mediaOutput = mediaOutputHelper.getImageMediaOutput()
if (mediaOutput is MediaOutput.BitmapOutput) {
imageCapture.takePicture(mainExecutor, object : ImageCapture.OnImageCapturedCallback() {
imageCapture.takePicture(mainExecutor, object : OnImageCapturedCallback() {
override fun onCaptureSuccess(image: ImageProxy) {
listener.toggleBottomButtons(false)
val bitmap = BitmapUtils.makeBitmap(image.toJpegByteArray())
if (bitmap != null) {
listener.onImageCaptured(bitmap)
} else {
cameraErrorHandler.handleImageCaptureError(ERROR_CAPTURE_FAILED)
ensureBackgroundThread {
image.use {
val bitmap = BitmapUtils.makeBitmap(image.toJpegByteArray())
activity.runOnUiThread {
listener.toggleBottomButtons(false)
if (bitmap != null) {
listener.onImageCaptured(bitmap)
} else {
cameraErrorHandler.handleImageCaptureError(ERROR_CAPTURE_FAILED)
}
}
}
}
}
@ -457,7 +464,6 @@ class CameraXPreview(
val outputOptionsBuilder = when (mediaOutput) {
is MediaOutput.MediaStoreOutput -> OutputFileOptions.Builder(contentResolver, mediaOutput.contentUri, mediaOutput.contentValues)
is MediaOutput.OutputStreamMediaOutput -> OutputFileOptions.Builder(mediaOutput.outputStream)
is MediaOutput.BitmapOutput -> throw IllegalStateException("Cannot produce an OutputFileOptions for a bitmap output")
else -> throw IllegalArgumentException("Unexpected option for image ")
}

View File

@ -1,22 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="18"
android:viewportHeight="18">
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/camera_option_color"
android:pathData="M9,7m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" />
<path
android:fillColor="@color/camera_option_color"
android:pathData="M9,11m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0" />
<path
android:fillColor="@color/camera_option_color"
android:fillColor="@color/white"
android:fillType="evenOdd"
android:pathData="M2,0C0.895,0 0,0.895 0,2V5H2V2L16,2V5H18V2C18,0.895 17.105,0 16,0H2ZM18,13H16V16H2V13H0V16C0,17.105 0.895,18 2,18H16C17.105,18 18,17.105 18,16V13Z" />
android:pathData="M4.0098,3.89C3.9832,3.89 3.9578,3.9005 3.9391,3.9193C3.9203,3.938 3.9098,3.9634 3.9098,3.99V6.99H2.1098V3.99C2.1098,3.486 2.31,3.0028 2.6663,2.6465C3.0226,2.2901 3.5059,2.09 4.0098,2.09H19.9898C20.4937,2.09 20.977,2.2901 21.3333,2.6465C21.6896,3.0028 21.8898,3.4861 21.8898,3.99V6.99H20.0898V3.99C20.0898,3.9634 20.0792,3.938 20.0605,3.9193C20.0417,3.9005 20.0163,3.89 19.9898,3.89H4.0098Z" />
<path
android:fillColor="@color/camera_option_color"
android:pathData="M15,12H13.13V9.033C13.13,8.978 13.13,8.878 13.13,8.733C13.13,8.585 13.132,8.423 13.135,8.245C13.141,8.067 13.149,7.907 13.158,7.765C13.078,7.85 13.002,7.922 12.93,7.982C12.862,8.042 12.795,8.099 12.73,8.15L11.956,8.713L11,7.679L13.34,6H15V12Z" />
android:fillColor="@color/white"
android:fillType="evenOdd"
android:pathData="M3.9098,17.0149V20.0149C3.9098,20.0414 3.9203,20.0668 3.9391,20.0856C3.9578,20.1043 3.9832,20.1149 4.0098,20.1149H19.9898C20.0163,20.1149 20.0417,20.1043 20.0605,20.0856C20.0792,20.0668 20.0898,20.0414 20.0898,20.0149V17.0149H21.8898V20.0149C21.8898,20.5188 21.6896,21.0021 21.3333,21.3584C20.977,21.7147 20.4937,21.9149 19.9898,21.9149H4.0098C3.5059,21.9149 3.0226,21.7147 2.6663,21.3584C2.31,21.0021 2.1098,20.5188 2.1098,20.0149V17.0149H3.9098Z" />
<path
android:fillColor="@color/camera_option_color"
android:pathData="M6,12H4.131V9.033C4.131,8.978 4.131,8.878 4.131,8.733C4.131,8.585 4.132,8.423 4.135,8.245C4.141,8.067 4.149,7.907 4.159,7.765C4.078,7.85 4.002,7.922 3.93,7.982C3.862,8.042 3.795,8.099 3.73,8.15L2.956,8.713L2,7.679L4.34,6H6V12Z" />
android:fillColor="@color/white"
android:pathData="M4.27,10.677V9.2C4.7997,9.2486 5.329,9.1036 5.76,8.792C5.9267,8.6107 6.0531,8.3963 6.1312,8.1629C6.2093,7.9293 6.2371,7.682 6.213,7.437H7.866V16.448H6.03V10.677H4.27Z" />
<path
android:fillColor="@color/white"
android:pathData="M15.3291,10.677V9.2C15.8588,9.2486 16.3881,9.1036 16.8191,8.792C16.9859,8.6108 17.1125,8.3965 17.1905,8.1629C17.2686,7.9294 17.2964,7.682 17.2721,7.437H18.9261V16.448H17.0891V10.677H15.3291Z" />
<path
android:fillColor="@color/white"
android:pathData="M12,11C12.5523,11 13,10.5523 13,10C13,9.4477 12.5523,9 12,9C11.4477,9 11,9.4477 11,10C11,10.5523 11.4477,11 12,11Z" />
<path
android:fillColor="@color/white"
android:pathData="M12,15C12.5523,15 13,14.5523 13,14C13,13.4477 12.5523,13 12,13C11.4477,13 11,13.4477 11,14C11,14.5523 11.4477,15 12,15Z" />
</vector>

View File

@ -1,21 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="512"
android:viewportHeight="512">
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/camera_option_color"
android:pathData="M0,0v512h512V0H0zM477.87,477.87H34.13V34.13h443.73V477.87z" />
<path
android:fillColor="@color/camera_option_color"
android:pathData="M126.53,102.4l72.58,0l0,-34.13l-130.84,0l0,130.84l34.13,0l0,-72.57l96.02,96.02l24.13,-24.13z" />
<path
android:fillColor="@color/camera_option_color"
android:pathData="M222.56,313.58l-24.14,-24.14l-96.02,96.02l0,-72.58l-34.13,0l0,130.84l130.84,0l0,-34.13l-72.57,0z" />
<path
android:fillColor="@color/camera_option_color"
android:pathData="M409.6,312.89l0,72.58l-96.02,-96.02l-24.13,24.13l96.02,96.02l-72.57,0l0,34.13l130.84,0l0,-130.84z" />
<path
android:fillColor="@color/camera_option_color"
android:pathData="M312.89,68.27l0,34.13l72.58,0l-96.02,96.02l24.13,24.13l96.02,-96.02l0,72.57l34.13,0l0,-130.84z" />
android:fillAlpha="0.85"
android:fillColor="@color/white"
android:fillType="evenOdd"
android:pathData="M15,2.9H17.8271L13.3635,7.3636L14.6363,8.6364L19.1,4.1727V7H20.9V2C20.9,1.5029 20.4971,1.1 20,1.1H15V2.9ZM6.0001,2.1C5.4962,2.1 5.0129,2.3001 4.6566,2.6565C4.3003,3.0128 4.1001,3.4961 4.1001,4V14H5.9001V4C5.9001,3.9734 5.9106,3.948 5.9294,3.9293C5.9481,3.9105 5.9736,3.9 6.0001,3.9H12.0001V2.1H6.0001ZM19.9,20V10H18.1V20C18.1,20.0265 18.0895,20.052 18.0707,20.0707C18.052,20.0895 18.0265,20.1 18,20.1H12V21.9H18C18.5039,21.9 18.9872,21.6998 19.3435,21.3435C19.6998,20.9872 19.9,20.5039 19.9,20ZM4.9001,19.827L9.3635,15.3636L10.6363,16.6364L6.1727,21.1H9.0001V22.9H4.0001C3.503,22.9 3.1001,22.4971 3.1001,22V17H4.9001V19.827Z" />
</vector>

View File

@ -31,12 +31,7 @@
app:layout_constraintTop_toTopOf="parent">
<include layout="@layout/layout_top" />
<include layout="@layout/layout_media_size" />
<include
layout="@layout/layout_flash"
android:visibility="gone" />
<include layout="@layout/layout_flash" />
</FrameLayout>

View File

@ -1,11 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.button.MaterialButtonToggleGroup 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/flash_toggle_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
app:selectionRequired="true"
app:singleSelection="true">
app:singleSelection="true"
tools:visibility="visible">
<Button

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.button.MaterialButtonToggleGroup xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/media_size_toggle_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:selectionRequired="true"
app:singleSelection="true" />

View File

@ -1,53 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout 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/default_icons"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
<com.google.android.material.button.MaterialButton
android:id="@+id/toggle_flash"
android:layout_width="@dimen/top_icon_size"
android:layout_height="@dimen/top_icon_size"
android:layout_marginStart="@dimen/normal_margin"
android:layout_marginEnd="@dimen/normal_margin"
style="@style/Widget.App.Button.OutlineButton.IconOnly"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/toggle_flash"
android:padding="@dimen/normal_margin"
android:src="@drawable/ic_flash_off_vector"
app:icon="@drawable/ic_flash_off_vector"
app:layout_constraintEnd_toStartOf="@id/change_resolution"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
<com.google.android.material.button.MaterialButton
android:id="@+id/change_resolution"
android:layout_width="@dimen/top_icon_size"
android:layout_height="@dimen/top_icon_size"
android:layout_alignParentEnd="true"
android:layout_marginStart="@dimen/normal_margin"
android:layout_marginEnd="@dimen/normal_margin"
style="@style/Widget.App.Button.OutlineButton.IconOnly"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/resolution"
android:padding="@dimen/normal_margin"
android:transitionName="one_by_one"
app:layout_constraintEnd_toStartOf="@id/settings"
app:layout_constraintStart_toEndOf="@id/toggle_flash"
app:layout_constraintTop_toTopOf="@id/toggle_flash"
tools:src="@drawable/ic_photo_4x3" />
tools:icon="@drawable/ic_photo_4x3" />
<ImageView
<com.google.android.material.button.MaterialButton
android:id="@+id/settings"
android:layout_width="@dimen/top_icon_size"
android:layout_height="@dimen/top_icon_size"
android:layout_marginStart="@dimen/normal_margin"
android:layout_marginEnd="@dimen/normal_margin"
style="@style/Widget.App.Button.OutlineButton.IconOnly"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/settings"
android:padding="@dimen/normal_margin"
android:src="@drawable/ic_settings_cog_vector"
app:icon="@drawable/ic_settings_cog_vector"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/change_resolution"
app:layout_constraintTop_toTopOf="@id/toggle_flash" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>