diff --git a/app/src/main/java/com/fredhappyface/ewesticker/ImageKeyboard.kt b/app/src/main/java/com/fredhappyface/ewesticker/ImageKeyboard.kt index 9cfdfa3..e20c22f 100644 --- a/app/src/main/java/com/fredhappyface/ewesticker/ImageKeyboard.kt +++ b/app/src/main/java/com/fredhappyface/ewesticker/ImageKeyboard.kt @@ -3,6 +3,8 @@ package com.fredhappyface.ewesticker import android.content.SharedPreferences import android.inputmethodservice.InputMethodService import android.os.Build.VERSION.SDK_INT +import android.view.GestureDetector +import android.view.MotionEvent import android.view.View import android.view.ViewGroup import android.view.inputmethod.EditorInfo @@ -28,8 +30,11 @@ import com.fredhappyface.ewesticker.utilities.StickerClickListener import com.fredhappyface.ewesticker.utilities.StickerSender import com.fredhappyface.ewesticker.utilities.Toaster import java.io.File +import kotlin.math.abs import kotlin.math.min +private const val SWIPE_THRESHOLD = 1 +private const val SWIPE_VELOCITY_THRESHOLD = 1 /** * ImageKeyboard class inherits from the InputMethodService class - provides the keyboard @@ -41,6 +46,7 @@ class ImageKeyboard : InputMethodService(), StickerClickListener { private lateinit var sharedPreferences: SharedPreferences private var restoreOnClose = false private var vertical = false + private var scroll = false private var iconsPerX = 0 private var iconSize = 0 @@ -67,6 +73,9 @@ class ImageKeyboard : InputMethodService(), StickerClickListener { private var keyboardHeight = 0 private var fullIconSize = 0 + private lateinit var gestureDetector: GestureDetector + + /** * When the activity is created... * - ensure coil can decode (and display) animated images @@ -94,6 +103,7 @@ class ImageKeyboard : InputMethodService(), StickerClickListener { this.sharedPreferences = PreferenceManager.getDefaultSharedPreferences(baseContext) this.restoreOnClose = this.sharedPreferences.getBoolean("restoreOnClose", false) this.vertical = this.sharedPreferences.getBoolean("vertical", false) + this.scroll = this.sharedPreferences.getBoolean("scroll", false) this.iconsPerX = this.sharedPreferences.getInt("iconsPerX", 3) this.totalIconPadding = (resources.getDimension(R.dimen.sticker_padding) * 2 * (this.iconsPerX + 1)).toInt() @@ -141,6 +151,7 @@ class ImageKeyboard : InputMethodService(), StickerClickListener { */ override fun onCreateInputView(): View { val keyboardLayout = View.inflate(baseContext, R.layout.keyboard_layout, null) + gestureDetector = GestureDetector(baseContext, GestureListener()) this.keyboardRoot = keyboardLayout.findViewById(R.id.keyboardRoot) this.packsList = keyboardLayout.findViewById(R.id.packsList) @@ -228,7 +239,7 @@ class ImageKeyboard : InputMethodService(), StickerClickListener { stickers = loadedPacks[packName]?.stickerList ?: return } val recyclerView = RecyclerView(this) - val adapter = StickerPackAdapter(iconSize, stickers, this) + val adapter = StickerPackAdapter(iconSize, stickers, this, gestureDetector) val layoutManager = GridLayoutManager( this, iconsPerX, @@ -320,6 +331,76 @@ class ImageKeyboard : InputMethodService(), StickerClickListener { fSticker.setOnClickListener { this.keyboardRoot.removeView(fullStickerLayout) } this.keyboardRoot.addView(fullStickerLayout) } + + internal fun switchToPreviousPack() { + // Get a list of sorted pack names + val sortedPackNames = loadedPacks.keys.sorted() + + // Find the index of the current active pack + val currentIndex = sortedPackNames.indexOf(activePack) + + // Calculate the index of the previous pack, considering wrap-around + val previousIndex = if (currentIndex > 0) currentIndex - 1 else sortedPackNames.size - 1 + + // Get the name of the previous pack + val previousPack = sortedPackNames[previousIndex] + + // Switch to the previous pack layout + switchPackLayout(previousPack) + } + + internal fun switchToNextPack() { + // Get a list of sorted pack names + val sortedPackNames = loadedPacks.keys.sorted() + + // Find the index of the current active pack + val currentIndex = sortedPackNames.indexOf(activePack) + + // Calculate the index of the next pack, considering wrap-around + val nextIndex = (currentIndex + 1) % sortedPackNames.size + + // Get the name of the next pack + val nextPack = sortedPackNames[nextIndex] + + // Switch to the next pack layout + switchPackLayout(nextPack) + } + + + private inner class GestureListener : GestureDetector.SimpleOnGestureListener() { + override fun onDown(e: MotionEvent): Boolean { + return false + } + + override fun onScroll( + e1: MotionEvent, + e2: MotionEvent, + velocityX: Float, + velocityY: Float + ): Boolean { + val diffX = e2.x - e1.x + val diffY = e2.y - e1.y + + if ( + scroll && + abs(if (vertical) diffX else diffY) > SWIPE_THRESHOLD && + abs(if (vertical) velocityX else velocityY) > SWIPE_VELOCITY_THRESHOLD + ) { + if (diffX > 0) { + // Swipe right + switchToPreviousPack() + } else { + // Swipe left + switchToNextPack() + } + return true + } + + return false + } + } + + } fun trimString(str: String): String { @@ -328,3 +409,4 @@ fun trimString(str: String): String { } return str } + diff --git a/app/src/main/java/com/fredhappyface/ewesticker/MainActivity.kt b/app/src/main/java/com/fredhappyface/ewesticker/MainActivity.kt index 13685f6..29b02a7 100644 --- a/app/src/main/java/com/fredhappyface/ewesticker/MainActivity.kt +++ b/app/src/main/java/com/fredhappyface/ewesticker/MainActivity.kt @@ -51,6 +51,7 @@ class MainActivity : AppCompatActivity() { findViewById(R.id.iconSizeSb).isEnabled = !isChecked } toggle(findViewById(R.id.restoreOnClose), "restoreOnClose", false) {} + toggle(findViewById(R.id.scroll), "scroll", false) {} } /** diff --git a/app/src/main/java/com/fredhappyface/ewesticker/adapter/StickerPackAdapter.kt b/app/src/main/java/com/fredhappyface/ewesticker/adapter/StickerPackAdapter.kt index 19c446d..a8b1c7a 100644 --- a/app/src/main/java/com/fredhappyface/ewesticker/adapter/StickerPackAdapter.kt +++ b/app/src/main/java/com/fredhappyface/ewesticker/adapter/StickerPackAdapter.kt @@ -1,5 +1,6 @@ package com.fredhappyface.ewesticker.adapter +import android.view.GestureDetector import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView @@ -12,7 +13,8 @@ import java.io.File class StickerPackAdapter( private val iconSize: Int, private val stickers: Array, - private val listener: StickerClickListener + private val listener: StickerClickListener, + private val gestureDetector: GestureDetector, ) : @@ -39,6 +41,9 @@ class StickerPackAdapter( listener.onStickerLongClicked(file) return@setOnLongClickListener true } + holder.stickerThumbnail.setOnTouchListener { _, event -> + gestureDetector.onTouchEvent(event) + } } override fun getItemCount(): Int = stickers.size diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 30d4b6f..3554d7b 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -206,6 +206,20 @@ android:text="@string/options_restore_on_close" /> + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e2621ee..cb42b2b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -22,6 +22,7 @@ Show back button in navbar Use vertical layout Restore previous keyboard on keyboard close + Enable swipe between packs (perpendicular to scroll direction) "Number of Rows: " "Icon size: " diff --git a/documentation/tutorials/README.md b/documentation/tutorials/README.md index 380c3e7..8746e68 100644 --- a/documentation/tutorials/README.md +++ b/documentation/tutorials/README.md @@ -10,12 +10,12 @@ sticker collection. - [Get it on Google Play](#get-it-on-google-play) - [Download the APK](#download-the-apk) - [Step 3 - Activate the keyboard](#step-3---activate-the-keyboard) -- [Step 4 - Select Directory with EweSticker (and wait...)](#step-4---select-directory-with-ewesticker-and-wait) +- [Step 4 - Select Directory with EweSticker )](#step-4---select-directory-with-ewesticker-) - [Step 5 - Send Stickers in your favourite apps](#step-5---send-stickers-in-your-favourite-apps) ## Step 1 - Create Sticker Directory (and transfer to device) -Step 1 +VSCode showing an example sticker pack structure The sticker directory has the following structure: @@ -78,30 +78,45 @@ Navigate to the releases page by clicking on the badge above. ## Step 3 - Activate the keyboard -1. Click the "LAUNCH SETTINGS" button +Click the `Launch Settings` button - Step 3.1 +EweSticker UI with 'Launch Settings' button -2. Toggle EweSticker on +Toggle EweSticker on - Step 3 +System UI 'On Screen Keyboard' with EweSticker toggle -## Step 4 - Select Directory with EweSticker (and wait...) +## Step 4 - Select Directory with EweSticker ) -1. Click the "CHOOSE STICKER SOURCE DIRECTORY" button +Click the `Choose sticker source directory` button - Step 4.1 +EweSticker UI with 'Choose sticker source directory' button -2. Select the sticker directory created in step 1 +Select the sticker directory created in step 1 - Step 4.2 +System UI file chooser ## Step 5 - Send Stickers in your favourite apps -1. Tap the keyboard switcher icon and select EweSticker +Tap the keyboard switcher icon and select EweSticker - Step 5 +System UI keyboard switcher wit select EweSticker -2. Find and send a sticker of your choosing +Find and send a sticker of your choosing - Step 5.2 +EweSticker UI showing horizontal layout 5 wide x 3 stickers deep + + +**Note:** That you can configure EweSticker to: + +- enable/disable the back button +- use the vertical scroll layout +- restore the previous keyboard when the keyboard is closed (through tapping away from a text input) +- enable swipe between sticker packs (perpendicular to scroll direction, i.e. vertical swipe if not using the vertical layout) +- number of rows (between 2 and 6) +- icon size if not in vertical scroll layout + +EweSticker UI showing configuration options + + +EweSticker UI showing horizontal layout 5 wide x 6 stickers deep diff --git a/documentation/tutorials/assets/configure.png b/documentation/tutorials/assets/configure.png new file mode 100644 index 0000000..161f104 Binary files /dev/null and b/documentation/tutorials/assets/configure.png differ diff --git a/documentation/tutorials/assets/enable-import.png b/documentation/tutorials/assets/enable-import.png new file mode 100644 index 0000000..df6679a Binary files /dev/null and b/documentation/tutorials/assets/enable-import.png differ diff --git a/documentation/tutorials/assets/few.png b/documentation/tutorials/assets/few.png new file mode 100644 index 0000000..c765b85 Binary files /dev/null and b/documentation/tutorials/assets/few.png differ diff --git a/documentation/tutorials/assets/step1.png b/documentation/tutorials/assets/make-packs.png similarity index 100% rename from documentation/tutorials/assets/step1.png rename to documentation/tutorials/assets/make-packs.png diff --git a/documentation/tutorials/assets/many.png b/documentation/tutorials/assets/many.png new file mode 100644 index 0000000..010f44c Binary files /dev/null and b/documentation/tutorials/assets/many.png differ diff --git a/documentation/tutorials/assets/screenshot-1.png b/documentation/tutorials/assets/screenshot-1.png deleted file mode 100644 index b0407d6..0000000 Binary files a/documentation/tutorials/assets/screenshot-1.png and /dev/null differ diff --git a/documentation/tutorials/assets/screenshot-2.png b/documentation/tutorials/assets/screenshot-2.png deleted file mode 100644 index 0f10909..0000000 Binary files a/documentation/tutorials/assets/screenshot-2.png and /dev/null differ diff --git a/documentation/tutorials/assets/screenshot-3.png b/documentation/tutorials/assets/screenshot-3.png deleted file mode 100644 index 9a495f2..0000000 Binary files a/documentation/tutorials/assets/screenshot-3.png and /dev/null differ diff --git a/documentation/tutorials/assets/screenshot-4.png b/documentation/tutorials/assets/screenshot-4.png deleted file mode 100644 index a327072..0000000 Binary files a/documentation/tutorials/assets/screenshot-4.png and /dev/null differ diff --git a/documentation/tutorials/assets/step3.png b/documentation/tutorials/assets/step3.png deleted file mode 100644 index da32efb..0000000 Binary files a/documentation/tutorials/assets/step3.png and /dev/null differ diff --git a/documentation/tutorials/assets/sys-enable.png b/documentation/tutorials/assets/sys-enable.png new file mode 100644 index 0000000..50d0167 Binary files /dev/null and b/documentation/tutorials/assets/sys-enable.png differ diff --git a/documentation/tutorials/assets/sys-import.png b/documentation/tutorials/assets/sys-import.png new file mode 100644 index 0000000..94aace5 Binary files /dev/null and b/documentation/tutorials/assets/sys-import.png differ diff --git a/documentation/tutorials/assets/sys-switcher.png b/documentation/tutorials/assets/sys-switcher.png new file mode 100644 index 0000000..40a7381 Binary files /dev/null and b/documentation/tutorials/assets/sys-switcher.png differ