Long press on a sticker to show a preview + Update fonts
This commit is contained in:
parent
a20cb26360
commit
df71ab1254
@ -7,12 +7,14 @@ patch-level version changes can be found in [commit messages](../../commits/mast
|
|||||||
- Use coil https://coil-kt.github.io/coil/ for supported image types to improve performance
|
- Use coil https://coil-kt.github.io/coil/ for supported image types to improve performance
|
||||||
- Add support for vertical scroll https://github.com/FredHappyface/Android.EweSticker/issues/8
|
- Add support for vertical scroll https://github.com/FredHappyface/Android.EweSticker/issues/8
|
||||||
- Add Spanish translation https://github.com/FredHappyface/Android.EweSticker/pull/13
|
- Add Spanish translation https://github.com/FredHappyface/Android.EweSticker/pull/13
|
||||||
|
- Long press on a sticker to show a preview https://github.com/FredHappyface/Android.EweSticker/issues/10
|
||||||
- Use JavaVersion.VERSION_11 in place of JavaVersion.VERSION_1_8
|
- Use JavaVersion.VERSION_11 in place of JavaVersion.VERSION_1_8
|
||||||
- Use GridLayout in place of linear views
|
- Use GridLayout in place of linear views
|
||||||
- Refactor and code clean up (reduced ImageKeyboard.kt by about 17% sloc, reduced MainActivity.kt by about 18% sloc)
|
- Refactor and code clean up (reduced ImageKeyboard.kt by about 17% sloc, reduced MainActivity.kt by about 18% sloc)
|
||||||
- Update UI (now more material you inspired)
|
- Update UI (now more material you inspired)
|
||||||
- Update screenshots
|
- Update screenshots
|
||||||
- Update tutorial
|
- Update tutorial
|
||||||
|
- Update fonts (using fira sans ttf)
|
||||||
|
|
||||||
## 20211011 - 2021/10/11
|
## 20211011 - 2021/10/11
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ Sticker-board for android inspired by uSticker (forked from woosticker).
|
|||||||
- Vertical and Horizontal scrolling
|
- Vertical and Horizontal scrolling
|
||||||
- Change number of rows and sticker preview size
|
- Change number of rows and sticker preview size
|
||||||
- Ties in with the system theme
|
- Ties in with the system theme
|
||||||
|
- Long press on a sticker to show a preview
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import android.view.inputmethod.EditorInfo
|
|||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.ImageButton
|
import android.widget.ImageButton
|
||||||
|
import android.widget.RelativeLayout
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
import androidx.core.content.res.ResourcesCompat
|
import androidx.core.content.res.ResourcesCompat
|
||||||
@ -29,6 +30,7 @@ import java.io.FileOutputStream
|
|||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImageKeyboard class inherits from the InputMethodService class - provides the keyboard functionality
|
* ImageKeyboard class inherits from the InputMethodService class - provides the keyboard functionality
|
||||||
@ -42,17 +44,19 @@ class ImageKeyboard : InputMethodService() {
|
|||||||
// shared pref
|
// shared pref
|
||||||
private lateinit var mSharedPreferences: SharedPreferences
|
private lateinit var mSharedPreferences: SharedPreferences
|
||||||
private var mVertical = false
|
private var mVertical = false
|
||||||
|
private var mKeyboardHeight = 0
|
||||||
private var mIconsPerColumn = 0
|
private var mIconsPerColumn = 0
|
||||||
private var mIconSize = 0
|
private var mIconSize = 0
|
||||||
|
private var mFullIconSize = 0
|
||||||
private var mCompatCache = Cache()
|
private var mCompatCache = Cache()
|
||||||
private var mRecentCache = Cache()
|
private var mRecentCache = Cache()
|
||||||
|
|
||||||
// Attributes
|
// Attributes
|
||||||
private lateinit var mLoadedPacks: HashMap<String, StickerPack>
|
private lateinit var mLoadedPacks: HashMap<String, StickerPack>
|
||||||
private lateinit var mSupportedMimes: MutableMap<String, String>
|
private lateinit var mSupportedMimes: List<String>
|
||||||
|
|
||||||
// keyboard root view, pack content view, pack list view
|
// keyboard root view, pack content view, pack list view
|
||||||
private lateinit var mKeyboardRoot: View
|
private lateinit var mKeyboardRoot: ViewGroup
|
||||||
private lateinit var mPackContent: ViewGroup
|
private lateinit var mPackContent: ViewGroup
|
||||||
private lateinit var mPacksList: ViewGroup
|
private lateinit var mPacksList: ViewGroup
|
||||||
|
|
||||||
@ -122,11 +126,13 @@ class ImageKeyboard : InputMethodService() {
|
|||||||
mKeyboardRoot = keyboardLayout.findViewById(R.id.keyboardRoot)
|
mKeyboardRoot = keyboardLayout.findViewById(R.id.keyboardRoot)
|
||||||
mPacksList = keyboardLayout.findViewById(R.id.packsList)
|
mPacksList = keyboardLayout.findViewById(R.id.packsList)
|
||||||
mPackContent = keyboardLayout.findViewById(R.id.packContent)
|
mPackContent = keyboardLayout.findViewById(R.id.packContent)
|
||||||
mPackContent.layoutParams?.height = if (mVertical) {
|
mKeyboardHeight = if (mVertical) {
|
||||||
800
|
800
|
||||||
} else {
|
} else {
|
||||||
mIconSize * mIconsPerColumn + mTotalIconPadding
|
mIconSize * mIconsPerColumn + mTotalIconPadding
|
||||||
}
|
}
|
||||||
|
mPackContent.layoutParams?.height = mKeyboardHeight
|
||||||
|
mFullIconSize = (min(resources.displayMetrics.widthPixels, mKeyboardHeight) * 0.8).toInt()
|
||||||
createPackIcons()
|
createPackIcons()
|
||||||
return keyboardLayout
|
return keyboardLayout
|
||||||
}
|
}
|
||||||
@ -147,14 +153,7 @@ class ImageKeyboard : InputMethodService() {
|
|||||||
* @param restarting
|
* @param restarting
|
||||||
*/
|
*/
|
||||||
override fun onStartInput(info: EditorInfo?, restarting: Boolean) {
|
override fun onStartInput(info: EditorInfo?, restarting: Boolean) {
|
||||||
mSupportedMimes = Utils.getSupportedMimes()
|
mSupportedMimes = Utils.getSupportedMimes().filter { isCommitContentSupported(info, it) }
|
||||||
val mimesToCheck = mSupportedMimes.keys.toTypedArray()
|
|
||||||
for (mimeToCheck in mimesToCheck) {
|
|
||||||
val mimeSupported = isCommitContentSupported(info, mSupportedMimes[mimeToCheck])
|
|
||||||
if (!mimeSupported) {
|
|
||||||
mSupportedMimes.remove(mimeToCheck)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -178,11 +177,10 @@ class ImageKeyboard : InputMethodService() {
|
|||||||
*/
|
*/
|
||||||
private fun doFallbackCommitContent(file: File) {
|
private fun doFallbackCommitContent(file: File) {
|
||||||
// PNG might not be supported
|
// PNG might not be supported
|
||||||
if (mSupportedMimes[".png"] == null) {
|
if ("image/png" !in mSupportedMimes) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
applicationContext,
|
applicationContext,
|
||||||
Utils.getFileExtension(file.name) +
|
file.extension + " not supported here.", Toast.LENGTH_SHORT
|
||||||
" not supported here.", Toast.LENGTH_SHORT
|
|
||||||
).show()
|
).show()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -307,16 +305,38 @@ class ImageKeyboard : InputMethodService() {
|
|||||||
imgButton.layoutParams.width = mIconSize
|
imgButton.layoutParams.width = mIconSize
|
||||||
imgButton.load(sticker)
|
imgButton.load(sticker)
|
||||||
imgButton.tag = sticker
|
imgButton.tag = sticker
|
||||||
imgButton.setOnClickListener { view: View ->
|
imgButton.setOnClickListener {
|
||||||
val file = view.tag as File
|
val file = it.tag as File
|
||||||
mRecentCache.add(file.absolutePath)
|
mRecentCache.add(file.absolutePath)
|
||||||
val stickerType = mSupportedMimes[Utils.getFileExtension(file.name)]
|
val stickerType = Utils.getMimeType(file)
|
||||||
if (stickerType == null) {
|
if (stickerType == null || stickerType !in mSupportedMimes) {
|
||||||
doFallbackCommitContent(file)
|
doFallbackCommitContent(file)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
doCommitContent(stickerType, file)
|
doCommitContent(stickerType, file)
|
||||||
}
|
}
|
||||||
|
imgButton.setOnLongClickListener { view: View ->
|
||||||
|
val file = view.tag as File
|
||||||
|
val fullSticker = layoutInflater.inflate(
|
||||||
|
R.layout.sticker_preview,
|
||||||
|
mKeyboardRoot,
|
||||||
|
false
|
||||||
|
) as RelativeLayout
|
||||||
|
val fSticker = fullSticker.findViewById<ImageButton>(R.id.stickerButton)
|
||||||
|
// Set dimens + load image
|
||||||
|
fullSticker.layoutParams.height =
|
||||||
|
mKeyboardHeight + (resources.getDimension(R.dimen.pack_dimens) + resources.getDimension(
|
||||||
|
R.dimen.pack_padding_vertical
|
||||||
|
) * 2).toInt()
|
||||||
|
fSticker.layoutParams.height = mFullIconSize
|
||||||
|
fSticker.layoutParams.width = mFullIconSize
|
||||||
|
fSticker.load(file)
|
||||||
|
// Tap to exit popup
|
||||||
|
fullSticker.setOnClickListener { mKeyboardRoot.removeView(it) }
|
||||||
|
fSticker.setOnClickListener { mKeyboardRoot.removeView(fullSticker) }
|
||||||
|
mKeyboardRoot.addView(fullSticker)
|
||||||
|
return@setOnLongClickListener true
|
||||||
|
}
|
||||||
pack.addView(imageCard)
|
pack.addView(imageCard)
|
||||||
}
|
}
|
||||||
return packContainer
|
return packContainer
|
||||||
|
@ -120,9 +120,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
* @return 1 if sticker imported successfully else 0
|
* @return 1 if sticker imported successfully else 0
|
||||||
*/
|
*/
|
||||||
private fun importSticker(sticker: DocumentFile, pack: String): Int {
|
private fun importSticker(sticker: DocumentFile, pack: String): Int {
|
||||||
if (sticker.isDirectory ||
|
if (sticker.isDirectory || sticker.type !in mSupportedMimes) {
|
||||||
!mSupportedMimes.keys.contains(Utils.getFileExtension(sticker.name))
|
|
||||||
) {
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
val destSticker = File(filesDir, "stickers/" + pack + sticker.name)
|
val destSticker = File(filesDir, "stickers/" + pack + sticker.name)
|
||||||
@ -255,6 +253,4 @@ class MainActivity : AppCompatActivity() {
|
|||||||
Snackbar.LENGTH_SHORT
|
Snackbar.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,52 +1,28 @@
|
|||||||
package com.fredhappyface.ewesticker
|
package com.fredhappyface.ewesticker
|
||||||
|
|
||||||
|
import android.webkit.MimeTypeMap
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to provide utils that are shared across ewesticker.
|
* Class to provide utils that are shared across ewesticker.
|
||||||
*/
|
*/
|
||||||
object Utils {
|
object Utils {
|
||||||
/**
|
/**
|
||||||
* @param name the File's name. Takes in a string here instead of a File because in certain
|
* Get the mimetype of a File
|
||||||
* places we have to use DocumentFile instead-- String name can be found by calling
|
*
|
||||||
* .getName() on both, but they are different classes.
|
* @param file File file to get the mimetype of
|
||||||
* @return returns "." inclusive file extension.
|
* @return String? Return the mimetype or none if it cannot be determined
|
||||||
*/
|
*/
|
||||||
fun getFileExtension(name: String?): String {
|
fun getMimeType(file: File): String? {
|
||||||
if (name == null) {
|
return MimeTypeMap.getSingleton().getMimeTypeFromExtension(file.extension)
|
||||||
return ""
|
|
||||||
}
|
|
||||||
val lastIndexOf = name.lastIndexOf(".")
|
|
||||||
return if (lastIndexOf == -1) {
|
|
||||||
""
|
|
||||||
} else name.substring(lastIndexOf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Needs to create a new HashMap on every call because shallow copies will cause issues between
|
* Return a MutableList of EweSticker Supported mimetypes
|
||||||
* different input areas that support different media types.
|
|
||||||
*
|
*
|
||||||
* @return HashMap of ewesticker-supported mimes. Keys are "." inclusive.
|
* @return MutableList of EweSticker Supported mimetypes
|
||||||
*/
|
*/
|
||||||
fun getSupportedMimes(): MutableMap<String, String> {
|
fun getSupportedMimes(): MutableList<String> {
|
||||||
val mimes = mutableMapOf(
|
return mutableListOf("image/gif", "image/png", "image/webp", "image/jpeg", "image/heif")
|
||||||
".gif" to "image/gif",
|
|
||||||
".png" to "image/png",
|
|
||||||
".webp" to "image/webp",
|
|
||||||
)
|
|
||||||
for (el in listOf(".jpg", ".jpeg", ".jpe", ".jif", ".jfif", ".jfi")) {
|
|
||||||
mimes[el] = "image/jpg"
|
|
||||||
}
|
|
||||||
for (el in listOf(
|
|
||||||
".heif",
|
|
||||||
".heifs",
|
|
||||||
".heic",
|
|
||||||
".heics",
|
|
||||||
".avci",
|
|
||||||
".avcs",
|
|
||||||
".avif",
|
|
||||||
".avifs"
|
|
||||||
)) {
|
|
||||||
mimes[el] = "image/heif"
|
|
||||||
}
|
|
||||||
return mimes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
app/src/main/res/font/firasans.ttf
Normal file
BIN
app/src/main/res/font/firasans.ttf
Normal file
Binary file not shown.
BIN
app/src/main/res/font/firasans_bold.ttf
Normal file
BIN
app/src/main/res/font/firasans_bold.ttf
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
23
app/src/main/res/layout/sticker_preview.xml
Normal file
23
app/src/main/res/layout/sticker_preview.xml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/packContent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/bg">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:id="@+id/stickerButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center|center_horizontal|center_vertical"
|
||||||
|
android:background="@color/sticker"
|
||||||
|
android:contentDescription="@string/sticker_icon"
|
||||||
|
android:cropToPadding="true"
|
||||||
|
android:scaleType="fitCenter" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/body_text"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:text="@string/close_sticker_preview" />
|
||||||
|
</RelativeLayout>
|
@ -2,6 +2,7 @@
|
|||||||
<!-- App info -->
|
<!-- App info -->
|
||||||
<string name="pack_icon">Icono del paquete</string>
|
<string name="pack_icon">Icono del paquete</string>
|
||||||
<string name="sticker_icon">Icono del sticker</string>
|
<string name="sticker_icon">Icono del sticker</string>
|
||||||
|
<string name="close_sticker_preview">[Toque para cerrar la vista previa de la etiqueta]</string>
|
||||||
<!-- Update Sticker Pack -->
|
<!-- Update Sticker Pack -->
|
||||||
<string name="update_sticker_pack_heading">Paquete de etiqueta actualización</string>
|
<string name="update_sticker_pack_heading">Paquete de etiqueta actualización</string>
|
||||||
<string name="update_sticker_pack_button">Elija el directorio de fuente de la etiqueta</string>
|
<string name="update_sticker_pack_button">Elija el directorio de fuente de la etiqueta</string>
|
||||||
@ -21,11 +22,12 @@
|
|||||||
<!-- Features -->
|
<!-- Features -->
|
||||||
<string name="features_heading">Características</string>
|
<string name="features_heading">Características</string>
|
||||||
<string name="features_text">"- Amplia gama de pegatinas personalizadas admitidas
|
<string name="features_text">"- Amplia gama de pegatinas personalizadas admitidas
|
||||||
- Los formatos admitidos son image/gif (.gif), image/png (.png), image/webp (.webp), image/jpg (.jpg, .jpeg, .jpe, ...), image/heif (.heif,.heifs, .heic, ...)
|
- Los formatos admitidos son image/gif (.gif), image/png (.png), image/webp (.webp), image/jpg (.jpg, .jpeg, .jpe, …), image/heif (.heif,.heifs, .heic, …)
|
||||||
- Envíe stickers en las aplicaciones compatibles (.png se utiliza como alternativa)
|
- Envíe stickers en las aplicaciones compatibles (.png se utiliza como alternativa)
|
||||||
- Desplazamiento vertical y horizontal.
|
- Desplazamiento vertical y horizontal.
|
||||||
- Cambio Número de filas y tamaño de vista previa de la etiqueta
|
- Cambio Número de filas y tamaño de vista previa de la etiqueta
|
||||||
- Se ajusta al tema del sistema.</string>
|
- Se ajusta al tema del sistema.
|
||||||
|
- Pulse larga en una etiqueta para mostrar una vista previa.</string>
|
||||||
<!-- How to use -->
|
<!-- How to use -->
|
||||||
<string name="how_to_use_heading">Cómo utilizar</string>
|
<string name="how_to_use_heading">Cómo utilizar</string>
|
||||||
<string name="how_to_use_text">Selecciona un directorio que contenga pegatinas y envíalas en tus aplicaciones favoritas.</string>
|
<string name="how_to_use_text">Selecciona un directorio que contenga pegatinas y envíalas en tus aplicaciones favoritas.</string>
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
<string name="app_name" translatable="false">EweSticker</string>
|
<string name="app_name" translatable="false">EweSticker</string>
|
||||||
<string name="pack_icon">Pack icon</string>
|
<string name="pack_icon">Pack icon</string>
|
||||||
<string name="sticker_icon">Sticker icon</string>
|
<string name="sticker_icon">Sticker icon</string>
|
||||||
|
<string name="close_sticker_preview">[tap to close sticker preview]</string>
|
||||||
<!-- Update Sticker Pack -->
|
<!-- Update Sticker Pack -->
|
||||||
<string name="update_sticker_pack_heading">Update Sticker Pack</string>
|
<string name="update_sticker_pack_heading">Update Sticker Pack</string>
|
||||||
<string name="update_sticker_pack_button">Choose sticker source directory</string>
|
<string name="update_sticker_pack_button">Choose sticker source directory</string>
|
||||||
@ -26,7 +27,8 @@
|
|||||||
- Send stickers in supported apps (.png is used as a fallback)
|
- Send stickers in supported apps (.png is used as a fallback)
|
||||||
- Vertical and Horizontal scrolling
|
- Vertical and Horizontal scrolling
|
||||||
- Change number of rows and sticker preview size
|
- Change number of rows and sticker preview size
|
||||||
- Ties in with the system theme</string>
|
- Ties in with the system theme
|
||||||
|
- Long press on a sticker to show a preview</string>
|
||||||
<!-- How to use -->
|
<!-- How to use -->
|
||||||
<string name="how_to_use_heading">How to Use</string>
|
<string name="how_to_use_heading">How to Use</string>
|
||||||
<string name="how_to_use_text">Select a directory containing stickers and send them in your favourite apps!</string>
|
<string name="how_to_use_text">Select a directory containing stickers and send them in your favourite apps!</string>
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
<item name="actionOverflowButtonStyle">@style/OverflowButtonStyle</item>
|
<item name="actionOverflowButtonStyle">@style/OverflowButtonStyle</item>
|
||||||
<item name="actionBarStyle">@style/AppBarBackground</item>
|
<item name="actionBarStyle">@style/AppBarBackground</item>
|
||||||
<item name="actionBarTheme">@style/AppBarText</item>
|
<item name="actionBarTheme">@style/AppBarText</item>
|
||||||
<item name="android:fontFamily">@font/firasans_nf_bold</item>
|
<item name="android:fontFamily">@font/firasans_bold</item>
|
||||||
<item name="colorSurface">@color/sticker</item>
|
<item name="colorSurface">@color/sticker</item>
|
||||||
<item name="colorOnSurface">@color/fg</item>
|
<item name="colorOnSurface">@color/fg</item>
|
||||||
<item name="shapeAppearanceMediumComponent">@style/ShapeAppearance.App.MediumComponent
|
<item name="shapeAppearanceMediumComponent">@style/ShapeAppearance.App.MediumComponent
|
||||||
@ -33,7 +33,7 @@
|
|||||||
<style name="Widget.App.Snackbar.TextView" parent="Widget.MaterialComponents.Snackbar.TextView">
|
<style name="Widget.App.Snackbar.TextView" parent="Widget.MaterialComponents.Snackbar.TextView">
|
||||||
<item name="android:textColor">@color/onAccent</item>
|
<item name="android:textColor">@color/onAccent</item>
|
||||||
<item name="android:textSize">@dimen/text_size_body</item>
|
<item name="android:textSize">@dimen/text_size_body</item>
|
||||||
<item name="android:fontFamily">@font/firasans_nf</item>
|
<item name="android:fontFamily">@font/firasans</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="ThemeOverlay.App.Snackbar" parent="">
|
<style name="ThemeOverlay.App.Snackbar" parent="">
|
||||||
@ -78,7 +78,8 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="body_text" parent="widget">
|
<style name="body_text" parent="widget">
|
||||||
<item name="android:fontFamily">@font/firasans_nf</item>
|
<item name="android:textColor">@color/fg</item>
|
||||||
|
<item name="android:fontFamily">@font/firasans</item>
|
||||||
<item name="android:textSize">@dimen/text_size_body</item>
|
<item name="android:textSize">@dimen/text_size_body</item>
|
||||||
<item name="android:layout_width">wrap_content</item>
|
<item name="android:layout_width">wrap_content</item>
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user