From 0a93b48b8385f80fe90c65bf192bdfb9d3b24f5c Mon Sep 17 00:00:00 2001 From: ekibun Date: Fri, 12 Aug 2022 00:15:45 +0800 Subject: [PATCH] 1. update ui --- .idea/deploymentTargetDropDown.xml | 17 + .../inspectionProfiles/profiles_settings.xml | 7 + .idea/misc.xml | 14 +- app/build.gradle | 1 + app/src/main/java/soko/ekibun/stitch/App.kt | 11 +- .../java/soko/ekibun/stitch/BitmapCache.kt | 4 +- .../java/soko/ekibun/stitch/CaptureService.kt | 9 +- .../java/soko/ekibun/stitch/EditActivity.kt | 376 ++++++++++++------ .../main/java/soko/ekibun/stitch/EditView.kt | 16 +- .../java/soko/ekibun/stitch/MainActivity.kt | 8 +- .../soko/ekibun/stitch/ProjectListAdapter.kt | 16 +- .../java/soko/ekibun/stitch/RangeSeekbar.kt | 12 + .../main/java/soko/ekibun/stitch/Stitch.kt | 109 +++-- app/src/main/res/drawable/bg_rect.xml | 2 +- app/src/main/res/drawable/ic_arrow_back.xml | 11 + .../main/res/drawable/ic_arrow_forward.xml | 11 + app/src/main/res/drawable/ic_check_all.xml | 10 + app/src/main/res/drawable/ic_check_clear.xml | 13 + app/src/main/res/drawable/ic_chevron_left.xml | 10 + .../main/res/drawable/ic_chevron_right.xml | 10 + app/src/main/res/drawable/ic_drop_down.xml | 10 + app/src/main/res/drawable/ic_edit.xml | 10 + app/src/main/res/drawable/ic_image_add.xml | 10 + app/src/main/res/drawable/ic_save.xml | 10 + app/src/main/res/drawable/ic_share.xml | 10 + app/src/main/res/drawable/ic_shuffle.xml | 10 + app/src/main/res/drawable/ic_undo.xml | 10 + app/src/main/res/layout/activity_edit.xml | 339 ++++++++-------- app/src/main/res/layout/list_header.xml | 8 +- app/src/main/res/layout/list_project.xml | 4 +- app/src/main/res/menu/menu_stitch.xml | 15 - app/src/main/res/values/colors.xml | 1 - app/src/main/res/values/strings.xml | 33 +- app/src/main/res/values/themes.xml | 1 + build.gradle | 5 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 36 files changed, 703 insertions(+), 442 deletions(-) create mode 100644 .idea/deploymentTargetDropDown.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 app/src/main/res/drawable/ic_arrow_back.xml create mode 100644 app/src/main/res/drawable/ic_arrow_forward.xml create mode 100644 app/src/main/res/drawable/ic_check_all.xml create mode 100644 app/src/main/res/drawable/ic_check_clear.xml create mode 100644 app/src/main/res/drawable/ic_chevron_left.xml create mode 100644 app/src/main/res/drawable/ic_chevron_right.xml create mode 100644 app/src/main/res/drawable/ic_drop_down.xml create mode 100644 app/src/main/res/drawable/ic_edit.xml create mode 100644 app/src/main/res/drawable/ic_image_add.xml create mode 100644 app/src/main/res/drawable/ic_save.xml create mode 100644 app/src/main/res/drawable/ic_share.xml create mode 100644 app/src/main/res/drawable/ic_shuffle.xml create mode 100644 app/src/main/res/drawable/ic_undo.xml delete mode 100644 app/src/main/res/menu/menu_stitch.xml diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..6965d65 --- /dev/null +++ b/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..dd4c951 --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index e650ae9..bd14764 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -5,13 +5,25 @@ + + + + + + + + + - + + + + diff --git a/app/build.gradle b/app/build.gradle index 261edf8..c737f6c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -30,6 +30,7 @@ android { defaultConfig { applicationId "soko.ekibun.stitch" minSdkVersion 21 + //noinspection OldTargetApi targetSdkVersion 31 versionCode gitVersionCode() versionName gitVersionTag() diff --git a/app/src/main/java/soko/ekibun/stitch/App.kt b/app/src/main/java/soko/ekibun/stitch/App.kt index 1ae7947..9242c4e 100644 --- a/app/src/main/java/soko/ekibun/stitch/App.kt +++ b/app/src/main/java/soko/ekibun/stitch/App.kt @@ -1,14 +1,14 @@ package soko.ekibun.stitch import android.app.Application -import android.preference.PreferenceManager +import android.content.Context import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.runBlocking import java.io.File import java.util.concurrent.Executors class App : Application() { - val sp by lazy { PreferenceManager.getDefaultSharedPreferences(this) } + val sp by lazy { getSharedPreferences(packageName + "_preferences", Context.MODE_PRIVATE)!! } private val bitmapCache by lazy { BitmapCache(this) } private val projects by lazy { HashMap() } @@ -18,7 +18,7 @@ class App : Application() { } val dataDirPath: String by lazy { - dataDir.path + File.separator + "Project" + applicationInfo.dataDir + File.separator + "Project" } companion object { @@ -43,10 +43,7 @@ class App : Application() { return File(app.dataDirPath + File.separator + projectKey + File.separator + ".project") } - fun newProject(): String { - val projectKey = System.currentTimeMillis().toString(16) - return projectKey - } + fun newProject(): String = System.currentTimeMillis().toString(16) fun clearProjects() { val file = File(app.dataDirPath) diff --git a/app/src/main/java/soko/ekibun/stitch/BitmapCache.kt b/app/src/main/java/soko/ekibun/stitch/BitmapCache.kt index 8205594..063e237 100644 --- a/app/src/main/java/soko/ekibun/stitch/BitmapCache.kt +++ b/app/src/main/java/soko/ekibun/stitch/BitmapCache.kt @@ -6,7 +6,7 @@ import android.graphics.BitmapFactory import android.util.LruCache import androidx.core.content.FileProvider import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch import java.io.File import java.io.FileOutputStream @@ -65,7 +65,7 @@ class BitmapCache(var app: App) { return saveBitmap(project, bmp, saveToMemory) } lastKey = key - GlobalScope.launch(Dispatchers.IO) { + MainScope().launch(Dispatchers.IO) { try { if (saveToMemory) addBitmapToMemoryCache(key, bmp) val file = File(app.dataDirPath, key) diff --git a/app/src/main/java/soko/ekibun/stitch/CaptureService.kt b/app/src/main/java/soko/ekibun/stitch/CaptureService.kt index 53ec0cc..97271df 100644 --- a/app/src/main/java/soko/ekibun/stitch/CaptureService.kt +++ b/app/src/main/java/soko/ekibun/stitch/CaptureService.kt @@ -3,6 +3,7 @@ package soko.ekibun.stitch import android.app.Service import android.content.Context import android.content.Intent +import android.os.Build import android.os.IBinder import android.widget.Toast @@ -36,7 +37,9 @@ class CaptureService : Service() { } override fun onCreate() { - startService(Intent(this, QuickTileService::class.java)) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + startService(Intent(this, QuickTileService::class.java)) + } floatButton.run { } notification.run { } } @@ -58,7 +61,9 @@ class CaptureService : Service() { stopForeground(true) screenCapture?.destroy() floatButton.destroy() - startService(Intent(this, QuickTileService::class.java)) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + startService(Intent(this, QuickTileService::class.java)) + } } override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { diff --git a/app/src/main/java/soko/ekibun/stitch/EditActivity.kt b/app/src/main/java/soko/ekibun/stitch/EditActivity.kt index 25feecd..0e751ef 100644 --- a/app/src/main/java/soko/ekibun/stitch/EditActivity.kt +++ b/app/src/main/java/soko/ekibun/stitch/EditActivity.kt @@ -17,12 +17,14 @@ import android.os.Build import android.os.Bundle import android.util.Log import android.view.View -import android.widget.PopupMenu -import android.widget.TextView -import android.widget.Toast +import android.view.inputmethod.InputMethodManager +import android.widget.* +import androidx.core.widget.doAfterTextChanged import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch +import kotlin.math.pow +import kotlin.math.roundToInt class EditActivity : Activity() { companion object { @@ -42,13 +44,30 @@ class EditActivity : Activity() { private val editView by lazy { findViewById(R.id.edit) } private val selectInfo by lazy { findViewById(R.id.select_info) } - private val seekDx by lazy { findViewById(R.id.seek_x) } - private val seekDy by lazy { findViewById(R.id.seek_y) } - private val seekTrim by lazy { findViewById(R.id.seek_trim) } - private val seekXRange by lazy { findViewById(R.id.seek_xrange) } - private val seekYRange by lazy { findViewById(R.id.seek_yrange) } - private val seekRotate by lazy { findViewById(R.id.seek_rotate) } - private val seekScale by lazy { findViewById(R.id.seek_scale) } + private val seekbar by lazy { findViewById(R.id.menu_seekbar) } + private val numberView by lazy { findViewById(R.id.menu_number_picker) } + private val numberDec by lazy { findViewById(R.id.menu_decrement) } + private val numberInc by lazy { findViewById(R.id.menu_increment) } + private val numberA by lazy { findViewById(R.id.menu_edit_a) } + private val numberB by lazy { findViewById(R.id.menu_edit_b) } + private val numberDiv by lazy { findViewById(R.id.menu_edit_divider) } + private val dropdown by lazy { findViewById(R.id.menu_dropdown) } + + data class SelectItemInfo( + val roundOf: Int, + val showB: Boolean + ) + + private val selectItems = mapOf( + R.string.label_dx to (0 to false), + R.string.label_dy to (0 to false), + R.string.label_trim to (2 to true), + R.string.label_xrange to (0 to true), + R.string.label_yrange to (0 to true), + R.string.label_scale to (2 to false), + R.string.label_rotate to (0 to false) + ) + private var selectIndex = R.string.label_dy private val projectKey by lazy { intent.extras!!.getString("project")!! } val project by lazy { App.getProject(projectKey) } @@ -59,30 +78,162 @@ class EditActivity : Activity() { editView.postInvalidate() } + private fun updateNumberView(a: Float? = null, b: Float? = null) { + val (roundOf, showB) = selectItems[selectIndex] ?: (0 to false) + numberB.visibility = if (showB) View.VISIBLE else View.GONE + numberDiv.visibility = if (showB) View.VISIBLE else View.GONE + numberDec.visibility = if (showB) View.GONE else View.VISIBLE + numberInc.visibility = if (showB) View.GONE else View.VISIBLE + if (roundOf == 0) { + if (a != null) numberA.setText(a.roundToInt().toString()) + if (b != null) numberB.setText(b.roundToInt().toString()) + } + if (a != null) numberA.setText(String.format("%.${roundOf}f", a)) + if (b != null) numberB.setText(String.format("%.${roundOf}f", b)) + if (numberA.isFocused) { + numberA.clearFocus() + (getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow( + numberA.windowToken, + InputMethodManager.HIDE_NOT_ALWAYS + ) + } + if (numberB.isFocused) { + numberB.clearFocus() + (getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow( + numberB.windowToken, + InputMethodManager.HIDE_NOT_ALWAYS + ) + } + } + + fun setNumber(a: Float? = null, b: Float? = null, relative: Boolean = false) { + val selected = selectedStitchInfo + if (selected.isNotEmpty()) selected.forEach { + when (selectIndex) { + R.string.label_dx -> if (a != null) it.dx = if (relative) (a * 2 - 1) * it.width else a + R.string.label_dy -> if (a != null) it.dy = if (relative) (a * 2 - 1) * it.height else a + R.string.label_trim -> { + if (a != null) it.a = a + if (b != null) it.b = b + } + R.string.label_xrange -> { + if (a != null) it.xa = if (!relative && it.width > 0) a / it.width else a + if (b != null) it.xb = if (!relative && it.width > 0) b / it.width else b + } + R.string.label_yrange -> { + if (a != null) it.ya = if (!relative && it.height > 0) a / it.height else a + if (b != null) it.yb = if (!relative && it.height > 0) b / it.height else b + } + R.string.label_scale -> if (a != null) it.dscale = if (relative) (a * 2) else a + R.string.label_rotate -> if (a != null) it.drot = if (relative) (a * 2 - 1) * 180 else a + } + } + } + + private val selectedStitchInfo + get() = when (selectIndex) { + R.string.label_dx, + R.string.label_dy, + R.string.label_trim -> project.stitchInfo.filterIndexed { i, v -> + i > 0 && project.selected.contains(v.imageKey) + } + else -> project.stitchInfo.filter { project.selected.contains(it.imageKey) } + } + + private fun updateNumber() { + val selected = selectedStitchInfo + if (selected.isNotEmpty()) { + numberView.visibility = View.VISIBLE + when (selectIndex) { + R.string.label_dx -> { + updateNumberView(selected.map { it.dx }.average().toFloat()) + } + R.string.label_dy -> { + updateNumberView(selected.map { it.dy }.average().toFloat()) + } + R.string.label_trim -> { + updateNumberView( + selected.map { it.a }.average().toFloat(), + selected.map { it.b }.average().toFloat() + ) + } + R.string.label_xrange -> { + updateNumberView( + selected.map { it.xa * it.width }.average().toFloat(), + selected.map { it.xb * it.width }.average().toFloat() + ) + } + R.string.label_yrange -> { + updateNumberView( + selected.map { it.ya * it.height }.average().toFloat(), + selected.map { it.yb * it.height }.average().toFloat() + ) + } + R.string.label_scale -> { + updateNumberView(selected.map { it.dscale }.average().toFloat()) + } + R.string.label_rotate -> { + updateNumberView(selected.map { it.drot }.average().toFloat()) + } + } + } else { + numberView.visibility = View.GONE + } + } + + fun updateSeekbar() { + val selected = selectedStitchInfo + if (selected.isNotEmpty()) { + seekbar.isEnabled = true + when (selectIndex) { + R.string.label_dx -> { + seekbar.type = RangeSeekbar.TYPE_CENTER + seekbar.a = selected.map { (it.dx / it.width + 1) / 2 }.average().toFloat() + } + R.string.label_dy -> { + seekbar.type = RangeSeekbar.TYPE_CENTER + seekbar.a = selected.map { (it.dy / it.height + 1) / 2 }.average().toFloat() + + numberB.visibility = View.VISIBLE + numberDiv.visibility = View.GONE + } + R.string.label_trim -> { + seekbar.type = RangeSeekbar.TYPE_GRADIENT + seekbar.a = selected.map { it.a }.average().toFloat() + seekbar.b = selected.map { it.b }.average().toFloat() + } + R.string.label_xrange -> { + seekbar.type = RangeSeekbar.TYPE_RANGE + seekbar.a = selected.map { it.xa }.average().toFloat() + seekbar.b = selected.map { it.xb }.average().toFloat() + } + R.string.label_yrange -> { + seekbar.type = RangeSeekbar.TYPE_RANGE + seekbar.a = selected.map { it.ya }.average().toFloat() + seekbar.b = selected.map { it.yb }.average().toFloat() + } + R.string.label_scale -> { + seekbar.type = RangeSeekbar.TYPE_CENTER + seekbar.a = selected.map { it.dscale / 2f }.average().toFloat() + } + R.string.label_rotate -> { + seekbar.type = RangeSeekbar.TYPE_CENTER + seekbar.a = selected.map { (it.drot / 360) + 0.5f }.average().toFloat() + } + } + seekbar.invalidate() + } else { + seekbar.isEnabled = false + } + } + fun updateSelectInfo() { + dropdown.setText(selectIndex) invalidateView() selectInfo.text = getString(R.string.label_select, project.selected.size, project.stitchInfo.size) - val selected = project.stitchInfo.filter { project.selected.contains(it.imageKey) } - if (selected.isNotEmpty()) { - seekDx.a = selected.map { (it.dx / it.width + 1) / 2 }.average().toFloat() - seekDy.a = selected.map { (it.dy / it.height + 1) / 2 }.average().toFloat() - seekTrim.a = selected.map { it.a }.average().toFloat() - seekTrim.b = selected.map { it.b }.average().toFloat() - seekXRange.a = selected.map { it.xa }.average().toFloat() - seekXRange.b = selected.map { it.xb }.average().toFloat() - seekYRange.a = selected.map { it.ya }.average().toFloat() - seekYRange.b = selected.map { it.yb }.average().toFloat() - seekRotate.a = selected.map { (it.drot / 360) + 0.5f }.average().toFloat() - seekScale.a = selected.map { it.dscale / 2f }.average().toFloat() - seekDx.invalidate() - seekDy.invalidate() - seekTrim.invalidate() - seekXRange.invalidate() - seekYRange.invalidate() - seekRotate.invalidate() - seekScale.invalidate() - } + updateSeekbar() + updateNumber() } private fun selectAll() { @@ -131,7 +282,7 @@ class EditActivity : Activity() { startActivityForResult(Intent.createChooser(intent, "Stitch"), requesetCode) } - private fun stitch(method: Stitch.CombineMethod) { + private fun stitch(homo: Boolean, diff: Boolean) { if (project.selected.isEmpty()) { Toast.makeText(this, R.string.please_select_image, Toast.LENGTH_SHORT).show() return @@ -140,11 +291,11 @@ class EditActivity : Activity() { var done = 0 progress.setMessage(getString(R.string.alert_computing, done, project.selected.size)) progress.show() - GlobalScope.launch(Dispatchers.IO) { + MainScope().launch(Dispatchers.IO) { project.updateUndo() project.stitchInfo.reduceOrNull { acc, it -> if (progress.isShowing && project.selected.contains(it.imageKey)) { - Stitch.combine(method, acc, it)?.let { data -> + Stitch.combine(homo, diff, acc, it)?.let { data -> if (progress.isShowing) { it.dx = data.dx it.dy = data.dy @@ -178,7 +329,7 @@ class EditActivity : Activity() { setContentView(R.layout.activity_edit) - if (intent.getBooleanExtra("gallery", false) == true) { + if (intent.getBooleanExtra("gallery", false)) { intent.putExtra("gallery", false) importFromGallery(REQUEST_IMPORT_NEW) editView.visibility = View.INVISIBLE @@ -191,24 +342,12 @@ class EditActivity : Activity() { windowInsets.systemWindowInsetRight, 0 ) - findViewById(R.id.panel0).setPadding( - windowInsets.systemWindowInsetLeft, - 0, - windowInsets.systemWindowInsetRight, - 0 - ) - findViewById(R.id.panel1).setPadding( + findViewById(R.id.panel).setPadding( windowInsets.systemWindowInsetLeft, 0, windowInsets.systemWindowInsetRight, 0 ) - findViewById(R.id.panel2).setPadding( - windowInsets.systemWindowInsetLeft, - 0, - windowInsets.systemWindowInsetRight, - windowInsets.systemWindowInsetBottom - ) windowInsets.consumeSystemWindowInsets() } @@ -217,14 +356,35 @@ class EditActivity : Activity() { project.selected.clear() updateSelectInfo() } - findViewById(R.id.menu_import).setOnClickListener { - importFromGallery() + + dropdown.setOnClickListener { view -> + val popupMenu = PopupMenu(this, view) + selectItems.forEach { + popupMenu.menu.add(0, it.key, 0, it.key) + popupMenu.show() + popupMenu.setOnMenuItemClickListener { item -> + selectIndex = item.itemId + updateSelectInfo() + true + } + } } - findViewById(R.id.menu_capture).setOnClickListener { - this.startActivityForResult( - StartCaptureActivity.startActivityIntent(this, projectKey), - REQUEST_CAPTURE - ) + + findViewById(R.id.menu_import).setOnClickListener { + val popupMenu = PopupMenu(this, it) + popupMenu.menu.add(0, 1, 0, R.string.import_from_gallery) + popupMenu.menu.add(0, 2, 0, R.string.import_from_capture) + popupMenu.show() + popupMenu.setOnMenuItemClickListener { item -> + when (item.itemId) { + 1 -> importFromGallery() + 2 -> this.startActivityForResult( + StartCaptureActivity.startActivityIntent(this, projectKey), + REQUEST_CAPTURE + ) + } + true + } } findViewById(R.id.menu_select_all).setOnClickListener { selectAll() @@ -278,7 +438,7 @@ class EditActivity : Activity() { return@setOnClickListener } val progress = ProgressDialog.show(this, null, getString(R.string.alert_stitching)) - GlobalScope.launch(Dispatchers.IO) { + MainScope().launch(Dispatchers.IO) { val intent = try { val bitmap = editView.drawToBitmap() App.bitmapCache.saveToCache(bitmap, "Stitch$projectKey.png") @@ -311,85 +471,45 @@ class EditActivity : Activity() { saveIntent.putExtra(Intent.EXTRA_TITLE, "Stitch$projectKey.png") startActivityForResult(saveIntent, REQUEST_SAVE) } - findViewById(R.id.menu_auto_stitch).setOnLongClickListener { - val popupMenu = PopupMenu(this, it) - popupMenu.menuInflater.inflate(R.menu.menu_stitch, popupMenu.menu) - popupMenu.show() - popupMenu.setOnMenuItemClickListener { item -> - when (item.itemId) { - R.id.menu_find_homography -> stitch(Stitch.CombineMethod.FIND_HOMOGRAPHY) - R.id.menu_phase_correlate -> stitch(Stitch.CombineMethod.PHASE_CORRELATE) - R.id.menu_find_homography_diff -> stitch(Stitch.CombineMethod.FIND_HOMOGRAPHY_DIFF) - R.id.menu_phase_correlate_diff -> stitch(Stitch.CombineMethod.PHASE_CORRELATE_DIFF) - } - true - } - true - } findViewById(R.id.menu_auto_stitch).setOnClickListener { - stitch(Stitch.CombineMethod.PHASE_CORRELATE_DIFF) - } - - seekDx.type = RangeSeekbar.TYPE_CENTER - seekDx.a = 0.5f - seekDx.onRangeChange = { a, _ -> - project.stitchInfo.forEach { - if (project.selected.contains(it.imageKey)) it.dx = (a * 2 - 1) * it.width - } - invalidateView() - } - seekDy.type = RangeSeekbar.TYPE_CENTER - seekDy.a = 0.5f - seekDy.onRangeChange = { a, _ -> - project.stitchInfo.forEach { - if (project.selected.contains(it.imageKey)) it.dy = (a * 2 - 1) * it.height - } - invalidateView() + stitch( + findViewById(R.id.switch_homography).isChecked, + findViewById(R.id.switch_diff).isChecked + ) } - seekRotate.type = RangeSeekbar.TYPE_CENTER - seekRotate.a = 0.5f - seekRotate.onRangeChange = { a, _ -> - project.stitchInfo.forEach { - if (project.selected.contains(it.imageKey)) it.drot = (a * 2 - 1) * 180 - } + numberA.doAfterTextChanged { + if (!numberA.isFocused) return@doAfterTextChanged + val newNum = it?.toString()?.toFloatOrNull() ?: return@doAfterTextChanged + setNumber(newNum) + updateSeekbar() invalidateView() } - seekScale.type = RangeSeekbar.TYPE_CENTER - seekScale.a = 0.5f - seekScale.onRangeChange = { a, _ -> - project.stitchInfo.forEach { - if (project.selected.contains(it.imageKey)) it.dscale = (a * 2) - } + numberB.doAfterTextChanged { + if (!numberB.isFocused) return@doAfterTextChanged + val newNum = it?.toString()?.toFloatOrNull() ?: return@doAfterTextChanged + setNumber(null, newNum) + updateSeekbar() invalidateView() } - seekTrim.type = RangeSeekbar.TYPE_GRADIENT - seekTrim.a = 0.4f - seekTrim.b = 0.6f - seekTrim.onRangeChange = { a, b -> - project.stitchInfo.forEach { - if (project.selected.contains(it.imageKey)) { - it.a = a - it.b = b - } - } + numberInc.setOnClickListener { + val newNum = (numberA.text.toString().toFloatOrNull() ?: 0f) + + 10.0.pow(-(selectItems[selectIndex]?.first ?: 0).toDouble()).toFloat() + updateNumberView(newNum) + setNumber(newNum) + updateSeekbar() invalidateView() } - seekXRange.onRangeChange = { a, b -> - project.stitchInfo.forEach { - if (project.selected.contains(it.imageKey)) { - it.xa = a - it.xb = b - } - } + numberDec.setOnClickListener { + val newNum = (numberA.text.toString().toFloatOrNull() ?: 0f) - + 10.0.pow(-(selectItems[selectIndex]?.first ?: 0).toDouble()).toFloat() + updateNumberView(newNum) + setNumber(newNum) + updateSeekbar() invalidateView() } - seekYRange.onRangeChange = { a, b -> - project.stitchInfo.forEach { - if (project.selected.contains(it.imageKey)) { - it.ya = a - it.yb = b - } - } + seekbar.onRangeChange = { a, b -> + setNumber(a, b, true) + updateNumber() invalidateView() } selectAll() @@ -414,7 +534,7 @@ class EditActivity : Activity() { this, null, getString(R.string.alert_reading) ) - GlobalScope.launch(Dispatchers.IO) { + MainScope().launch(Dispatchers.IO) { val clipData = data?.clipData if (clipData != null) { val count: Int = @@ -427,7 +547,7 @@ class EditActivity : Activity() { } runOnUiThread { if (requestCode == REQUEST_IMPORT_NEW) { - EditActivity.startActivity(this@EditActivity, projectKey) + startActivity(this@EditActivity, projectKey) finish() } progress.cancel() @@ -440,7 +560,7 @@ class EditActivity : Activity() { this, null, getString(R.string.alert_stitching) ) - GlobalScope.launch(Dispatchers.IO) { + MainScope().launch(Dispatchers.IO) { val err = try { val fileOutputStream = contentResolver.openOutputStream(data?.data!!)!! val bitmap = editView.drawToBitmap() diff --git a/app/src/main/java/soko/ekibun/stitch/EditView.kt b/app/src/main/java/soko/ekibun/stitch/EditView.kt index 7287b0c..6889841 100644 --- a/app/src/main/java/soko/ekibun/stitch/EditView.kt +++ b/app/src/main/java/soko/ekibun/stitch/EditView.kt @@ -4,6 +4,7 @@ import android.annotation.SuppressLint import android.app.Activity import android.content.Context import android.graphics.* +import android.os.Build import android.util.AttributeSet import android.view.MotionEvent import android.view.ScaleGestureDetector @@ -31,10 +32,10 @@ class EditView(context: Context, attrs: AttributeSet?) : SurfaceView(context, at ) @Suppress("DEPRECATION") - private val colorPrimary by lazy { resources.getColor(R.color.colorPrimary) } + private val colorUnselected by lazy { resources.getColor(R.color.opaque) } @Suppress("DEPRECATION") - private val colorWarn by lazy { resources.getColor(R.color.colorWarn) } + private val colorSelected by lazy { resources.getColor(R.color.colorPrimary) } private val paint by lazy { Paint().apply { @@ -106,11 +107,12 @@ class EditView(context: Context, attrs: AttributeSet?) : SurfaceView(context, at lastDrawY = transY lastDrawScale = scale job?.cancel() - job = GlobalScope.launch(dispatcher) { + job = MainScope().launch(dispatcher) { if (!isActive) return@launch - val c = holder.lockHardwareCanvas() ?: holder.lockCanvas() ?: return@launch + val c = (if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) + holder.lockHardwareCanvas() else null) ?: holder.lockCanvas() ?: return@launch c.save() - c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); + c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR) c.translate(transX, transY) c.scale(scale, scale) val project = project ?: return@launch @@ -123,7 +125,7 @@ class EditView(context: Context, attrs: AttributeSet?) : SurfaceView(context, at project.stitchInfo.firstOrNull()?.let { val selected = project.selected.contains(it.imageKey) - paint.color = if (selected) colorWarn else colorPrimary + paint.color = if (selected) colorSelected else colorUnselected c.drawCircle( it.cx, it.cy, @@ -137,7 +139,7 @@ class EditView(context: Context, attrs: AttributeSet?) : SurfaceView(context, at } project.stitchInfo.reduceIndexedOrNull { i, acc, it -> val selected = project.selected.contains(it.imageKey) - paint.color = if (selected) colorWarn else colorPrimary + paint.color = if (selected) colorSelected else colorUnselected c.drawCircle( it.cx, it.cy, diff --git a/app/src/main/java/soko/ekibun/stitch/MainActivity.kt b/app/src/main/java/soko/ekibun/stitch/MainActivity.kt index aa56897..6093d68 100644 --- a/app/src/main/java/soko/ekibun/stitch/MainActivity.kt +++ b/app/src/main/java/soko/ekibun/stitch/MainActivity.kt @@ -31,12 +31,12 @@ class MainActivity : Activity() { private fun getVersion(context: Context): String { var versionName = "" - var versionCode = 0 + var versionCode = 0L var isApkInDebug = false try { val pi = context.packageManager.getPackageInfo(context.packageName, 0) versionName = pi.versionName - versionCode = pi.versionCode + versionCode = pi.longVersionCode val info = context.applicationInfo isApkInDebug = info.flags and ApplicationInfo.FLAG_DEBUGGABLE != 0 } catch (e: PackageManager.NameNotFoundException) { @@ -56,7 +56,7 @@ class MainActivity : Activity() { val policyVersion = getString(R.string.policy_version) if (App.sp.getString("policy_version", "") != policyVersion) { val policyView = TextView(this) - policyView.text = Html.fromHtml(getString(R.string.policy)) + policyView.text = Html.fromHtml(getString(R.string.policy, Html.FROM_HTML_MODE_LEGACY)) val padding = (resources.displayMetrics.density * 24).roundToInt() policyView.setPaddingRelative(padding, padding, padding, 0) policyView.movementMethod = LinkMovementMethod.getInstance() @@ -73,7 +73,7 @@ class MainActivity : Activity() { projectList.adapter = adapter val str = getString(R.string.guidance_info, getVersion(this)) - headerView.findViewById(R.id.guidance_info).text = Html.fromHtml(str) + headerView.findViewById(R.id.guidance_info).text = Html.fromHtml(str, Html.FROM_HTML_MODE_LEGACY) headerView.findViewById(R.id.menu_privacy).setOnClickListener { try { val intent = Intent(Intent.ACTION_VIEW) diff --git a/app/src/main/java/soko/ekibun/stitch/ProjectListAdapter.kt b/app/src/main/java/soko/ekibun/stitch/ProjectListAdapter.kt index 3cb40f4..bd5c410 100644 --- a/app/src/main/java/soko/ekibun/stitch/ProjectListAdapter.kt +++ b/app/src/main/java/soko/ekibun/stitch/ProjectListAdapter.kt @@ -6,8 +6,8 @@ import android.view.ViewGroup import android.widget.BaseAdapter import android.widget.TextView import java.io.File -import java.time.Instant -import java.time.ZoneId +import java.text.SimpleDateFormat +import java.util.* class ProjectListAdapter(private val headerView: View) : BaseAdapter() { @@ -31,12 +31,16 @@ class ProjectListAdapter(private val headerView: View) : BaseAdapter() { override fun getView(i: Int, convertView: View?, parent: ViewGroup): View { if (i == 0) return headerView val view = if (convertView != headerView && convertView != null) convertView else - LayoutInflater.from(parent.context).inflate(R.layout.list_project, null, false) + LayoutInflater.from(parent.context).inflate(R.layout.list_project, parent, false) val file = getItem(i) val titleView = view.findViewById(R.id.text_title) titleView.text = file.name.toLongOrNull(16)?.let { - Instant.ofEpochMilli(it).atZone(ZoneId.systemDefault()).toString().substringBefore('+') - } + dateFormat.format( + Calendar.getInstance().apply { + timeInMillis = it + }.time + ) + } ?: file.name view.findViewById(R.id.item_view).setOnClickListener { EditActivity.startActivity(parent.context, file.name) } @@ -46,4 +50,6 @@ class ProjectListAdapter(private val headerView: View) : BaseAdapter() { } return view } + + val dateFormat by lazy { SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS", Locale.getDefault()) } } diff --git a/app/src/main/java/soko/ekibun/stitch/RangeSeekbar.kt b/app/src/main/java/soko/ekibun/stitch/RangeSeekbar.kt index f6de0bf..999f0e4 100644 --- a/app/src/main/java/soko/ekibun/stitch/RangeSeekbar.kt +++ b/app/src/main/java/soko/ekibun/stitch/RangeSeekbar.kt @@ -48,6 +48,17 @@ class RangeSeekbar(context: Context?, attrs: AttributeSet?) : View(context, attr @SuppressLint("DrawAllocation") override fun onDraw(c: Canvas) { + if (!isEnabled) { + controlPaint.color = colorOpaque + c.drawRect( + radius, + height / 2f - thick, + width.toFloat() - radius, + height / 2f + thick, + controlPaint + ) + return + } val ax = radius + (width - 2 * radius) * a val bx = radius + (width - 2 * radius) * b when (type) { @@ -153,6 +164,7 @@ class RangeSeekbar(context: Context?, attrs: AttributeSet?) : View(context, attr @SuppressLint("ClickableViewAccessibility") override fun onTouchEvent(event: MotionEvent): Boolean { + if (!isEnabled) return false when (event.action) { MotionEvent.ACTION_DOWN -> { parent.requestDisallowInterceptTouchEvent(true) diff --git a/app/src/main/java/soko/ekibun/stitch/Stitch.kt b/app/src/main/java/soko/ekibun/stitch/Stitch.kt index 4e436cc..81d8904 100644 --- a/app/src/main/java/soko/ekibun/stitch/Stitch.kt +++ b/app/src/main/java/soko/ekibun/stitch/Stitch.kt @@ -22,13 +22,13 @@ object Stitch { App.getProjectFile(projectKey) } val stitchInfo by lazy { - val list = mutableListOf() + val list = mutableListOf() runBlocking(App.dispatcherIO) { if (file.exists()) try { val ins = ObjectInputStream(file.inputStream()) val size = ins.readInt() for (i in 0 until size) { - list.add(ins.readObject() as Stitch.StitchInfo) + list.add(ins.readObject() as StitchInfo) } ins.close() } catch (e: IOException) { @@ -38,12 +38,13 @@ object Stitch { list } - private val stitchInfoBak by lazy { mutableListOf() } + private val stitchInfoBak by lazy { mutableListOf() } fun updateUndo() { stitchInfoBak.clear() stitchInfoBak.addAll(stitchInfo.map { it.clone() }) + @Suppress("BlockingMethodInNonBlockingContext") MainScope().launch(App.dispatcherIO) { if (!file.exists()) { if (stitchInfo.isNotEmpty()) file.parentFile?.mkdirs() @@ -298,72 +299,52 @@ object Stitch { } } - enum class CombineMethod { - PHASE_CORRELATE, FIND_HOMOGRAPHY, PHASE_CORRELATE_DIFF, FIND_HOMOGRAPHY_DIFF, - } - - fun combine(method: CombineMethod, img0: StitchInfo, img1: StitchInfo): StitchInfo? { + fun combine(homo: Boolean, diff: Boolean, img0: StitchInfo, img1: StitchInfo): StitchInfo? { val data = DoubleArray(9) - return when (method) { - CombineMethod.PHASE_CORRELATE, CombineMethod.PHASE_CORRELATE_DIFF -> { - val bmp0 = getClipBitmap(img0, img1) ?: return null - val bmp1 = getClipBitmap(img1, img0) ?: return null - if (!phaseCorrelateNative( - bmp0, - bmp1, - method == CombineMethod.PHASE_CORRELATE_DIFF, - data - ) - ) return null - img1.clone().also { - val dx = (data[2] + (0.5 - img1.xa) * img1.width - - (0.5 - img0.xa) * img0.width).toFloat() - val dy = (data[5] + (0.5 - img0.ya) * img1.height - - (0.5 - img0.ya) * img0.height).toFloat() - if ((dx != 0f || dy != 0f) && - abs(dx) < (img1.width + img0.width) / 2 && - abs(dy) < (img1.height + img0.height) / 2 - ) { - it.dx = dx - it.dy = dy - it.drot = 0f - it.dscale = 1f - } + return if (homo) { + val bmp0 = getClipBitmap(img0) ?: return null + val bmp1 = getClipBitmap(img1) ?: return null + if (!findHomographyNative(bmp0, bmp1, diff, data)) return null + img1.clone().also { + val cx = (0.5 - img1.xa) * img1.width + val cy = (0.5 - img1.ya) * img1.height + val ps = data[6] * cx + data[7] * cy + data[8] + Log.v("HOMO", data.toList().toString()) + val dx = ((data[0] * cx + data[1] * cy + data[2]) / ps - + (0.5 - img0.xa) * img0.width).toFloat() + val dy = ((data[3] * cx + data[4] * cy + data[5]) / ps - + (0.5 - img0.ya) * img0.height).toFloat() + val scale = sqrt(abs(data[0] * data[4] - data[1] * data[3])) + val rot = atan2((data[3] - data[1]) / 2, (data[0] + data[4]) / 2) * 180 / Math.PI + if ((dx != 0f || dy != 0f) && + abs(dx) < (img1.width + img0.width) / 2 && + abs(dy) < (img1.height + img0.height) / 2 + ) { + it.dx = dx + it.dy = dy + it.drot = rot.toFloat() + it.dscale = scale.toFloat() } } - CombineMethod.FIND_HOMOGRAPHY, CombineMethod.FIND_HOMOGRAPHY_DIFF -> { - val bmp0 = getClipBitmap(img0) ?: return null - val bmp1 = getClipBitmap(img1) ?: return null - if (!findHomographyNative( - bmp0, - bmp1, - method == CombineMethod.FIND_HOMOGRAPHY_DIFF, - data - ) - ) return null - img1.clone().also { - val cx = (0.5 - img1.xa) * img1.width - val cy = (0.5 - img1.ya) * img1.height - val ps = data[6] * cx + data[7] * cy + data[8] - Log.v("HOMO", data.toList().toString()) - val dx = ((data[0] * cx + data[1] * cy + data[2]) / ps - - (0.5 - img0.xa) * img0.width).toFloat() - val dy = ((data[3] * cx + data[4] * cy + data[5]) / ps - - (0.5 - img0.ya) * img0.height).toFloat() - val scale = sqrt(abs(data[0] * data[4] - data[1] * data[3])) - val rot = atan2((data[3] - data[1]) / 2, (data[0] + data[4]) / 2) * 180 / Math.PI - if ((dx != 0f || dy != 0f) && - abs(dx) < (img1.width + img0.width) / 2 && - abs(dy) < (img1.height + img0.height) / 2 - ) { - it.dx = dx - it.dy = dy - it.drot = rot.toFloat() - it.dscale = scale.toFloat() - } + } else { + val bmp0 = getClipBitmap(img0, img1) ?: return null + val bmp1 = getClipBitmap(img1, img0) ?: return null + if (!phaseCorrelateNative(bmp0, bmp1, diff, data)) return null + img1.clone().also { + val dx = (data[2] + (0.5 - img1.xa) * img1.width - + (0.5 - img0.xa) * img0.width).toFloat() + val dy = (data[5] + (0.5 - img0.ya) * img1.height - + (0.5 - img0.ya) * img0.height).toFloat() + if ((dx != 0f || dy != 0f) && + abs(dx) < (img1.width + img0.width) / 2 && + abs(dy) < (img1.height + img0.height) / 2 + ) { + it.dx = dx + it.dy = dy + it.drot = 0f + it.dscale = 1f } } } - } } \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_rect.xml b/app/src/main/res/drawable/bg_rect.xml index 5024076..49c4ee7 100644 --- a/app/src/main/res/drawable/bg_rect.xml +++ b/app/src/main/res/drawable/bg_rect.xml @@ -3,7 +3,7 @@ android:color="?android:attr/colorControlHighlight"> - + diff --git a/app/src/main/res/drawable/ic_arrow_back.xml b/app/src/main/res/drawable/ic_arrow_back.xml new file mode 100644 index 0000000..0c2f81d --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_back.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/ic_arrow_forward.xml b/app/src/main/res/drawable/ic_arrow_forward.xml new file mode 100644 index 0000000..ede63b7 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_forward.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/ic_check_all.xml b/app/src/main/res/drawable/ic_check_all.xml new file mode 100644 index 0000000..366aceb --- /dev/null +++ b/app/src/main/res/drawable/ic_check_all.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_check_clear.xml b/app/src/main/res/drawable/ic_check_clear.xml new file mode 100644 index 0000000..01136e5 --- /dev/null +++ b/app/src/main/res/drawable/ic_check_clear.xml @@ -0,0 +1,13 @@ + + + + diff --git a/app/src/main/res/drawable/ic_chevron_left.xml b/app/src/main/res/drawable/ic_chevron_left.xml new file mode 100644 index 0000000..11623d2 --- /dev/null +++ b/app/src/main/res/drawable/ic_chevron_left.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_chevron_right.xml b/app/src/main/res/drawable/ic_chevron_right.xml new file mode 100644 index 0000000..941f7dc --- /dev/null +++ b/app/src/main/res/drawable/ic_chevron_right.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_drop_down.xml b/app/src/main/res/drawable/ic_drop_down.xml new file mode 100644 index 0000000..683f8d6 --- /dev/null +++ b/app/src/main/res/drawable/ic_drop_down.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_edit.xml b/app/src/main/res/drawable/ic_edit.xml new file mode 100644 index 0000000..7440492 --- /dev/null +++ b/app/src/main/res/drawable/ic_edit.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_image_add.xml b/app/src/main/res/drawable/ic_image_add.xml new file mode 100644 index 0000000..140ae46 --- /dev/null +++ b/app/src/main/res/drawable/ic_image_add.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_save.xml b/app/src/main/res/drawable/ic_save.xml new file mode 100644 index 0000000..427c192 --- /dev/null +++ b/app/src/main/res/drawable/ic_save.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_share.xml b/app/src/main/res/drawable/ic_share.xml new file mode 100644 index 0000000..2da9afd --- /dev/null +++ b/app/src/main/res/drawable/ic_share.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_shuffle.xml b/app/src/main/res/drawable/ic_shuffle.xml new file mode 100644 index 0000000..76ff342 --- /dev/null +++ b/app/src/main/res/drawable/ic_shuffle.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_undo.xml b/app/src/main/res/drawable/ic_undo.xml new file mode 100644 index 0000000..8a0c779 --- /dev/null +++ b/app/src/main/res/drawable/ic_undo.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/activity_edit.xml b/app/src/main/res/layout/activity_edit.xml index 5e14d65..dd14607 100644 --- a/app/src/main/res/layout/activity_edit.xml +++ b/app/src/main/res/layout/activity_edit.xml @@ -3,235 +3,219 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:orientation="vertical"> + android:orientation="vertical" + tools:ignore="UnusedAttribute,ContentDescription,LabelFor"> + android:layout_weight="1" /> + android:gravity="center_vertical" + android:orientation="horizontal" + android:padding="8dp"> + + + android:tooltipText="@string/menu_select_all" + android:src="@drawable/ic_check_all" + android:tint="?android:attr/textColorPrimary" /> - - - + android:tooltipText="@string/menu_select_clear" + android:src="@drawable/ic_check_clear" + android:tint="?android:attr/textColorPrimary" /> - + android:tooltipText="@string/menu_swap" + android:src="@drawable/ic_shuffle" + android:tint="?android:attr/textColorPrimary" /> - - - + android:tooltipText="@string/menu_remove" + android:src="@drawable/ic_delete" + android:tint="?android:attr/textColorPrimary" /> - + android:layout_height="wrap_content" + android:background="@drawable/bg_rect" + android:backgroundTint="@color/opaque" + android:gravity="center_vertical" + android:padding="8dp"> - + android:layout_weight="1"> - - - - - - + android:layout_height="wrap_content"> - + android:checked="true" + android:gravity="center" + android:text="@string/switch_diff" /> - - - - - + android:text="@string/switch_homography" /> + - - - + + - + - + - + - + - + + + + + - - + + + - + - + android:tooltipText="@string/menu_import" + android:src="@drawable/ic_image_add" + android:tint="?android:colorPrimary" /> - - - - - + android:tooltipText="@string/menu_undo" + android:src="@drawable/ic_undo" + android:tint="?android:attr/textColorPrimary" /> - + android:tooltipText="@string/menu_share" + android:src="@drawable/ic_share" + android:tint="?android:attr/textColorPrimary" /> - + android:tooltipText="@string/menu_save" + android:src="@drawable/ic_save" + android:tint="@android:color/white" /> \ No newline at end of file diff --git a/app/src/main/res/layout/list_header.xml b/app/src/main/res/layout/list_header.xml index 5cb17eb..f4bad89 100644 --- a/app/src/main/res/layout/list_header.xml +++ b/app/src/main/res/layout/list_header.xml @@ -3,7 +3,8 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="vertical"> + android:orientation="vertical" + tools:ignore="ContentDescription,NestedWeights"> + android:layout_height="wrap_content" + android:baselineAligned="false"> @@ -66,6 +69,7 @@ android:layout_margin="8dp" android:layout_weight="1" android:background="@drawable/bg_rect" + android:backgroundTint="@color/opaque" android:gravity="center" android:orientation="horizontal" android:padding="24dp"> diff --git a/app/src/main/res/layout/list_project.xml b/app/src/main/res/layout/list_project.xml index 1ba702d..40e0730 100644 --- a/app/src/main/res/layout/list_project.xml +++ b/app/src/main/res/layout/list_project.xml @@ -10,9 +10,11 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/bg_rect" + android:backgroundTint="@color/opaque" android:gravity="center_vertical" android:orientation="horizontal" - android:padding="8dp"> + android:padding="8dp" + tools:ignore="UselessParent,ContentDescription"> - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 2ee73f8..d1ca13a 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,6 +1,5 @@ #4284F3 - #f44 #4888 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4b31537..a0ad4b2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -16,18 +16,27 @@ 取消 确认 - 全选 - 清除 - 选中 %d/%d + 去重 + 特征匹配(旋转缩放) + 删除 自动拼接 - 水平偏移 - 竖向偏移 - 裁切位置 + 全选 + 清除 导入 截图 保存 分享 + + 选中 %d/%d + 水平偏移 + 竖向偏移 + 过渡位置 + 横向范围 + 纵向范围 + 旋转角度 + 缩放比例 + 图片保存成功 出错啦 捕捉屏幕失败,请允许后台运行并重新截取 @@ -108,17 +117,11 @@ SURF is noncommercial. You may not use this work for commercial purposes. For any reuse or distribution, you must make clear to others the license terms of this work. Any of these conditions can be waived if you get written permission from the copyright holder. 开源许可协议 - 横向范围 - 纵向范围 + 撤销 - 从相册导入 + 相册导入 屏幕截图 关于 - 旋转角度 - 特征匹配 - 相位相关 - 特征匹配(去重) - 相位相关(去重) - 缩放 清空历史记录 + - \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 138bca7..5cda9d6 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -6,6 +6,7 @@ @color/colorPrimary @color/colorPrimary @color/colorPrimary + @color/colorPrimary true @style/Theme.Stitch.Dialog ?android:colorBackground diff --git a/build.gradle b/build.gradle index 8f6d5a9..234e793 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,11 @@ buildscript { - ext.kotlin_version = '1.7.10' repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.0.3' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath 'com.android.tools.build:gradle:7.2.1' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10" } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c86e4e9..a796bcb 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Sun Aug 01 08:58:25 CST 2021 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME