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 "androidx.core:core-ktx:1.3.1"
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.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 sushi.hardcore.droidfs.ConstValues
import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.util.MiscUtils
import sushi.hardcore.droidfs.explorers.ExplorerElement
import sushi.hardcore.droidfs.util.MiscUtils
import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
import sushi.hardcore.droidfs.widgets.ZoomableImageView
import java.io.File
import java.security.MessageDigest
@ -28,6 +29,7 @@ class ImageViewer: FileViewerActivity() {
private const val hideDelay: Long = 3000
private const val MIN_SWIPE_DISTANCE = 150
}
private lateinit var fileName: String
private lateinit var glideImage: RequestBuilder<Drawable>
private var x1 = 0F
private var x2 = 0F
@ -43,44 +45,56 @@ class ImageViewer: FileViewerActivity() {
action_bar.visibility = View.GONE
}
override fun viewFile() {
val imageBuff = loadWholeFile(filePath)
if (imageBuff != null){
setContentView(R.layout.activity_image_viewer)
image_viewer.setOnInteractionListener(object : ZoomableImageView.OnInteractionListener{
override fun onSingleTap(event: MotionEvent?) {
handler.removeCallbacks(hideUI)
if (action_buttons.visibility == View.GONE){
action_buttons.visibility = View.VISIBLE
action_bar.visibility = View.VISIBLE
handler.postDelayed(hideUI, hideDelay)
} else {
hideUI.run()
}
setContentView(R.layout.activity_image_viewer)
image_viewer.setOnInteractionListener(object : ZoomableImageView.OnInteractionListener {
override fun onSingleTap(event: MotionEvent?) {
handler.removeCallbacks(hideUI)
if (action_buttons.visibility == View.GONE) {
action_buttons.visibility = View.VISIBLE
action_bar.visibility = View.VISIBLE
handler.postDelayed(hideUI, hideDelay)
} else {
hideUI.run()
}
override fun onTouch(event: MotionEvent?) {
if (!image_viewer.isZoomed){
when(event?.action){
MotionEvent.ACTION_DOWN -> {
x1 = event.x
}
MotionEvent.ACTION_UP -> {
x2 = event.x
val deltaX = x2 - x1
if (abs(deltaX) > MIN_SWIPE_DISTANCE){
swipeImage(deltaX)
}
}
override fun onTouch(event: MotionEvent?) {
if (!image_viewer.isZoomed) {
when (event?.action) {
MotionEvent.ACTION_DOWN -> {
x1 = event.x
}
MotionEvent.ACTION_UP -> {
x2 = event.x
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)
text_filename.text = File(filePath).name
handler.postDelayed(hideUI, hideDelay)
fileName = File(filePath).name
text_filename.text = fileName
rotationAngle = 0F
}
}
override fun onUserInteraction() {
super.onUserInteraction()
handler.removeCallbacks(hideUI)
handler.postDelayed(hideUI, hideDelay)
}
private fun swipeImage(deltaX: Float){
if (!wasMapped){
for (e in gocryptfsVolume.recursiveMapFiles(PathUtils.getParentPath(filePath))){
@ -103,26 +117,61 @@ class ImageViewer: FileViewerActivity() {
} else {
MiscUtils.decrementIndex(currentMappedImageIndex, mappedImages)
}
loadWholeFile(mappedImages[currentMappedImageIndex].fullPath)?.let {
glideImage = Glide.with(applicationContext).load(it)
glideImage.into(image_viewer)
text_filename.text = File(mappedImages[currentMappedImageIndex].fullPath).name
rotationAngle = 0F
}
filePath = mappedImages[currentMappedImageIndex].fullPath
loadImage()
}
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) {
if (!slideshowActive){
slideshowActive = true
Thread {
Thread.sleep(ConstValues.slideshow_delay)
while (slideshowActive){
runOnUiThread { swipeImage(-1F) }
Thread.sleep(ConstValues.slideshow_delay)
}
}.start()
hideUI.run()
Toast.makeText(this, R.string.slideshow_started, Toast.LENGTH_SHORT).show()
} else {
slideshowActive = false
Toast.makeText(this, R.string.slideshow_stopped, Toast.LENGTH_SHORT).show()
stopSlideshow()
}
}
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 android.content.Context
import android.view.WindowManager
class ColoredAlertDialogBuilder: AlertDialog.Builder {
constructor(context: Context): super(context)
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){
dialog.setOnShowListener{
val themeColor = ThemeColor.getThemeColor(context)
@ -14,16 +23,19 @@ class ColoredAlertDialogBuilder: AlertDialog.Builder {
}
}
}
override fun show(): AlertDialog? {
val dialog = super.create()
applyColor(dialog)
override fun show(): AlertDialog {
val dialog = create()
dialog.show()
return null
return dialog
}
override fun create(): AlertDialog {
val dialog = super.create()
applyColor(dialog)
if (keepFullScreen){
dialog.window?.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
}
return dialog
}
}

View File

@ -27,8 +27,21 @@
android:singleLine="true"
android:ellipsize="end"
android:textSize="20sp"
android:layout_marginEnd="40dp"
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"/>
<ImageButton

View File

@ -136,7 +136,7 @@
<string name="query_cursor_null_error_msg">Unable to access this file</string>
<string name="about">About</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="decrypt_files">Export/Decrypt</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_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_started">Slideshow started</string>
</resources>