Long press on a sticker to show a preview + Update fonts

This commit is contained in:
Kieran BW 2021-10-29 20:18:54 +01:00
parent a20cb26360
commit df71ab1254
13 changed files with 89 additions and 66 deletions

View File

@ -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
- Add support for vertical scroll https://github.com/FredHappyface/Android.EweSticker/issues/8
- 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 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)
- Update UI (now more material you inspired)
- Update screenshots
- Update tutorial
- Update fonts (using fira sans ttf)
## 20211011 - 2021/10/11

View File

@ -47,6 +47,7 @@ Sticker-board for android inspired by uSticker (forked from woosticker).
- Vertical and Horizontal scrolling
- Change number of rows and sticker preview size
- Ties in with the system theme
- Long press on a sticker to show a preview
## Screenshots

View File

@ -12,6 +12,7 @@ import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.widget.FrameLayout
import android.widget.ImageButton
import android.widget.RelativeLayout
import android.widget.Toast
import androidx.core.content.FileProvider
import androidx.core.content.res.ResourcesCompat
@ -29,6 +30,7 @@ import java.io.FileOutputStream
import java.io.IOException
import java.util.*
import kotlin.collections.HashMap
import kotlin.math.min
/**
* ImageKeyboard class inherits from the InputMethodService class - provides the keyboard functionality
@ -42,17 +44,19 @@ class ImageKeyboard : InputMethodService() {
// shared pref
private lateinit var mSharedPreferences: SharedPreferences
private var mVertical = false
private var mKeyboardHeight = 0
private var mIconsPerColumn = 0
private var mIconSize = 0
private var mFullIconSize = 0
private var mCompatCache = Cache()
private var mRecentCache = Cache()
// Attributes
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
private lateinit var mKeyboardRoot: View
private lateinit var mKeyboardRoot: ViewGroup
private lateinit var mPackContent: ViewGroup
private lateinit var mPacksList: ViewGroup
@ -122,11 +126,13 @@ class ImageKeyboard : InputMethodService() {
mKeyboardRoot = keyboardLayout.findViewById(R.id.keyboardRoot)
mPacksList = keyboardLayout.findViewById(R.id.packsList)
mPackContent = keyboardLayout.findViewById(R.id.packContent)
mPackContent.layoutParams?.height = if (mVertical) {
mKeyboardHeight = if (mVertical) {
800
} else {
mIconSize * mIconsPerColumn + mTotalIconPadding
}
mPackContent.layoutParams?.height = mKeyboardHeight
mFullIconSize = (min(resources.displayMetrics.widthPixels, mKeyboardHeight) * 0.8).toInt()
createPackIcons()
return keyboardLayout
}
@ -147,14 +153,7 @@ class ImageKeyboard : InputMethodService() {
* @param restarting
*/
override fun onStartInput(info: EditorInfo?, restarting: Boolean) {
mSupportedMimes = Utils.getSupportedMimes()
val mimesToCheck = mSupportedMimes.keys.toTypedArray()
for (mimeToCheck in mimesToCheck) {
val mimeSupported = isCommitContentSupported(info, mSupportedMimes[mimeToCheck])
if (!mimeSupported) {
mSupportedMimes.remove(mimeToCheck)
}
}
mSupportedMimes = Utils.getSupportedMimes().filter { isCommitContentSupported(info, it) }
}
/**
@ -178,11 +177,10 @@ class ImageKeyboard : InputMethodService() {
*/
private fun doFallbackCommitContent(file: File) {
// PNG might not be supported
if (mSupportedMimes[".png"] == null) {
if ("image/png" !in mSupportedMimes) {
Toast.makeText(
applicationContext,
Utils.getFileExtension(file.name) +
" not supported here.", Toast.LENGTH_SHORT
file.extension + " not supported here.", Toast.LENGTH_SHORT
).show()
return
}
@ -307,16 +305,38 @@ class ImageKeyboard : InputMethodService() {
imgButton.layoutParams.width = mIconSize
imgButton.load(sticker)
imgButton.tag = sticker
imgButton.setOnClickListener { view: View ->
val file = view.tag as File
imgButton.setOnClickListener {
val file = it.tag as File
mRecentCache.add(file.absolutePath)
val stickerType = mSupportedMimes[Utils.getFileExtension(file.name)]
if (stickerType == null) {
val stickerType = Utils.getMimeType(file)
if (stickerType == null || stickerType !in mSupportedMimes) {
doFallbackCommitContent(file)
return@setOnClickListener
}
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)
}
return packContainer

View File

@ -120,9 +120,7 @@ class MainActivity : AppCompatActivity() {
* @return 1 if sticker imported successfully else 0
*/
private fun importSticker(sticker: DocumentFile, pack: String): Int {
if (sticker.isDirectory ||
!mSupportedMimes.keys.contains(Utils.getFileExtension(sticker.name))
) {
if (sticker.isDirectory || sticker.type !in mSupportedMimes) {
return 0
}
val destSticker = File(filesDir, "stickers/" + pack + sticker.name)
@ -255,6 +253,4 @@ class MainActivity : AppCompatActivity() {
Snackbar.LENGTH_SHORT
).show()
}
}

View File

@ -1,52 +1,28 @@
package com.fredhappyface.ewesticker
import android.webkit.MimeTypeMap
import java.io.File
/**
* Class to provide utils that are shared across ewesticker.
*/
object Utils {
/**
* @param name the File's name. Takes in a string here instead of a File because in certain
* places we have to use DocumentFile instead-- String name can be found by calling
* .getName() on both, but they are different classes.
* @return returns "." inclusive file extension.
* Get the mimetype of a File
*
* @param file File file to get the mimetype of
* @return String? Return the mimetype or none if it cannot be determined
*/
fun getFileExtension(name: String?): String {
if (name == null) {
return ""
}
val lastIndexOf = name.lastIndexOf(".")
return if (lastIndexOf == -1) {
""
} else name.substring(lastIndexOf)
fun getMimeType(file: File): String? {
return MimeTypeMap.getSingleton().getMimeTypeFromExtension(file.extension)
}
/**
* Needs to create a new HashMap on every call because shallow copies will cause issues between
* different input areas that support different media types.
* Return a MutableList of EweSticker Supported mimetypes
*
* @return HashMap of ewesticker-supported mimes. Keys are "." inclusive.
* @return MutableList of EweSticker Supported mimetypes
*/
fun getSupportedMimes(): MutableMap<String, String> {
val mimes = mutableMapOf(
".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
fun getSupportedMimes(): MutableList<String> {
return mutableListOf("image/gif", "image/png", "image/webp", "image/jpeg", "image/heif")
}
}

Binary file not shown.

Binary file not shown.

View 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>

View File

@ -2,6 +2,7 @@
<!-- App info -->
<string name="pack_icon">Icono del paquete</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 -->
<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>
@ -21,11 +22,12 @@
<!-- Features -->
<string name="features_heading">Características</string>
<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)
- Desplazamiento vertical y horizontal.
- 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 -->
<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>

View File

@ -3,6 +3,7 @@
<string name="app_name" translatable="false">EweSticker</string>
<string name="pack_icon">Pack icon</string>
<string name="sticker_icon">Sticker icon</string>
<string name="close_sticker_preview">[tap to close sticker preview]</string>
<!-- Update Sticker Pack -->
<string name="update_sticker_pack_heading">Update Sticker Pack</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)
- Vertical and Horizontal scrolling
- 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 -->
<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>

View File

@ -16,7 +16,7 @@
<item name="actionOverflowButtonStyle">@style/OverflowButtonStyle</item>
<item name="actionBarStyle">@style/AppBarBackground</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="colorOnSurface">@color/fg</item>
<item name="shapeAppearanceMediumComponent">@style/ShapeAppearance.App.MediumComponent
@ -33,7 +33,7 @@
<style name="Widget.App.Snackbar.TextView" parent="Widget.MaterialComponents.Snackbar.TextView">
<item name="android:textColor">@color/onAccent</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 name="ThemeOverlay.App.Snackbar" parent="">
@ -78,7 +78,8 @@
</style>
<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:layout_width">wrap_content</item>
</style>