ImageViewer: delete button & ui behavior improvements

This commit is contained in:
Hardcore Sushi 2020-09-04 13:30:12 +02:00
parent c82d6c0e36
commit bad270851f
5 changed files with 120 additions and 45 deletions

View File

@ -42,7 +42,7 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "androidx.core:core-ktx:1.3.1" implementation "androidx.core:core-ktx:1.3.1"
implementation "androidx.appcompat:appcompat:1.2.0" implementation "androidx.appcompat:appcompat:1.2.0"
implementation "androidx.constraintlayout:constraintlayout:2.0.0" implementation "androidx.constraintlayout:constraintlayout:2.0.1"
implementation "androidx.sqlite:sqlite:2.1.0" implementation "androidx.sqlite:sqlite:2.1.0"
implementation "androidx.preference:preference:1.1.1" implementation "androidx.preference:preference:1.1.1"

View File

@ -15,9 +15,10 @@ import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
import kotlinx.android.synthetic.main.activity_image_viewer.* import kotlinx.android.synthetic.main.activity_image_viewer.*
import sushi.hardcore.droidfs.ConstValues import sushi.hardcore.droidfs.ConstValues
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.util.MiscUtils
import sushi.hardcore.droidfs.explorers.ExplorerElement import sushi.hardcore.droidfs.explorers.ExplorerElement
import sushi.hardcore.droidfs.util.MiscUtils
import sushi.hardcore.droidfs.util.PathUtils import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
import sushi.hardcore.droidfs.widgets.ZoomableImageView import sushi.hardcore.droidfs.widgets.ZoomableImageView
import java.io.File import java.io.File
import java.security.MessageDigest import java.security.MessageDigest
@ -28,6 +29,7 @@ class ImageViewer: FileViewerActivity() {
private const val hideDelay: Long = 3000 private const val hideDelay: Long = 3000
private const val MIN_SWIPE_DISTANCE = 150 private const val MIN_SWIPE_DISTANCE = 150
} }
private lateinit var fileName: String
private lateinit var glideImage: RequestBuilder<Drawable> private lateinit var glideImage: RequestBuilder<Drawable>
private var x1 = 0F private var x1 = 0F
private var x2 = 0F private var x2 = 0F
@ -43,44 +45,56 @@ class ImageViewer: FileViewerActivity() {
action_bar.visibility = View.GONE action_bar.visibility = View.GONE
} }
override fun viewFile() { override fun viewFile() {
val imageBuff = loadWholeFile(filePath) setContentView(R.layout.activity_image_viewer)
if (imageBuff != null){ image_viewer.setOnInteractionListener(object : ZoomableImageView.OnInteractionListener {
setContentView(R.layout.activity_image_viewer) override fun onSingleTap(event: MotionEvent?) {
image_viewer.setOnInteractionListener(object : ZoomableImageView.OnInteractionListener{ handler.removeCallbacks(hideUI)
override fun onSingleTap(event: MotionEvent?) { if (action_buttons.visibility == View.GONE) {
handler.removeCallbacks(hideUI) action_buttons.visibility = View.VISIBLE
if (action_buttons.visibility == View.GONE){ action_bar.visibility = View.VISIBLE
action_buttons.visibility = View.VISIBLE handler.postDelayed(hideUI, hideDelay)
action_bar.visibility = View.VISIBLE } else {
handler.postDelayed(hideUI, hideDelay) hideUI.run()
} else {
hideUI.run()
}
} }
override fun onTouch(event: MotionEvent?) { }
if (!image_viewer.isZoomed){
when(event?.action){ override fun onTouch(event: MotionEvent?) {
MotionEvent.ACTION_DOWN -> { if (!image_viewer.isZoomed) {
x1 = event.x when (event?.action) {
} MotionEvent.ACTION_DOWN -> {
MotionEvent.ACTION_UP -> { x1 = event.x
x2 = event.x }
val deltaX = x2 - x1 MotionEvent.ACTION_UP -> {
if (abs(deltaX) > MIN_SWIPE_DISTANCE){ x2 = event.x
swipeImage(deltaX) val deltaX = x2 - x1
} if (abs(deltaX) > MIN_SWIPE_DISTANCE) {
swipeImage(deltaX)
} }
} }
} }
} }
}) }
glideImage = Glide.with(this).load(imageBuff) })
loadImage()
handler.postDelayed(hideUI, hideDelay)
}
private fun loadImage(){
loadWholeFile(filePath)?.let {
glideImage = Glide.with(this).load(it)
glideImage.into(image_viewer) glideImage.into(image_viewer)
text_filename.text = File(filePath).name fileName = File(filePath).name
handler.postDelayed(hideUI, hideDelay) text_filename.text = fileName
rotationAngle = 0F
} }
} }
override fun onUserInteraction() {
super.onUserInteraction()
handler.removeCallbacks(hideUI)
handler.postDelayed(hideUI, hideDelay)
}
private fun swipeImage(deltaX: Float){ private fun swipeImage(deltaX: Float){
if (!wasMapped){ if (!wasMapped){
for (e in gocryptfsVolume.recursiveMapFiles(PathUtils.getParentPath(filePath))){ for (e in gocryptfsVolume.recursiveMapFiles(PathUtils.getParentPath(filePath))){
@ -103,26 +117,61 @@ class ImageViewer: FileViewerActivity() {
} else { } else {
MiscUtils.decrementIndex(currentMappedImageIndex, mappedImages) MiscUtils.decrementIndex(currentMappedImageIndex, mappedImages)
} }
loadWholeFile(mappedImages[currentMappedImageIndex].fullPath)?.let { filePath = mappedImages[currentMappedImageIndex].fullPath
glideImage = Glide.with(applicationContext).load(it) loadImage()
glideImage.into(image_viewer) }
text_filename.text = File(mappedImages[currentMappedImageIndex].fullPath).name
rotationAngle = 0F fun onClickDelete(view: View) {
} ColoredAlertDialogBuilder(this)
.keepFullScreen()
.setTitle(R.string.warning)
.setPositiveButton(R.string.ok) { _, _ ->
if (gocryptfsVolume.removeFile(filePath)){
currentMappedImageIndex = MiscUtils.decrementIndex(currentMappedImageIndex, mappedImages)
mappedImages.clear()
wasMapped = false
swipeImage(-1F)
} else {
ColoredAlertDialogBuilder(this)
.keepFullScreen()
.setTitle(R.string.error)
.setMessage(getString(R.string.remove_failed, fileName))
.setPositiveButton(R.string.ok, null)
.show()
}
}
.setNegativeButton(R.string.cancel, null)
.setMessage(getString(R.string.single_delete_confirm, fileName))
.show()
} }
fun onClickSlideshow(view: View) { fun onClickSlideshow(view: View) {
if (!slideshowActive){ if (!slideshowActive){
slideshowActive = true slideshowActive = true
Thread { Thread {
Thread.sleep(ConstValues.slideshow_delay)
while (slideshowActive){ while (slideshowActive){
runOnUiThread { swipeImage(-1F) } runOnUiThread { swipeImage(-1F) }
Thread.sleep(ConstValues.slideshow_delay) Thread.sleep(ConstValues.slideshow_delay)
} }
}.start() }.start()
hideUI.run()
Toast.makeText(this, R.string.slideshow_started, Toast.LENGTH_SHORT).show()
} else { } else {
slideshowActive = false stopSlideshow()
Toast.makeText(this, R.string.slideshow_stopped, Toast.LENGTH_SHORT).show() }
}
private fun stopSlideshow(){
slideshowActive = false
Toast.makeText(this, R.string.slideshow_stopped, Toast.LENGTH_SHORT).show()
}
override fun onBackPressed() {
if (slideshowActive){
stopSlideshow()
} else {
super.onBackPressed()
} }
} }

View File

@ -2,10 +2,19 @@ package sushi.hardcore.droidfs.widgets
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import android.content.Context import android.content.Context
import android.view.WindowManager
class ColoredAlertDialogBuilder: AlertDialog.Builder { class ColoredAlertDialogBuilder: AlertDialog.Builder {
constructor(context: Context): super(context) constructor(context: Context): super(context)
constructor(context: Context, themeResId: Int): super(context, themeResId) constructor(context: Context, themeResId: Int): super(context, themeResId)
private var keepFullScreen = false
fun keepFullScreen(): AlertDialog.Builder {
keepFullScreen = true
return this
}
private fun applyColor(dialog: AlertDialog){ private fun applyColor(dialog: AlertDialog){
dialog.setOnShowListener{ dialog.setOnShowListener{
val themeColor = ThemeColor.getThemeColor(context) val themeColor = ThemeColor.getThemeColor(context)
@ -14,16 +23,19 @@ class ColoredAlertDialogBuilder: AlertDialog.Builder {
} }
} }
} }
override fun show(): AlertDialog? {
val dialog = super.create() override fun show(): AlertDialog {
applyColor(dialog) val dialog = create()
dialog.show() dialog.show()
return null return dialog
} }
override fun create(): AlertDialog { override fun create(): AlertDialog {
val dialog = super.create() val dialog = super.create()
applyColor(dialog) applyColor(dialog)
if (keepFullScreen){
dialog.window?.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
}
return dialog return dialog
} }
} }

View File

@ -27,8 +27,21 @@
android:singleLine="true" android:singleLine="true"
android:ellipsize="end" android:ellipsize="end"
android:textSize="20sp" android:textSize="20sp"
android:layout_marginEnd="40dp"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_toStartOf="@id/image_delete"
android:layout_centerVertical="true"/>
<ImageButton
android:id="@+id/image_delete"
android:layout_width="30dp"
android:layout_height="30dp"
android:background="#00000000"
android:scaleType="fitCenter"
android:src="@drawable/icon_delete"
android:onClick="onClickDelete"
android:layout_marginStart="10dp"
android:layout_marginEnd="20dp"
android:layout_toStartOf="@id/image_button_slideshow"
android:layout_centerVertical="true"/> android:layout_centerVertical="true"/>
<ImageButton <ImageButton

View File

@ -136,7 +136,7 @@
<string name="query_cursor_null_error_msg">Unable to access this file</string> <string name="query_cursor_null_error_msg">Unable to access this file</string>
<string name="about">About</string> <string name="about">About</string>
<string name="github">GitHub</string> <string name="github">GitHub</string>
<string name="github_summary">Want to read the documentation, request feature, report bug, read the source code… Check the DroidFS\'s repository !</string> <string name="github_summary">Want to read the documentation, review the source code, request feature, report bug… Check the DroidFS\'s repository !</string>
<string name="share">Share</string> <string name="share">Share</string>
<string name="decrypt_files">Export/Decrypt</string> <string name="decrypt_files">Export/Decrypt</string>
<string name="loading_msg_copy">Copying selected items…</string> <string name="loading_msg_copy">Copying selected items…</string>
@ -172,4 +172,5 @@
<string name="change_pwd_cant_write_error_msg">DroidFS doesn\'t have write access to this path. You can try to move the volume to a writable location.</string> <string name="change_pwd_cant_write_error_msg">DroidFS doesn\'t have write access to this path. You can try to move the volume to a writable location.</string>
<string name="change_pwd_on_sdcard_error_msg">DroidFS can\'t write on removable SD cards, please move the volume to internal storage.</string> <string name="change_pwd_on_sdcard_error_msg">DroidFS can\'t write on removable SD cards, please move the volume to internal storage.</string>
<string name="slideshow_stopped">Slideshow stopped</string> <string name="slideshow_stopped">Slideshow stopped</string>
<string name="slideshow_started">Slideshow started</string>
</resources> </resources>