Merge pull request #428 from fatihergin/feature/migrating-to-viewbinding

Feature/migrating to viewbinding
This commit is contained in:
Tibor Kaputa
2023-07-31 10:10:40 +02:00
committed by GitHub
4 changed files with 277 additions and 231 deletions

View File

@@ -1,6 +1,5 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
def keystorePropertiesFile = rootProject.file("keystore.properties") def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties() def keystoreProperties = new Properties()
@@ -32,6 +31,11 @@ android {
} }
} }
buildFeatures {
buildConfig true
viewBinding true
}
buildTypes { buildTypes {
debug { debug {
applicationIdSuffix ".debug" applicationIdSuffix ".debug"

View File

@@ -25,6 +25,7 @@ import com.google.android.material.button.MaterialButtonToggleGroup
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import com.simplemobiletools.camera.BuildConfig import com.simplemobiletools.camera.BuildConfig
import com.simplemobiletools.camera.R import com.simplemobiletools.camera.R
import com.simplemobiletools.camera.databinding.ActivityMainBinding
import com.simplemobiletools.camera.extensions.config import com.simplemobiletools.camera.extensions.config
import com.simplemobiletools.camera.extensions.fadeIn import com.simplemobiletools.camera.extensions.fadeIn
import com.simplemobiletools.camera.extensions.fadeOut import com.simplemobiletools.camera.extensions.fadeOut
@@ -40,10 +41,6 @@ import com.simplemobiletools.camera.views.FocusCircleView
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.Release import com.simplemobiletools.commons.models.Release
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.layout_flash.*
import kotlinx.android.synthetic.main.layout_timer.*
import kotlinx.android.synthetic.main.layout_top.*
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.math.abs import kotlin.math.abs
@@ -62,6 +59,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
private lateinit var mOrientationEventListener: OrientationEventListener private lateinit var mOrientationEventListener: OrientationEventListener
private lateinit var mFocusCircleView: FocusCircleView private lateinit var mFocusCircleView: FocusCircleView
private lateinit var mediaSoundHelper: MediaSoundHelper private lateinit var mediaSoundHelper: MediaSoundHelper
private lateinit var binding: ActivityMainBinding
private var mPreview: MyPreview? = null private var mPreview: MyPreview? = null
private var mediaSizeToggleGroup: MaterialButtonToggleGroup? = null private var mediaSizeToggleGroup: MaterialButtonToggleGroup? = null
private var mPreviewUri: Uri? = null private var mPreviewUri: Uri? = null
@@ -92,6 +90,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
useDynamicTheme = false useDynamicTheme = false
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
appLaunched(BuildConfig.APPLICATION_ID) appLaunched(BuildConfig.APPLICATION_ID)
requestWindowFeature(Window.FEATURE_NO_TITLE) requestWindowFeature(Window.FEATURE_NO_TITLE)
initVariables() initVariables()
@@ -166,7 +165,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
removeTabListener() removeTabListener()
} }
camera_mode_tab.getTabAt(PHOTO_MODE_INDEX)?.select() binding.cameraModeTab.getTabAt(PHOTO_MODE_INDEX)?.select()
setTabListener() setTabListener()
} }
@@ -174,16 +173,16 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
if (!triggerListener) { if (!triggerListener) {
removeTabListener() removeTabListener()
} }
camera_mode_tab.getTabAt(VIDEO_MODE_INDEX)?.select() binding.cameraModeTab.getTabAt(VIDEO_MODE_INDEX)?.select()
setTabListener() setTabListener()
} }
private fun setTabListener() { private fun setTabListener() {
camera_mode_tab.addOnTabSelectedListener(tabSelectedListener) binding.cameraModeTab.addOnTabSelectedListener(tabSelectedListener)
} }
private fun removeTabListener() { private fun removeTabListener() {
camera_mode_tab.removeOnTabSelectedListener(tabSelectedListener) binding.cameraModeTab.removeOnTabSelectedListener(tabSelectedListener)
} }
private fun ensureTransparentNavigationBar() { private fun ensureTransparentNavigationBar() {
@@ -217,10 +216,10 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
return super.onKeyUp(keyCode, event) return super.onKeyUp(keyCode, event)
} }
private fun hideIntentButtons() { private fun hideIntentButtons() = binding.apply {
camera_mode_holder.beGone() cameraModeHolder.beGone()
settings.beGone() layoutTop.settings.beGone()
last_photo_video_preview.beInvisible() lastPhotoVideoPreview.beInvisible()
} }
private fun tryInitCamera() { private fun tryInitCamera() {
@@ -297,25 +296,27 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
} }
private fun initializeCamera(isInPhotoMode: Boolean) { private fun initializeCamera(isInPhotoMode: Boolean) {
setContentView(R.layout.activity_main) setContentView(binding.root)
initButtons() initButtons()
initModeSwitcher() initModeSwitcher()
defaultScene = Scene(top_options, default_icons) binding.apply {
flashModeScene = Scene(top_options, flash_toggle_group) defaultScene = Scene(topOptions, layoutTop.defaultIcons)
timerScene = Scene(top_options, timer_toggle_group) flashModeScene = Scene(topOptions, layoutFlash.flashToggleGroup)
timerScene = Scene(topOptions, layoutTimer.timerToggleGroup)
}
WindowCompat.setDecorFitsSystemWindows(window, false) WindowCompat.setDecorFitsSystemWindows(window, false)
ViewCompat.setOnApplyWindowInsetsListener(view_holder) { _, windowInsets -> ViewCompat.setOnApplyWindowInsetsListener(binding.viewHolder) { _, windowInsets ->
val safeInsetBottom = windowInsets.displayCutout?.safeInsetBottom ?: 0 val safeInsetBottom = windowInsets.displayCutout?.safeInsetBottom ?: 0
val safeInsetTop = windowInsets.displayCutout?.safeInsetTop ?: 0 val safeInsetTop = windowInsets.displayCutout?.safeInsetTop ?: 0
top_options.updateLayoutParams<ViewGroup.MarginLayoutParams> { binding.topOptions.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = safeInsetTop topMargin = safeInsetTop
} }
val marginBottom = safeInsetBottom + navigationBarHeight + resources.getDimensionPixelSize(R.dimen.bigger_margin) val marginBottom = safeInsetBottom + navigationBarHeight + resources.getDimensionPixelSize(R.dimen.bigger_margin)
shutter.updateLayoutParams<ViewGroup.MarginLayoutParams> { binding.shutter.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = marginBottom bottomMargin = marginBottom
} }
@@ -331,7 +332,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
val outputUri = intent.extras?.get(MediaStore.EXTRA_OUTPUT) as? Uri val outputUri = intent.extras?.get(MediaStore.EXTRA_OUTPUT) as? Uri
val isThirdPartyIntent = isThirdPartyIntent() val isThirdPartyIntent = isThirdPartyIntent()
mPreview = CameraXInitializer(this).createCameraXPreview( mPreview = CameraXInitializer(this).createCameraXPreview(
preview_view, binding.previewView,
listener = this, listener = this,
mediaSoundHelper = mediaSoundHelper, mediaSoundHelper = mediaSoundHelper,
outputUri = outputUri, outputUri = outputUri,
@@ -342,7 +343,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
mFocusCircleView = FocusCircleView(this).apply { mFocusCircleView = FocusCircleView(this).apply {
id = View.generateViewId() id = View.generateViewId()
} }
view_holder.addView(mFocusCircleView) binding.viewHolder.addView(mFocusCircleView)
setupPreviewImage(true) setupPreviewImage(true)
initFlashModeTransitionNames() initFlashModeTransitionNames()
@@ -353,64 +354,72 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
} }
} }
private fun initFlashModeTransitionNames() { private fun initFlashModeTransitionNames() = binding.layoutFlash.apply {
val baseName = getString(R.string.toggle_flash) val baseName = getString(R.string.toggle_flash)
flash_auto.transitionName = "$baseName$FLASH_AUTO" flashAuto.transitionName = "$baseName$FLASH_AUTO"
flash_off.transitionName = "$baseName$FLASH_OFF" flashOff.transitionName = "$baseName$FLASH_OFF"
flash_on.transitionName = "$baseName$FLASH_ON" flashOn.transitionName = "$baseName$FLASH_ON"
flash_always_on.transitionName = "$baseName$FLASH_ALWAYS_ON" flashAlwaysOn.transitionName = "$baseName$FLASH_ALWAYS_ON"
} }
private fun initTimerModeTransitionNames() { private fun initTimerModeTransitionNames() = binding.layoutTimer.apply {
val baseName = getString(R.string.toggle_timer) val baseName = getString(R.string.toggle_timer)
timer_off.transitionName = "$baseName${TimerMode.OFF.name}" timerOff.transitionName = "$baseName${TimerMode.OFF.name}"
timer_3s.transitionName = "$baseName${TimerMode.TIMER_3.name}" timer3s.transitionName = "$baseName${TimerMode.TIMER_3.name}"
timer_5s.transitionName = "$baseName${TimerMode.TIMER_5.name}" timer5s.transitionName = "$baseName${TimerMode.TIMER_5.name}"
timer_10_s.transitionName = "$baseName${TimerMode.TIMER_10.name}" timer10S.transitionName = "$baseName${TimerMode.TIMER_10.name}"
} }
private fun initButtons() { private fun initButtons() = binding.apply {
timer_text.setFactory { layoutInflater.inflate(R.layout.timer_text, null) } timerText.setFactory { layoutInflater.inflate(R.layout.timer_text, null) }
toggle_camera.setOnClickListener { mPreview!!.toggleFrontBackCamera() } toggleCamera.setOnClickListener { mPreview!!.toggleFrontBackCamera() }
last_photo_video_preview.setOnClickListener { showLastMediaPreview() } lastPhotoVideoPreview.setOnClickListener { showLastMediaPreview() }
toggle_flash.setOnClickListener { mPreview!!.handleFlashlightClick() }
toggle_timer.setOnClickListener { layoutTop.apply {
val transitionSet = createTransition() toggleFlash.setOnClickListener { mPreview!!.handleFlashlightClick() }
TransitionManager.go(timerScene, transitionSet) toggleTimer.setOnClickListener {
timer_toggle_group.beVisible() val transitionSet = createTransition()
timer_toggle_group.check(config.timerMode.getTimerModeResId()) TransitionManager.go(timerScene, transitionSet)
timer_toggle_group.children.forEach { setButtonColors(it as MaterialButton) } layoutTimer.timerToggleGroup.beVisible()
layoutTimer.timerToggleGroup.check(config.timerMode.getTimerModeResId())
layoutTimer.timerToggleGroup.children.forEach { setButtonColors(it as MaterialButton) }
}
settings.setShadowIcon(R.drawable.ic_settings_vector)
settings.setOnClickListener { launchSettings() }
changeResolution.setOnClickListener { mPreview?.showChangeResolution() }
} }
shutter.setOnClickListener { shutterPressed() } shutter.setOnClickListener { shutterPressed() }
settings.setShadowIcon(R.drawable.ic_settings_vector) layoutFlash.apply {
settings.setOnClickListener { launchSettings() } flashOn.setShadowIcon(R.drawable.ic_flash_on_vector)
flashOn.setOnClickListener { selectFlashMode(FLASH_ON) }
change_resolution.setOnClickListener { mPreview?.showChangeResolution() } flashOff.setShadowIcon(R.drawable.ic_flash_off_vector)
flashOff.setOnClickListener { selectFlashMode(FLASH_OFF) }
flash_on.setShadowIcon(R.drawable.ic_flash_on_vector) flashAuto.setShadowIcon(R.drawable.ic_flash_auto_vector)
flash_on.setOnClickListener { selectFlashMode(FLASH_ON) } flashAuto.setOnClickListener { selectFlashMode(FLASH_AUTO) }
flash_off.setShadowIcon(R.drawable.ic_flash_off_vector) flashAlwaysOn.setShadowIcon(R.drawable.ic_flashlight_vector)
flash_off.setOnClickListener { selectFlashMode(FLASH_OFF) } flashAlwaysOn.setOnClickListener { selectFlashMode(FLASH_ALWAYS_ON) }
}
flash_auto.setShadowIcon(R.drawable.ic_flash_auto_vector) layoutTimer.apply {
flash_auto.setOnClickListener { selectFlashMode(FLASH_AUTO) } timerOff.setShadowIcon(R.drawable.ic_timer_off_vector)
timerOff.setOnClickListener { selectTimerMode(TimerMode.OFF) }
flash_always_on.setShadowIcon(R.drawable.ic_flashlight_vector) timer3s.setShadowIcon(R.drawable.ic_timer_3_vector)
flash_always_on.setOnClickListener { selectFlashMode(FLASH_ALWAYS_ON) } timer3s.setOnClickListener { selectTimerMode(TimerMode.TIMER_3) }
timer_off.setShadowIcon(R.drawable.ic_timer_off_vector) timer5s.setShadowIcon(R.drawable.ic_timer_5_vector)
timer_off.setOnClickListener { selectTimerMode(TimerMode.OFF) } timer5s.setOnClickListener { selectTimerMode(TimerMode.TIMER_5) }
timer_3s.setShadowIcon(R.drawable.ic_timer_3_vector) timer10S.setShadowIcon(R.drawable.ic_timer_10_vector)
timer_3s.setOnClickListener { selectTimerMode(TimerMode.TIMER_3) } timer10S.setOnClickListener { selectTimerMode(TimerMode.TIMER_10) }
}
timer_5s.setShadowIcon(R.drawable.ic_timer_5_vector)
timer_5s.setOnClickListener { selectTimerMode(TimerMode.TIMER_5) }
timer_10_s.setShadowIcon(R.drawable.ic_timer_10_vector)
timer_10_s.setOnClickListener { selectTimerMode(TimerMode.TIMER_10) }
setTimerModeIcon(config.timerMode) setTimerModeIcon(config.timerMode)
} }
@@ -420,9 +429,9 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
closeOptions() closeOptions()
} }
private fun setTimerModeIcon(timerMode: TimerMode) { private fun setTimerModeIcon(timerMode: TimerMode) = binding.layoutTop.toggleTimer.apply {
toggle_timer.setShadowIcon(timerMode.getTimerModeDrawableRes()) setShadowIcon(timerMode.getTimerModeDrawableRes())
toggle_timer.transitionName = "${getString(R.string.toggle_timer)}${timerMode.name}" transitionName = "${getString(R.string.toggle_timer)}${timerMode.name}"
} }
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
@@ -453,19 +462,19 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
} }
}) })
camera_mode_tab.setOnTouchListener { _, event -> binding.cameraModeTab.setOnTouchListener { _, event ->
gestureDetector.onTouchEvent(event) gestureDetector.onTouchEvent(event)
} }
} }
private fun onSwipeLeft() { private fun onSwipeLeft() {
if (!isThirdPartyIntent() && camera_mode_holder.isVisible()) { if (!isThirdPartyIntent() && binding.cameraModeHolder.isVisible()) {
selectPhotoTab(triggerListener = true) selectPhotoTab(triggerListener = true)
} }
} }
private fun onSwipeRight() { private fun onSwipeRight() {
if (!isThirdPartyIntent() && camera_mode_holder.isVisible()) { if (!isThirdPartyIntent() && binding.cameraModeHolder.isVisible()) {
selectVideoTab(triggerListener = true) selectVideoTab(triggerListener = true)
} }
} }
@@ -511,17 +520,21 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
} }
override fun onInitPhotoMode() { override fun onInitPhotoMode() {
shutter.setImageResource(R.drawable.ic_shutter_animated) binding.apply {
toggle_timer.beVisible() shutter.setImageResource(R.drawable.ic_shutter_animated)
toggle_timer.fadeIn() layoutTop.toggleTimer.beVisible()
layoutTop.toggleTimer.fadeIn()
}
setupPreviewImage(true) setupPreviewImage(true)
selectPhotoTab() selectPhotoTab()
} }
override fun onInitVideoMode() { override fun onInitVideoMode() {
shutter.setImageResource(R.drawable.ic_video_rec_animated) binding.apply {
toggle_timer.fadeOut() shutter.setImageResource(R.drawable.ic_video_rec_animated)
toggle_timer.beGone() layoutTop.toggleTimer.fadeOut()
layoutTop.toggleTimer.beGone()
}
setupPreviewImage(false) setupPreviewImage(false)
selectVideoTab() selectVideoTab()
} }
@@ -550,7 +563,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
.load(uri) .load(uri)
.apply(options) .apply(options)
.transition(DrawableTransitionOptions.withCrossFade()) .transition(DrawableTransitionOptions.withCrossFade())
.into(last_photo_video_preview) .into(binding.lastPhotoVideoPreview)
} }
} }
} }
@@ -603,8 +616,15 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
} }
} }
private fun animateViews(degrees: Int) { private fun animateViews(degrees: Int) = binding.apply {
val views = arrayOf<View>(toggle_camera, toggle_flash, change_resolution, shutter, settings, last_photo_video_preview) val views = arrayOf(
toggleCamera,
layoutTop.toggleFlash,
layoutTop.changeResolution,
shutter,
layoutTop.settings,
lastPhotoVideoPreview
)
for (view in views) { for (view in views) {
rotate(view, degrees) rotate(view, degrees)
} }
@@ -613,20 +633,20 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
private fun rotate(view: View, degrees: Int) = view.animate().rotation(degrees.toFloat()).start() private fun rotate(view: View, degrees: Int) = view.animate().rotation(degrees.toFloat()).start()
override fun setHasFrontAndBackCamera(hasFrontAndBack: Boolean) { override fun setHasFrontAndBackCamera(hasFrontAndBack: Boolean) {
toggle_camera?.beVisibleIf(hasFrontAndBack) binding.toggleCamera?.beVisibleIf(hasFrontAndBack)
} }
override fun setFlashAvailable(available: Boolean) { override fun setFlashAvailable(available: Boolean) {
if (available) { if (available) {
toggle_flash.beVisible() binding.layoutTop.toggleFlash.beVisible()
} else { } else {
toggle_flash.beGone() binding.layoutTop.toggleFlash.beGone()
mPreview?.setFlashlightState(FLASH_OFF) mPreview?.setFlashlightState(FLASH_OFF)
} }
} }
override fun onChangeCamera(frontCamera: Boolean) { override fun onChangeCamera(frontCamera: Boolean) {
toggle_camera.setImageResource(if (frontCamera) R.drawable.ic_camera_rear_vector else R.drawable.ic_camera_front_vector) binding.toggleCamera.setImageResource(if (frontCamera) R.drawable.ic_camera_rear_vector else R.drawable.ic_camera_front_vector)
} }
override fun onPhotoCaptureStart() { override fun onPhotoCaptureStart() {
@@ -637,23 +657,23 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
toggleActionButtons(enabled = true) toggleActionButtons(enabled = true)
} }
private fun toggleActionButtons(enabled: Boolean) { private fun toggleActionButtons(enabled: Boolean) = binding.apply {
runOnUiThread { runOnUiThread {
shutter.isClickable = enabled shutter.isClickable = enabled
preview_view.isEnabled = enabled previewView.isEnabled = enabled
change_resolution.isEnabled = enabled layoutTop.changeResolution.isEnabled = enabled
toggle_camera.isClickable = enabled toggleCamera.isClickable = enabled
toggle_flash.isClickable = enabled layoutTop.toggleFlash.isClickable = enabled
} }
} }
override fun shutterAnimation() { override fun shutterAnimation() {
shutter_animation.alpha = 1.0f binding.shutterAnimation.alpha = 1.0f
shutter_animation.animate().alpha(0f).setDuration(CAPTURE_ANIMATION_DURATION).start() binding.shutterAnimation.animate().alpha(0f).setDuration(CAPTURE_ANIMATION_DURATION).start()
} }
override fun onMediaSaved(uri: Uri) { override fun onMediaSaved(uri: Uri) {
change_resolution.isEnabled = true binding.layoutTop.changeResolution.isEnabled = true
loadLastTakenMedia(uri) loadLastTakenMedia(uri)
if (isImageCaptureIntent()) { if (isImageCaptureIntent()) {
Intent().apply { Intent().apply {
@@ -683,49 +703,55 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
} }
override fun onChangeFlashMode(flashMode: Int) { override fun onChangeFlashMode(flashMode: Int) {
val flashDrawable = when (flashMode) { binding.layoutTop.apply {
FLASH_OFF -> R.drawable.ic_flash_off_vector val flashDrawable = when (flashMode) {
FLASH_ON -> R.drawable.ic_flash_on_vector FLASH_OFF -> R.drawable.ic_flash_off_vector
FLASH_AUTO -> R.drawable.ic_flash_auto_vector FLASH_ON -> R.drawable.ic_flash_on_vector
else -> R.drawable.ic_flashlight_vector FLASH_AUTO -> R.drawable.ic_flash_auto_vector
else -> R.drawable.ic_flashlight_vector
}
toggleFlash.setShadowIcon(flashDrawable)
toggleFlash.transitionName = "${getString(R.string.toggle_flash)}$flashMode"
} }
toggle_flash.setShadowIcon(flashDrawable)
toggle_flash.transitionName = "${getString(R.string.toggle_flash)}$flashMode"
} }
override fun onVideoRecordingStarted() { override fun onVideoRecordingStarted() {
camera_mode_holder.beInvisible() binding.apply {
video_rec_curr_timer.beVisible() cameraModeHolder.beInvisible()
videoRecCurrTimer.beVisible()
toggle_camera.fadeOut() toggleCamera.fadeOut()
last_photo_video_preview.fadeOut() lastPhotoVideoPreview.fadeOut()
change_resolution.isEnabled = false layoutTop.changeResolution.isEnabled = false
settings.isEnabled = false layoutTop.settings.isEnabled = false
shutter.post { shutter.post {
if (!isDestroyed) { if (!isDestroyed) {
shutter.isSelected = true shutter.isSelected = true
}
} }
} }
} }
override fun onVideoRecordingStopped() { override fun onVideoRecordingStopped() {
camera_mode_holder.beVisible() binding.apply {
cameraModeHolder.beVisible()
toggle_camera.fadeIn() toggleCamera.fadeIn()
last_photo_video_preview.fadeIn() lastPhotoVideoPreview.fadeIn()
video_rec_curr_timer.text = 0.getFormattedDuration() videoRecCurrTimer.text = 0.getFormattedDuration()
video_rec_curr_timer.beGone() videoRecCurrTimer.beGone()
shutter.isSelected = false shutter.isSelected = false
change_resolution.isEnabled = true layoutTop.changeResolution.isEnabled = true
settings.isEnabled = true layoutTop.settings.isEnabled = true
}
} }
override fun onVideoDurationChanged(durationNanos: Long) { override fun onVideoDurationChanged(durationNanos: Long) {
val seconds = TimeUnit.NANOSECONDS.toSeconds(durationNanos).toInt() val seconds = TimeUnit.NANOSECONDS.toSeconds(durationNanos).toInt()
video_rec_curr_timer.text = seconds.getFormattedDuration() binding.videoRecCurrTimer.text = seconds.getFormattedDuration()
} }
override fun onFocusCamera(xPos: Float, yPos: Float) { override fun onFocusCamera(xPos: Float, yPos: Float) {
@@ -737,25 +763,27 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
} }
private fun closeOptions(): Boolean { private fun closeOptions(): Boolean {
if (mediaSizeToggleGroup?.isVisible() == true || binding.apply {
flash_toggle_group.isVisible() || timer_toggle_group.isVisible() if (mediaSizeToggleGroup?.isVisible() == true ||
) { layoutFlash.flashToggleGroup.isVisible() || layoutTimer.timerToggleGroup.isVisible()
val transitionSet = createTransition() ) {
TransitionManager.go(defaultScene, transitionSet) val transitionSet = createTransition()
mediaSizeToggleGroup?.beGone() TransitionManager.go(defaultScene, transitionSet)
flash_toggle_group.beGone() mediaSizeToggleGroup?.beGone()
timer_toggle_group.beGone() layoutFlash.flashToggleGroup.beGone()
default_icons.beVisible() layoutTimer.timerToggleGroup.beGone()
return true layoutTop.defaultIcons.beVisible()
} return true
}
return false return false
}
} }
override fun displaySelectedResolution(resolutionOption: ResolutionOption) { override fun displaySelectedResolution(resolutionOption: ResolutionOption) {
val imageRes = resolutionOption.imageDrawableResId val imageRes = resolutionOption.imageDrawableResId
change_resolution.setShadowIcon(imageRes) binding.layoutTop.changeResolution.setShadowIcon(imageRes)
change_resolution.transitionName = "${resolutionOption.buttonViewId}" binding.layoutTop.changeResolution.transitionName = "${resolutionOption.buttonViewId}"
} }
override fun showImageSizes( override fun showImageSizes(
@@ -765,12 +793,12 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
isFrontCamera: Boolean, isFrontCamera: Boolean,
onSelect: (index: Int, changed: Boolean) -> Unit onSelect: (index: Int, changed: Boolean) -> Unit
) { ) {
top_options.removeView(mediaSizeToggleGroup) binding.topOptions.removeView(mediaSizeToggleGroup)
val mediaSizeToggleGroup = createToggleGroup().apply { val mediaSizeToggleGroup = createToggleGroup().apply {
mediaSizeToggleGroup = this mediaSizeToggleGroup = this
} }
top_options.addView(mediaSizeToggleGroup) binding.topOptions.addView(mediaSizeToggleGroup)
val onItemClick = { clickedViewId: Int -> val onItemClick = { clickedViewId: Int ->
closeOptions() closeOptions()
@@ -786,9 +814,9 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
mediaSizeToggleGroup.check(selectedResolution.buttonViewId) mediaSizeToggleGroup.check(selectedResolution.buttonViewId)
val transitionSet = createTransition() val transitionSet = createTransition()
val mediaSizeScene = Scene(top_options, mediaSizeToggleGroup) val mediaSizeScene = Scene(binding.topOptions, mediaSizeToggleGroup)
TransitionManager.go(mediaSizeScene, transitionSet) TransitionManager.go(mediaSizeScene, transitionSet)
default_icons.beGone() binding.layoutTop.defaultIcons.beGone()
mediaSizeToggleGroup.beVisible() mediaSizeToggleGroup.beVisible()
mediaSizeToggleGroup.children.map { it as MaterialButton }.forEach(::setButtonColors) mediaSizeToggleGroup.children.map { it as MaterialButton }.forEach(::setButtonColors)
} }
@@ -818,14 +846,16 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
} }
override fun showFlashOptions(photoCapture: Boolean) { override fun showFlashOptions(photoCapture: Boolean) {
val transitionSet = createTransition() binding.layoutFlash.apply {
TransitionManager.go(flashModeScene, transitionSet) val transitionSet = createTransition()
flash_auto.beVisibleIf(photoCapture) TransitionManager.go(flashModeScene, transitionSet)
flash_always_on.beVisibleIf(photoCapture) flashAuto.beVisibleIf(photoCapture)
flash_toggle_group.check(config.flashlightState.toFlashModeId()) flashAlwaysOn.beVisibleIf(photoCapture)
flashToggleGroup.check(config.flashlightState.toFlashModeId())
flash_toggle_group.beVisible() flashToggleGroup.beVisible()
flash_toggle_group.children.forEach { setButtonColors(it as MaterialButton) } flashToggleGroup.children.forEach { setButtonColors(it as MaterialButton) }
}
} }
private fun setButtonColors(button: MaterialButton) { private fun setButtonColors(button: MaterialButton) {
@@ -836,16 +866,18 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
} }
override fun adjustPreviewView(requiresCentering: Boolean) { override fun adjustPreviewView(requiresCentering: Boolean) {
val constraintSet = ConstraintSet() binding.apply {
constraintSet.clone(view_holder) val constraintSet = ConstraintSet()
if (requiresCentering) { constraintSet.clone(viewHolder)
constraintSet.connect(preview_view.id, ConstraintSet.TOP, top_options.id, ConstraintSet.BOTTOM) if (requiresCentering) {
constraintSet.connect(preview_view.id, ConstraintSet.BOTTOM, camera_mode_holder.id, ConstraintSet.TOP) constraintSet.connect(previewView.id, ConstraintSet.TOP, topOptions.id, ConstraintSet.BOTTOM)
} else { constraintSet.connect(previewView.id, ConstraintSet.BOTTOM, cameraModeHolder.id, ConstraintSet.TOP)
constraintSet.connect(preview_view.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP) } else {
constraintSet.connect(preview_view.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM) constraintSet.connect(previewView.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP)
constraintSet.connect(previewView.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
}
constraintSet.applyTo(viewHolder)
} }
constraintSet.applyTo(view_holder)
} }
override fun mediaSaved(path: String) { override fun mediaSaved(path: String) {
@@ -866,13 +898,13 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
private fun scheduleTimer(timerMode: TimerMode) { private fun scheduleTimer(timerMode: TimerMode) {
hideViewsOnTimerStart() hideViewsOnTimerStart()
shutter.setImageState(intArrayOf(R.attr.state_timer_cancel), true) binding.shutter.setImageState(intArrayOf(R.attr.state_timer_cancel), true)
timer_text.beVisible() binding.timerText.beVisible()
var playSound = true var playSound = true
countDownTimer = object : CountDownTimer(timerMode.millisInFuture, 1000) { countDownTimer = object : CountDownTimer(timerMode.millisInFuture, 1000) {
override fun onTick(millisUntilFinished: Long) { override fun onTick(millisUntilFinished: Long) {
val seconds = (TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) + 1).toString() val seconds = (TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) + 1).toString()
timer_text.setText(seconds) binding.timerText.setText(seconds)
if (playSound && config.isSoundEnabled) { if (playSound && config.isSoundEnabled) {
if (millisUntilFinished <= TIMER_2_SECONDS) { if (millisUntilFinished <= TIMER_2_SECONDS) {
mediaSoundHelper.playTimerCountdown2SecondsSound() mediaSoundHelper.playTimerCountdown2SecondsSound()
@@ -890,20 +922,20 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
}.start() }.start()
} }
private fun hideViewsOnTimerStart() { private fun hideViewsOnTimerStart() = binding.apply {
arrayOf(top_options, toggle_camera, last_photo_video_preview, camera_mode_holder).forEach { arrayOf(topOptions, toggleCamera, lastPhotoVideoPreview, cameraModeHolder).forEach {
it.fadeOut() it.fadeOut()
it.beInvisible() it.beInvisible()
} }
} }
private fun resetViewsOnTimerFinish() { private fun resetViewsOnTimerFinish() = binding.apply {
arrayOf(top_options, toggle_camera, last_photo_video_preview, camera_mode_holder).forEach { arrayOf(topOptions, toggleCamera, lastPhotoVideoPreview, cameraModeHolder).forEach {
it?.fadeIn() it?.fadeIn()
it?.beVisible() it?.beVisible()
} }
timer_text.beGone() timerText.beGone()
shutter.setImageState(intArrayOf(-R.attr.state_timer_cancel), true) shutter.setImageState(intArrayOf(-R.attr.state_timer_cancel), true)
} }

View File

@@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.os.Bundle import android.os.Bundle
import com.simplemobiletools.camera.BuildConfig import com.simplemobiletools.camera.BuildConfig
import com.simplemobiletools.camera.R import com.simplemobiletools.camera.R
import com.simplemobiletools.camera.databinding.ActivitySettingsBinding
import com.simplemobiletools.camera.extensions.checkLocationPermission import com.simplemobiletools.camera.extensions.checkLocationPermission
import com.simplemobiletools.camera.extensions.config import com.simplemobiletools.camera.extensions.config
import com.simplemobiletools.camera.models.CaptureMode import com.simplemobiletools.camera.models.CaptureMode
@@ -12,25 +13,29 @@ import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.FAQItem import com.simplemobiletools.commons.models.FAQItem
import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.commons.models.RadioItem
import kotlinx.android.synthetic.main.activity_settings.*
import java.util.* import java.util.*
import kotlin.system.exitProcess import kotlin.system.exitProcess
class SettingsActivity : SimpleActivity() { class SettingsActivity : SimpleActivity() {
private lateinit var binding: ActivitySettingsBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true isMaterialActivity = true
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings) binding = ActivitySettingsBinding.inflate(layoutInflater)
setupOptionsMenu() binding.apply {
refreshMenuItems() setContentView(root)
setupOptionsMenu()
refreshMenuItems()
updateMaterialActivityViews(settings_coordinator, settings_holder, useTransparentNavigation = true, useTopSearchMenu = false) updateMaterialActivityViews(settingsCoordinator, settingsHolder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(settings_nested_scrollview, settings_toolbar) setupMaterialScrollListener(settingsNestedScrollview, settingsToolbar)
}
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
setupToolbar(settings_toolbar, NavigationIcon.Arrow) setupToolbar(binding.settingsToolbar, NavigationIcon.Arrow)
setupPurchaseThankYou() setupPurchaseThankYou()
setupCustomizeColors() setupCustomizeColors()
@@ -44,27 +49,29 @@ class SettingsActivity : SimpleActivity() {
setupSavePhotosFolder() setupSavePhotosFolder()
setupPhotoQuality() setupPhotoQuality()
setupCaptureMode() setupCaptureMode()
updateTextColors(settings_holder) updateTextColors(binding.settingsHolder)
val properPrimaryColor = getProperPrimaryColor() val properPrimaryColor = getProperPrimaryColor()
arrayListOf( binding.apply {
settings_color_customization_label, arrayListOf(
settings_general_settings_label, settingsColorCustomizationLabel,
settings_shutter_label, settingsGeneralSettingsLabel,
settings_saving_label settingsShutterLabel,
).forEach { settingsSavingLabel,
it.setTextColor(properPrimaryColor) ).forEach {
it.setTextColor(properPrimaryColor)
}
} }
} }
private fun refreshMenuItems() { private fun refreshMenuItems() {
settings_toolbar.menu.apply { binding.settingsToolbar.menu.apply {
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(R.bool.hide_google_relations) findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(R.bool.hide_google_relations)
} }
} }
private fun setupOptionsMenu() { private fun setupOptionsMenu() {
settings_toolbar.setOnMenuItemClickListener { menuItem -> binding.settingsToolbar.setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) { when (menuItem.itemId) {
R.id.more_apps_from_us -> launchMoreAppsFromUsIntent() R.id.more_apps_from_us -> launchMoreAppsFromUsIntent()
R.id.about -> launchAbout() R.id.about -> launchAbout()
@@ -75,38 +82,38 @@ class SettingsActivity : SimpleActivity() {
} }
private fun setupPurchaseThankYou() { private fun setupPurchaseThankYou() {
settings_purchase_thank_you_holder.beGoneIf(isOrWasThankYouInstalled()) binding.settingsPurchaseThankYouHolder.beGoneIf(isOrWasThankYouInstalled())
settings_purchase_thank_you_holder.setOnClickListener { binding.settingsPurchaseThankYouHolder.setOnClickListener {
launchPurchaseThankYouIntent() launchPurchaseThankYouIntent()
} }
} }
private fun setupCustomizeColors() { private fun setupCustomizeColors() {
settings_customize_colors_label.text = getCustomizeColorsString() binding.settingsCustomizeColorsLabel.text = getCustomizeColorsString()
settings_color_customization_holder.setOnClickListener { binding.settingsColorCustomizationHolder.setOnClickListener {
handleCustomizeColorsClick() handleCustomizeColorsClick()
} }
} }
private fun setupUseEnglish() { private fun setupUseEnglish() = binding.apply {
settings_use_english_holder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus()) settingsUseEnglishHolder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus())
settings_use_english.isChecked = config.useEnglish settingsUseEnglish.isChecked = config.useEnglish
settings_use_english_holder.setOnClickListener { settingsUseEnglishHolder.setOnClickListener {
settings_use_english.toggle() settingsUseEnglish.toggle()
config.useEnglish = settings_use_english.isChecked config.useEnglish = settingsUseEnglish.isChecked
exitProcess(0) exitProcess(0)
} }
} }
private fun setupLanguage() { private fun setupLanguage() = binding.apply {
settings_language.text = Locale.getDefault().displayLanguage settingsLanguage.text = Locale.getDefault().displayLanguage
settings_language_holder.beVisibleIf(isTiramisuPlus()) settingsLanguageHolder.beVisibleIf(isTiramisuPlus())
listOf(settings_general_settings_holder, settings_general_settings_label).forEach { listOf(settingsGeneralSettingsHolder, settingsGeneralSettingsLabel).forEach {
it.beGoneIf(settings_use_english_holder.isGone() && settings_purchase_thank_you_holder.isGone() && settings_language_holder.isGone()) it.beGoneIf(settingsUseEnglishHolder.isGone() && settingsPurchaseThankYouHolder.isGone() && settingsLanguageHolder.isGone())
} }
settings_language_holder.setOnClickListener { settingsLanguageHolder.setOnClickListener {
launchChangeAppLanguageIntent() launchChangeAppLanguageIntent()
} }
} }
@@ -131,41 +138,41 @@ class SettingsActivity : SimpleActivity() {
return humanized.substringAfterLast("/", humanized) return humanized.substringAfterLast("/", humanized)
} }
private fun setupSound() { private fun setupSound() = binding.apply {
settings_sound.isChecked = config.isSoundEnabled settingsSound.isChecked = config.isSoundEnabled
settings_sound_holder.setOnClickListener { settingsSoundHolder.setOnClickListener {
settings_sound.toggle() settingsSound.toggle()
config.isSoundEnabled = settings_sound.isChecked config.isSoundEnabled = settingsSound.isChecked
} }
} }
private fun setupVolumeButtonsAsShutter() { private fun setupVolumeButtonsAsShutter() = binding.apply {
settings_volume_buttons_as_shutter.isChecked = config.volumeButtonsAsShutter settingsVolumeButtonsAsShutter.isChecked = config.volumeButtonsAsShutter
settings_volume_buttons_as_shutter_holder.setOnClickListener { settingsVolumeButtonsAsShutterHolder.setOnClickListener {
settings_volume_buttons_as_shutter.toggle() settingsVolumeButtonsAsShutter.toggle()
config.volumeButtonsAsShutter = settings_volume_buttons_as_shutter.isChecked config.volumeButtonsAsShutter = settingsVolumeButtonsAsShutter.isChecked
} }
} }
private fun setupFlipPhotos() { private fun setupFlipPhotos() = binding.apply {
settings_flip_photos.isChecked = config.flipPhotos settingsFlipPhotos.isChecked = config.flipPhotos
settings_flip_photos_holder.setOnClickListener { settingsFlipPhotosHolder.setOnClickListener {
settings_flip_photos.toggle() settingsFlipPhotos.toggle()
config.flipPhotos = settings_flip_photos.isChecked config.flipPhotos = settingsFlipPhotos.isChecked
} }
} }
private fun setupSavePhotoMetadata() { private fun setupSavePhotoMetadata() = binding.apply {
settings_save_photo_metadata.isChecked = config.savePhotoMetadata settingsSavePhotoMetadata.isChecked = config.savePhotoMetadata
settings_save_photo_metadata_holder.setOnClickListener { settingsSavePhotoMetadataHolder.setOnClickListener {
settings_save_photo_metadata.toggle() settingsSavePhotoMetadata.toggle()
config.savePhotoMetadata = settings_save_photo_metadata.isChecked config.savePhotoMetadata = settingsSavePhotoMetadata.isChecked
} }
} }
private fun setupSavePhotoVideoLocation() { private fun setupSavePhotoVideoLocation() = binding.apply {
settings_save_photo_video_location.isChecked = config.savePhotoVideoLocation settingsSavePhotoVideoLocation.isChecked = config.savePhotoVideoLocation
settings_save_photo_video_location_holder.setOnClickListener { settingsSavePhotoVideoLocationHolder.setOnClickListener {
val willEnableSavePhotoVideoLocation = !config.savePhotoVideoLocation val willEnableSavePhotoVideoLocation = !config.savePhotoVideoLocation
if (willEnableSavePhotoVideoLocation) { if (willEnableSavePhotoVideoLocation) {
@@ -187,33 +194,33 @@ class SettingsActivity : SimpleActivity() {
} }
private fun updateSavePhotoVideoLocationConfig(enabled: Boolean) { private fun updateSavePhotoVideoLocationConfig(enabled: Boolean) {
settings_save_photo_video_location.isChecked = enabled binding.settingsSavePhotoVideoLocation.isChecked = enabled
config.savePhotoVideoLocation = enabled config.savePhotoVideoLocation = enabled
} }
private fun setupSavePhotosFolder() { private fun setupSavePhotosFolder() = binding.apply {
settings_save_photos_label.text = addLockedLabelIfNeeded(R.string.save_photos) settingsSavePhotosLabel.text = addLockedLabelIfNeeded(R.string.save_photos)
settings_save_photos.text = getLastPart(config.savePhotosFolder) settingsSavePhotos.text = getLastPart(config.savePhotosFolder)
settings_save_photos_holder.setOnClickListener { settingsSavePhotosHolder.setOnClickListener {
if (isOrWasThankYouInstalled()) { if (isOrWasThankYouInstalled()) {
FilePickerDialog(this, config.savePhotosFolder, false, showFAB = true) { FilePickerDialog(this@SettingsActivity, config.savePhotosFolder, false, showFAB = true) {
val path = it val path = it
handleSAFDialog(it) { success -> handleSAFDialog(it) { success ->
if (success) { if (success) {
config.savePhotosFolder = path config.savePhotosFolder = path
settings_save_photos.text = getLastPart(config.savePhotosFolder) settingsSavePhotos.text = getLastPart(config.savePhotosFolder)
} }
} }
} }
} else { } else {
FeatureLockedDialog(this) { } FeatureLockedDialog(this@SettingsActivity) { }
} }
} }
} }
private fun setupPhotoQuality() { private fun setupPhotoQuality() {
updatePhotoQuality(config.photoQuality) updatePhotoQuality(config.photoQuality)
settings_photo_quality_holder.setOnClickListener { binding.settingsPhotoQualityHolder.setOnClickListener {
val items = arrayListOf( val items = arrayListOf(
RadioItem(100, "100%"), RadioItem(100, "100%"),
RadioItem(95, "95%"), RadioItem(95, "95%"),
@@ -237,12 +244,12 @@ class SettingsActivity : SimpleActivity() {
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
private fun updatePhotoQuality(quality: Int) { private fun updatePhotoQuality(quality: Int) {
settings_photo_quality.text = "$quality%" binding.settingsPhotoQuality.text = "$quality%"
} }
private fun setupCaptureMode() { private fun setupCaptureMode() {
updateCaptureMode(config.captureMode) updateCaptureMode(config.captureMode)
settings_capture_mode_holder.setOnClickListener { binding.settingsCaptureModeHolder.setOnClickListener {
val items = CaptureMode.values().mapIndexed { index, captureMode -> val items = CaptureMode.values().mapIndexed { index, captureMode ->
RadioItem(index, getString(captureMode.stringResId), captureMode) RadioItem(index, getString(captureMode.stringResId), captureMode)
} }
@@ -255,7 +262,6 @@ class SettingsActivity : SimpleActivity() {
} }
private fun updateCaptureMode(captureMode: CaptureMode) { private fun updateCaptureMode(captureMode: CaptureMode) {
settings_capture_mode.text = getString(captureMode.stringResId) binding.settingsCaptureMode.text = getString(captureMode.stringResId)
} }
} }

View File

@@ -30,11 +30,17 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
<include layout="@layout/layout_top" /> <include
android:id="@+id/layout_top"
layout="@layout/layout_top" />
<include layout="@layout/layout_flash" /> <include
android:id="@+id/layout_flash"
layout="@layout/layout_flash" />
<include layout="@layout/layout_timer" /> <include
android:id="@+id/layout_timer"
layout="@layout/layout_timer" />
</FrameLayout> </FrameLayout>
@@ -80,13 +86,11 @@
app:tabTextColor="@color/md_grey_white"> app:tabTextColor="@color/md_grey_white">
<com.google.android.material.tabs.TabItem <com.google.android.material.tabs.TabItem
android:id="@+id/camera_mode_tab_video"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/video" /> android:text="@string/video" />
<com.google.android.material.tabs.TabItem <com.google.android.material.tabs.TabItem
android:id="@+id/camera_mode_tab_photo"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/photo" /> android:text="@string/photo" />