add swipe functionality and update docs
@ -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
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,7 @@ class MainActivity : AppCompatActivity() {
|
||||
findViewById<SeekBar>(R.id.iconSizeSb).isEnabled = !isChecked
|
||||
}
|
||||
toggle(findViewById(R.id.restoreOnClose), "restoreOnClose", false) {}
|
||||
toggle(findViewById(R.id.scroll), "scroll", false) {}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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<File>,
|
||||
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
|
||||
|
@ -206,6 +206,20 @@
|
||||
android:text="@string/options_restore_on_close" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
style="@style/widthMatchHeightWrap"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/scroll"
|
||||
style="@style/checkbox" />
|
||||
|
||||
<TextView
|
||||
style="@style/body_text"
|
||||
android:paddingBottom="@dimen/content_margin"
|
||||
android:text="@string/options_scroll" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
style="@style/widthMatchHeightWrap"
|
||||
android:orientation="horizontal">
|
||||
|
@ -22,6 +22,7 @@
|
||||
<string name="options_show_back_button">Show back button in navbar</string>
|
||||
<string name="options_vertical">Use vertical layout</string>
|
||||
<string name="options_restore_on_close">Restore previous keyboard on keyboard close</string>
|
||||
<string name="options_scroll">Enable swipe between packs (perpendicular to scroll direction)</string>
|
||||
<string name="options_icons_per_x_lbl">"Number of Rows: "</string>
|
||||
<string name="options_icon_size_status_lbl">"Icon size: "</string>
|
||||
<!-- Info -->
|
||||
|
@ -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)
|
||||
|
||||
<img src="assets/step1.png" alt="Step 1" width="600">
|
||||
<img src="assets/make-packs.png" alt="VSCode showing an example sticker pack structure" width="600">
|
||||
|
||||
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
|
||||
|
||||
<img src="assets/screenshot-1.png" alt="Step 3.1" width="300">
|
||||
<img src="assets/enable-import.png" alt="EweSticker UI with 'Launch Settings' button" width="300">
|
||||
|
||||
2. Toggle EweSticker on
|
||||
Toggle EweSticker on
|
||||
|
||||
<img src="assets/step3.png" alt="Step 3" width="300">
|
||||
<img src="assets/sys-enable.png" alt="System UI 'On Screen Keyboard' with EweSticker toggle" width="300">
|
||||
|
||||
## 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
|
||||
|
||||
<img src="assets/screenshot-1.png" alt="Step 4.1" width="300">
|
||||
<img src="assets/enable-import.png" alt="EweSticker UI with 'Choose sticker source directory' button" width="300">
|
||||
|
||||
2. Select the sticker directory created in step 1
|
||||
Select the sticker directory created in step 1
|
||||
|
||||
<img src="assets/screenshot-2.png" alt="Step 4.2" width="300">
|
||||
<img src="assets/sys-import.png" alt="System UI file chooser" width="300">
|
||||
|
||||
## 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
|
||||
|
||||
<img src="assets/screenshot-3.png" alt="Step 5" width="300">
|
||||
<img src="assets/sys-switcher.png" alt="System UI keyboard switcher wit select EweSticker" width="300">
|
||||
|
||||
2. Find and send a sticker of your choosing
|
||||
Find and send a sticker of your choosing
|
||||
|
||||
<img src="assets/screenshot-4.png" alt="Step 5.2" width="300">
|
||||
<img src="assets/few.png" alt="EweSticker UI showing horizontal layout 5 wide x 3 stickers deep" width="300">
|
||||
|
||||
|
||||
**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
|
||||
|
||||
<img src="assets/configure.png" alt="EweSticker UI showing configuration options" width="300">
|
||||
|
||||
|
||||
<img src="assets/many.png" alt="EweSticker UI showing horizontal layout 5 wide x 6 stickers deep" width="300">
|
||||
|
BIN
documentation/tutorials/assets/configure.png
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
documentation/tutorials/assets/enable-import.png
Normal file
After Width: | Height: | Size: 107 KiB |
BIN
documentation/tutorials/assets/few.png
Normal file
After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
BIN
documentation/tutorials/assets/many.png
Normal file
After Width: | Height: | Size: 120 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 20 KiB |
BIN
documentation/tutorials/assets/sys-enable.png
Normal file
After Width: | Height: | Size: 83 KiB |
BIN
documentation/tutorials/assets/sys-import.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
documentation/tutorials/assets/sys-switcher.png
Normal file
After Width: | Height: | Size: 265 KiB |