use tabs for camera modes
This commit is contained in:
parent
4b7166e90f
commit
2ebeb5a1e4
|
@ -15,6 +15,7 @@ import com.bumptech.glide.Glide
|
|||
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.tabs.TabLayout
|
||||
import com.simplemobiletools.camera.BuildConfig
|
||||
import com.simplemobiletools.camera.R
|
||||
import com.simplemobiletools.camera.extensions.config
|
||||
|
@ -33,6 +34,8 @@ import kotlinx.android.synthetic.main.activity_main.*
|
|||
class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, CameraXPreviewListener {
|
||||
companion object {
|
||||
private const val CAPTURE_ANIMATION_DURATION = 100L
|
||||
private const val PHOTO_MODE_INDEX = 1
|
||||
private const val VIDEO_MODE_INDEX = 0
|
||||
}
|
||||
|
||||
lateinit var mTimerHandler: Handler
|
||||
|
@ -49,6 +52,12 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
|||
private var mCurrVideoRecTimer = 0
|
||||
var mLastHandledOrientation = 0
|
||||
|
||||
private val tabSelectedListener = object : TabSelectedListener {
|
||||
override fun onTabSelected(tab: TabLayout.Tab) {
|
||||
handleTogglePhotoVideo()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
useDynamicTheme = false
|
||||
super.onCreate(savedInstanceState)
|
||||
|
@ -81,6 +90,32 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
|||
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
||||
)
|
||||
}
|
||||
|
||||
selectPhotoTab()
|
||||
}
|
||||
|
||||
private fun selectPhotoTab(triggerListener: Boolean = false) {
|
||||
if (!triggerListener) {
|
||||
removeTabListener()
|
||||
}
|
||||
camera_mode_tab.getTabAt(PHOTO_MODE_INDEX)?.select()
|
||||
setTabListener()
|
||||
}
|
||||
|
||||
private fun selectVideoTab(triggerListener: Boolean = false) {
|
||||
if (!triggerListener) {
|
||||
removeTabListener()
|
||||
}
|
||||
camera_mode_tab.getTabAt(VIDEO_MODE_INDEX)?.select()
|
||||
setTabListener()
|
||||
}
|
||||
|
||||
private fun setTabListener() {
|
||||
camera_mode_tab.addOnTabSelectedListener(tabSelectedListener)
|
||||
}
|
||||
|
||||
private fun removeTabListener() {
|
||||
camera_mode_tab.removeOnTabSelectedListener(tabSelectedListener)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
@ -158,9 +193,9 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
|||
}
|
||||
|
||||
private fun hideIntentButtons() {
|
||||
toggle_photo_video.beGone()
|
||||
camera_mode_tab.beGone()
|
||||
settings.beGone()
|
||||
last_photo_video_preview.beGone()
|
||||
last_photo_video_preview.beInvisible()
|
||||
}
|
||||
|
||||
private fun tryInitCamera() {
|
||||
|
@ -193,6 +228,8 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
|||
}
|
||||
}
|
||||
|
||||
private fun is3rdPartyIntent() = isVideoCaptureIntent() || isImageCaptureIntent()
|
||||
|
||||
private fun isImageCaptureIntent(): Boolean = intent?.action == MediaStore.ACTION_IMAGE_CAPTURE || intent?.action == MediaStore.ACTION_IMAGE_CAPTURE_SECURE
|
||||
|
||||
private fun isVideoCaptureIntent(): Boolean = intent?.action == MediaStore.ACTION_VIDEO_CAPTURE
|
||||
|
@ -219,7 +256,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
|||
setContentView(R.layout.activity_main)
|
||||
initButtons()
|
||||
|
||||
(toggle_photo_video.layoutParams as ConstraintLayout.LayoutParams).setMargins(
|
||||
(toggle_flash.layoutParams as ConstraintLayout.LayoutParams).setMargins(
|
||||
0,
|
||||
statusBarHeight,
|
||||
0,
|
||||
|
@ -237,8 +274,14 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
|||
)
|
||||
|
||||
checkVideoCaptureIntent()
|
||||
if (mIsInPhotoMode) {
|
||||
selectPhotoTab()
|
||||
} else {
|
||||
selectVideoTab()
|
||||
}
|
||||
|
||||
val outputUri = intent.extras?.get(MediaStore.EXTRA_OUTPUT) as? Uri
|
||||
val is3rdPartyIntent = isVideoCaptureIntent() || isImageCaptureIntent()
|
||||
val is3rdPartyIntent = is3rdPartyIntent()
|
||||
mPreview = CameraXInitializer(this).createCameraXPreview(
|
||||
preview_view,
|
||||
listener = this,
|
||||
|
@ -271,7 +314,6 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
|||
toggle_flash.setOnClickListener { toggleFlash() }
|
||||
shutter.setOnClickListener { shutterPressed() }
|
||||
settings.setOnClickListener { launchSettings() }
|
||||
toggle_photo_video.setOnClickListener { handleTogglePhotoVideo() }
|
||||
change_resolution.setOnClickListener { mPreview?.showChangeResolutionDialog() }
|
||||
}
|
||||
|
||||
|
@ -332,6 +374,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
|||
togglePhotoVideo()
|
||||
} else {
|
||||
toast(R.string.no_audio_permissions)
|
||||
selectPhotoTab()
|
||||
if (isVideoCaptureIntent()) {
|
||||
finish()
|
||||
}
|
||||
|
@ -369,10 +412,10 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
|||
}
|
||||
|
||||
private fun initPhotoMode() {
|
||||
toggle_photo_video.setImageResource(R.drawable.ic_video_vector)
|
||||
shutter.setImageResource(R.drawable.ic_shutter_vector)
|
||||
mPreview?.initPhotoMode()
|
||||
setupPreviewImage(true)
|
||||
selectPhotoTab()
|
||||
}
|
||||
|
||||
private fun tryInitVideoMode() {
|
||||
|
@ -387,10 +430,10 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
|||
}
|
||||
|
||||
private fun initVideoButtons() {
|
||||
toggle_photo_video.setImageResource(R.drawable.ic_camera_vector)
|
||||
shutter.setImageResource(R.drawable.ic_video_rec)
|
||||
setupPreviewImage(false)
|
||||
mPreview?.checkFlashlight()
|
||||
selectVideoTab()
|
||||
}
|
||||
|
||||
private fun setupPreviewImage(isPhoto: Boolean) {
|
||||
|
@ -487,7 +530,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
|||
}
|
||||
|
||||
private fun animateViews(degrees: Int) {
|
||||
val views = arrayOf<View>(toggle_camera, toggle_flash, toggle_photo_video, change_resolution, shutter, settings, last_photo_video_preview)
|
||||
val views = arrayOf<View>(toggle_camera, toggle_flash, change_resolution, shutter, settings, last_photo_video_preview)
|
||||
for (view in views) {
|
||||
rotate(view, degrees)
|
||||
}
|
||||
|
@ -514,7 +557,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
|||
if (available) {
|
||||
toggle_flash.beVisible()
|
||||
} else {
|
||||
toggle_flash.beGone()
|
||||
toggle_flash.beInvisible()
|
||||
toggle_flash.setImageResource(R.drawable.ic_flash_off_vector)
|
||||
mPreview?.setFlashlightState(FLASH_OFF)
|
||||
}
|
||||
|
@ -587,6 +630,18 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
|||
mFocusCircleView.drawFocusCircle(xPos, yPos)
|
||||
}
|
||||
|
||||
override fun onSwipeLeft() {
|
||||
if (!is3rdPartyIntent()) {
|
||||
selectPhotoTab(triggerListener = true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSwipeRight() {
|
||||
if (!is3rdPartyIntent()) {
|
||||
selectVideoTab(triggerListener = true)
|
||||
}
|
||||
}
|
||||
|
||||
fun setRecordingState(isRecording: Boolean) {
|
||||
runOnUiThread {
|
||||
if (isRecording) {
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package com.simplemobiletools.camera.helpers
|
||||
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
|
||||
interface TabSelectedListener : TabLayout.OnTabSelectedListener {
|
||||
override fun onTabReselected(tab: TabLayout.Tab?){}
|
||||
|
||||
override fun onTabUnselected(tab: TabLayout.Tab?) {}
|
||||
}
|
|
@ -31,6 +31,7 @@ import com.simplemobiletools.camera.models.MediaOutput
|
|||
import com.simplemobiletools.camera.models.MySize
|
||||
import com.simplemobiletools.commons.extensions.toast
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
import kotlin.math.abs
|
||||
|
||||
class CameraXPreview(
|
||||
private val activity: AppCompatActivity,
|
||||
|
@ -45,6 +46,7 @@ class CameraXPreview(
|
|||
// Auto focus is 1/6 of the area.
|
||||
private const val AF_SIZE = 1.0f / 6.0f
|
||||
private const val AE_SIZE = AF_SIZE * 1.5f
|
||||
private const val MIN_SWIPE_DISTANCE_X = 100
|
||||
}
|
||||
|
||||
private val config = activity.config
|
||||
|
@ -278,11 +280,26 @@ class CameraXPreview(
|
|||
true
|
||||
} ?: false
|
||||
}
|
||||
|
||||
override fun onFling(event1: MotionEvent, event2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
|
||||
val deltaX = event1.x - event2.x
|
||||
val deltaXAbs = abs(deltaX)
|
||||
|
||||
if (deltaXAbs >= MIN_SWIPE_DISTANCE_X) {
|
||||
if (deltaX > 0) {
|
||||
listener.onSwipeLeft()
|
||||
} else {
|
||||
listener.onSwipeRight()
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
})
|
||||
previewView.setOnTouchListener { _, event ->
|
||||
gestureDetector.onTouchEvent(event)
|
||||
scaleGesture?.onTouchEvent(event)
|
||||
true
|
||||
val handledGesture = gestureDetector.onTouchEvent(event)
|
||||
val handledScaleGesture = scaleGesture?.onTouchEvent(event)
|
||||
handledGesture || handledScaleGesture ?: false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,4 +16,6 @@ interface CameraXPreviewListener {
|
|||
fun onVideoRecordingStopped()
|
||||
fun onVideoDurationChanged(durationNanos: Long)
|
||||
fun onFocusCamera(xPos: Float, yPos: Float)
|
||||
fun onSwipeLeft()
|
||||
fun onSwipeRight()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/tab_indicator_selected" android:state_selected="true" />
|
||||
<item android:drawable="@drawable/tab_indicator_unselected" />
|
||||
</selector>
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:bottom="@dimen/tab_indicator_margin"
|
||||
android:end="@dimen/tab_indicator_margin"
|
||||
android:start="@dimen/tab_indicator_margin"
|
||||
android:top="@dimen/tab_indicator_margin">
|
||||
<shape>
|
||||
<corners android:radius="@dimen/tab_indicator_margin" />
|
||||
<solid android:color="@color/md_grey_white" />
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/transparent" />
|
||||
</shape>
|
|
@ -30,21 +30,6 @@
|
|||
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_marginStart="@dimen/normal_margin"
|
||||
android:layout_marginEnd="@dimen/normal_margin"
|
||||
android:contentDescription="@string/toggle_photo_video"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_video_vector"
|
||||
app:layout_constraintEnd_toStartOf="@id/toggle_flash"
|
||||
app:layout_constraintHorizontal_chainStyle="spread_inside"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/toggle_flash"
|
||||
android:layout_width="@dimen/icon_size"
|
||||
|
@ -56,15 +41,15 @@
|
|||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_flash_off_vector"
|
||||
app:layout_constraintEnd_toStartOf="@id/change_resolution"
|
||||
app:layout_constraintStart_toEndOf="@id/toggle_photo_video"
|
||||
app:layout_constraintTop_toTopOf="@id/toggle_photo_video" />
|
||||
app:layout_constraintHorizontal_chainStyle="spread_inside"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/change_resolution"
|
||||
android:layout_width="@dimen/icon_size"
|
||||
android:layout_height="@dimen/icon_size"
|
||||
android:layout_below="@+id/toggle_photo_video"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginStart="@dimen/normal_margin"
|
||||
android:layout_marginEnd="@dimen/normal_margin"
|
||||
|
@ -73,7 +58,7 @@
|
|||
android:src="@drawable/ic_resolution_vector"
|
||||
app:layout_constraintEnd_toStartOf="@id/settings"
|
||||
app:layout_constraintStart_toEndOf="@id/toggle_flash"
|
||||
app:layout_constraintTop_toTopOf="@id/toggle_photo_video" />
|
||||
app:layout_constraintTop_toTopOf="@id/toggle_flash" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/settings"
|
||||
|
@ -86,7 +71,7 @@
|
|||
android:src="@drawable/ic_settings_cog_vector"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/change_resolution"
|
||||
app:layout_constraintTop_toTopOf="@id/toggle_photo_video" />
|
||||
app:layout_constraintTop_toTopOf="@id/toggle_flash" />
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
|
@ -94,8 +79,7 @@
|
|||
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" />
|
||||
|
||||
app:constraint_referenced_ids="settings,change_resolution,toggle_flash" />
|
||||
|
||||
<View
|
||||
android:id="@+id/bottom_overlay"
|
||||
|
@ -105,7 +89,38 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/shutter" />
|
||||
app:layout_constraintTop_toTopOf="@id/camera_mode_tab" />
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/camera_mode_tab"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/big_margin"
|
||||
android:background="@android:color/transparent"
|
||||
app:layout_constraintBottom_toTopOf="@id/shutter"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:tabBackground="@drawable/tab_indicator"
|
||||
app:tabIndicator="@null"
|
||||
app:tabMode="auto"
|
||||
app:tabRippleColor="@color/md_grey_600_dark"
|
||||
app:tabSelectedTextColor="@color/md_grey_600_dark"
|
||||
app:tabTextColor="@color/md_grey_white">
|
||||
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:id="@+id/camera_mode_tab_video"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/video" />
|
||||
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:id="@+id/camera_mode_tab_photo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/photo" />
|
||||
|
||||
</com.google.android.material.tabs.TabLayout>
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/toggle_camera"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="icon_size">56dp</dimen>
|
||||
<dimen name="tab_indicator_margin">10dp</dimen>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue