20210810
2
.idea/deploymentTargetDropDown.xml
generated
@ -12,6 +12,6 @@
|
|||||||
</deviceKey>
|
</deviceKey>
|
||||||
</Target>
|
</Target>
|
||||||
</targetSelectedWithDropDown>
|
</targetSelectedWithDropDown>
|
||||||
<timeTargetWasSelectedWithDropDown value="2021-08-09T19:37:01.560785100Z" />
|
<timeTargetWasSelectedWithDropDown value="2021-08-10T19:32:45.536947900Z" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
3
.idea/misc.xml
generated
@ -5,6 +5,9 @@
|
|||||||
<map>
|
<map>
|
||||||
<entry key="..\:/Users/Dell/Documents/GitHub/Android.EweSticker/app/src/main/res/drawable/ic_chevron_left.xml" value="0.14635416666666667" />
|
<entry key="..\:/Users/Dell/Documents/GitHub/Android.EweSticker/app/src/main/res/drawable/ic_chevron_left.xml" value="0.14635416666666667" />
|
||||||
<entry key="..\:/Users/Dell/Documents/GitHub/Android.EweSticker/app/src/main/res/drawable/ic_clock.xml" value="0.14635416666666667" />
|
<entry key="..\:/Users/Dell/Documents/GitHub/Android.EweSticker/app/src/main/res/drawable/ic_clock.xml" value="0.14635416666666667" />
|
||||||
|
<entry key="..\:/Users/Dell/Documents/GitHub/Android.EweSticker/app/src/main/res/layout/image_container.xml" value="0.13020833333333334" />
|
||||||
|
<entry key="..\:/Users/Dell/Documents/GitHub/Android.EweSticker/app/src/main/res/layout/image_container_column.xml" value="0.13020833333333334" />
|
||||||
|
<entry key="..\:/Users/Dell/Documents/GitHub/Android.EweSticker/app/src/main/res/layout/keyboard_layout.xml" value="0.13020833333333334" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
10
CHANGELOG.md
@ -3,15 +3,17 @@ All major and minor version changes will be documented in this file. Details of
|
|||||||
patch-level version changes can be found in [commit messages](../../commits/master).
|
patch-level version changes can be found in [commit messages](../../commits/master).
|
||||||
|
|
||||||
|
|
||||||
|
## 20210810 - 2021/08/10
|
||||||
## (no version) - 2021/08/09
|
|
||||||
- Code optimisations
|
- Code optimisations
|
||||||
|
- Code clean-up
|
||||||
|
- Removed APNG animation due to memory leak
|
||||||
|
- Linting fixes
|
||||||
- Added caching functionality
|
- Added caching functionality
|
||||||
- to improve performance of fallback stickers
|
- to improve performance of fallback stickers
|
||||||
- to enable addition of recent list
|
- to enable addition of recent list
|
||||||
- Updated gradle
|
- to improve switching packs performance
|
||||||
|
- Updated gradle and deps
|
||||||
- Add recent icon
|
- Add recent icon
|
||||||
- (In progress ...) testing, cleanup
|
|
||||||
|
|
||||||
|
|
||||||
## 20210723 - 2021/07/23
|
## 20210723 - 2021/07/23
|
||||||
|
@ -11,8 +11,8 @@ android {
|
|||||||
applicationId "com.fredhappyface.ewesticker"
|
applicationId "com.fredhappyface.ewesticker"
|
||||||
minSdkVersion 28
|
minSdkVersion 28
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionCode 20210723
|
versionCode 20210810
|
||||||
versionName "2021.07.23"
|
versionName "2021.08.10"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
@ -39,14 +39,15 @@ android {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.5.21"
|
||||||
implementation 'androidx.core:core-ktx:1.5.0'
|
implementation 'androidx.core:core-ktx:1.6.0'
|
||||||
implementation 'androidx.appcompat:appcompat:1.3.0'
|
implementation "androidx.fragment:fragment-ktx"
|
||||||
implementation 'com.google.android.material:material:1.3.0'
|
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||||
|
implementation 'com.google.android.material:material:1.4.0'
|
||||||
implementation 'androidx.preference:preference-ktx:1.1.1'
|
implementation 'androidx.preference:preference-ktx:1.1.1'
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||||
|
|
||||||
implementation "com.github.penfeizhou.android.animation:apng:2.10.0"
|
//implementation "com.github.penfeizhou.android.animation:apng:2.11.0"
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,9 @@ import java.util.*
|
|||||||
* an element is removed from the start
|
* an element is removed from the start
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class Cache(size: Int = 30) {
|
class Cache(private val size: Int = 30) {
|
||||||
|
|
||||||
private var data: LinkedList<String> = LinkedList()
|
private var data: LinkedList<String> = LinkedList()
|
||||||
private val size = size
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logic to add an element
|
* Logic to add an element
|
||||||
@ -31,14 +30,6 @@ class Cache(size: Int = 30) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an element
|
|
||||||
*
|
|
||||||
* @param elem
|
|
||||||
*/
|
|
||||||
fun remove(elem: String) {
|
|
||||||
data.remove(elem)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an element
|
* Get an element
|
||||||
|
@ -7,13 +7,11 @@ import android.graphics.ImageDecoder
|
|||||||
import android.graphics.drawable.AnimatedImageDrawable
|
import android.graphics.drawable.AnimatedImageDrawable
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.inputmethodservice.InputMethodService
|
import android.inputmethodservice.InputMethodService
|
||||||
import android.util.Log
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.ImageButton
|
import android.widget.ImageButton
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.RelativeLayout
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.cardview.widget.CardView
|
import androidx.cardview.widget.CardView
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
@ -22,23 +20,24 @@ import androidx.core.view.inputmethod.EditorInfoCompat
|
|||||||
import androidx.core.view.inputmethod.InputConnectionCompat
|
import androidx.core.view.inputmethod.InputConnectionCompat
|
||||||
import androidx.core.view.inputmethod.InputContentInfoCompat
|
import androidx.core.view.inputmethod.InputContentInfoCompat
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.github.penfeizhou.animation.apng.APNGDrawable
|
//import com.github.penfeizhou.animation.apng.APNGDrawable
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.collections.HashMap
|
||||||
|
|
||||||
class ImageKeyboard : InputMethodService() {
|
class ImageKeyboard : InputMethodService() {
|
||||||
// Attributes
|
// Attributes
|
||||||
private lateinit var supportedMimes: MutableMap<String, String>
|
private lateinit var supportedMimes: MutableMap<String, String>
|
||||||
private var loadedPacks = HashMap<String, StickerPack>()
|
private var loadedPacks = HashMap<String, StickerPack>()
|
||||||
private var imageContainer: LinearLayout? = null
|
private lateinit var imageContainer: LinearLayout
|
||||||
private var packContainer: LinearLayout? = null
|
private lateinit var packContainer: LinearLayout
|
||||||
private lateinit var internalDir: File
|
private lateinit var internalDir: File
|
||||||
|
|
||||||
// SharedPref
|
// SharedPref
|
||||||
private lateinit var sharedPreferences: SharedPreferences
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
private var iconsPerRow = 0
|
private var iconsPerColumn = 0
|
||||||
private var iconSize = 0
|
private var iconSize = 0
|
||||||
private var disableAnimations = false
|
private var disableAnimations = false
|
||||||
|
|
||||||
@ -46,6 +45,9 @@ class ImageKeyboard : InputMethodService() {
|
|||||||
private var compatCache = Cache()
|
private var compatCache = Cache()
|
||||||
private var recentCache = Cache()
|
private var recentCache = Cache()
|
||||||
|
|
||||||
|
// Cache for image container
|
||||||
|
private var imageContainerCache = HashMap<Int, LinearLayout>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a back button as a PackCard to keyboard that shows the InputMethodPicker
|
* Adds a back button as a PackCard to keyboard that shows the InputMethodPicker
|
||||||
*/
|
*/
|
||||||
@ -59,7 +61,7 @@ class ImageKeyboard : InputMethodService() {
|
|||||||
.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
inputMethodManager.showInputMethodPicker()
|
inputMethodManager.showInputMethodPicker()
|
||||||
}
|
}
|
||||||
packContainer!!.addView(packCard)
|
packContainer.addView(packCard)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,11 +72,11 @@ class ImageKeyboard : InputMethodService() {
|
|||||||
val recentButton = packCard.findViewById<ImageButton>(R.id.ib3)
|
val recentButton = packCard.findViewById<ImageButton>(R.id.ib3)
|
||||||
val icon = ResourcesCompat.getDrawable(resources, R.drawable.ic_clock, null)
|
val icon = ResourcesCompat.getDrawable(resources, R.drawable.ic_clock, null)
|
||||||
recentButton.setImageDrawable(icon)
|
recentButton.setImageDrawable(icon)
|
||||||
recentButton.setOnClickListener { view: View ->
|
recentButton.setOnClickListener {
|
||||||
imageContainer!!.removeAllViewsInLayout()
|
imageContainer.removeAllViewsInLayout()
|
||||||
recreateImageContainer(recentCache.toFiles())
|
imageContainer.addView(createImageContainer(recentCache.toFiles()))
|
||||||
}
|
}
|
||||||
packContainer!!.addView(packCard)
|
packContainer.addView(packCard)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,10 +91,9 @@ class ImageKeyboard : InputMethodService() {
|
|||||||
setStickerButtonImage(pack.thumbSticker, packButton)
|
setStickerButtonImage(pack.thumbSticker, packButton)
|
||||||
packButton.tag = pack
|
packButton.tag = pack
|
||||||
packButton.setOnClickListener { view: View ->
|
packButton.setOnClickListener { view: View ->
|
||||||
imageContainer!!.removeAllViewsInLayout()
|
switchImageContainer((view.tag as StickerPack).stickerList)
|
||||||
recreateImageContainer((view.tag as StickerPack).stickerList)
|
|
||||||
}
|
}
|
||||||
packContainer!!.addView(packCard)
|
packContainer.addView(packCard)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -170,19 +171,19 @@ class ImageKeyboard : InputMethodService() {
|
|||||||
drawable = ImageDecoder.decodeDrawable(ImageDecoder.createSource(sticker))
|
drawable = ImageDecoder.decodeDrawable(ImageDecoder.createSource(sticker))
|
||||||
} catch (ignore: IOException) {
|
} catch (ignore: IOException) {
|
||||||
}
|
}
|
||||||
if (sName.contains(".png") || sName.contains(".apng")) {
|
//if (sName.contains(".png") || sName.contains(".apng")) {
|
||||||
drawable = APNGDrawable.fromFile(sticker.absolutePath)
|
// drawable = APNGDrawable.fromFile(sticker.absolutePath)
|
||||||
drawable!!.setAutoPlay(false)
|
// drawable!!.setAutoPlay(false)
|
||||||
drawable.start()
|
// drawable.start()
|
||||||
}
|
//}
|
||||||
// Disable animations?
|
// Disable animations?
|
||||||
if (drawable is AnimatedImageDrawable && !disableAnimations
|
if (drawable is AnimatedImageDrawable && !disableAnimations
|
||||||
) {
|
) {
|
||||||
drawable.start()
|
drawable.start()
|
||||||
}
|
}
|
||||||
if (drawable is APNGDrawable && disableAnimations) {
|
//if (drawable is APNGDrawable && disableAnimations) {
|
||||||
drawable.stop()
|
// drawable.stop()
|
||||||
}
|
//}
|
||||||
// Apply
|
// Apply
|
||||||
btn.setImageDrawable(drawable)
|
btn.setImageDrawable(drawable)
|
||||||
}
|
}
|
||||||
@ -215,14 +216,14 @@ class ImageKeyboard : InputMethodService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When the activity is crated, grab the number of icons per row and the configured icon size
|
* When the activity is crated, grab the number of icons per column and the configured icon size
|
||||||
* before reloading the packs
|
* before reloading the packs
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(baseContext)
|
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(baseContext)
|
||||||
iconsPerRow = sharedPreferences.getInt("iconsPerRow", 3)
|
iconsPerColumn = sharedPreferences.getInt("iconsPerColumn", 3)
|
||||||
iconSize = sharedPreferences.getInt("iconSize", 160)
|
iconSize = sharedPreferences.getInt("iconSize", 160)
|
||||||
disableAnimations = sharedPreferences.getBoolean(
|
disableAnimations = sharedPreferences.getBoolean(
|
||||||
"disableAnimations",
|
"disableAnimations",
|
||||||
@ -234,19 +235,28 @@ class ImageKeyboard : InputMethodService() {
|
|||||||
reloadPacks()
|
reloadPacks()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the keyboard is first drawn
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
override fun onCreateInputView(): View {
|
override fun onCreateInputView(): View {
|
||||||
val keyboardLayout =
|
val keyboardLayout =
|
||||||
layoutInflater.inflate(R.layout.keyboard_layout, null) as RelativeLayout
|
View.inflate(applicationContext, R.layout.keyboard_layout, null)
|
||||||
packContainer = keyboardLayout.findViewById(R.id.packContainer)
|
packContainer = keyboardLayout.findViewById(R.id.packContainer)
|
||||||
imageContainer = keyboardLayout.findViewById(R.id.imageContainer)
|
imageContainer = keyboardLayout.findViewById(R.id.imageContainer)
|
||||||
imageContainer?.layoutParams?.height = (iconSize * iconsPerRow * 1.4).toInt()
|
imageContainer.layoutParams?.height = (iconSize * iconsPerColumn * 1.4).toInt()
|
||||||
recreatePackContainer()
|
recreatePackContainer()
|
||||||
return keyboardLayout
|
return keyboardLayout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In full-screen mode the inserted content is likely to be hidden by the IME. Hence in this
|
||||||
|
* sample we simply disable full-screen mode.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
override fun onEvaluateFullscreenMode(): Boolean {
|
override fun onEvaluateFullscreenMode(): Boolean {
|
||||||
// In full-screen mode the inserted content is likely to be hidden by the IME. Hence in this
|
|
||||||
// sample we simply disable full-screen mode.
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,27 +277,45 @@ class ImageKeyboard : InputMethodService() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swap the image container every time a new pack is selected. If already cached use that otherwise create
|
||||||
|
*
|
||||||
|
* @param stickers
|
||||||
|
*/
|
||||||
|
private fun switchImageContainer(stickers: Array<File>) {
|
||||||
|
// Check the cache
|
||||||
|
val imageContainerHash = stickers.hashCode()
|
||||||
|
lateinit var imageContainerLayout: LinearLayout
|
||||||
|
if (imageContainerHash !in imageContainerCache.keys) {
|
||||||
|
imageContainerLayout = createImageContainer(stickers)
|
||||||
|
imageContainerCache[imageContainerHash] = createImageContainer(stickers)
|
||||||
|
} else {
|
||||||
|
imageContainerLayout = imageContainerCache[imageContainerHash]!!
|
||||||
|
}
|
||||||
|
// Swap the image container
|
||||||
|
imageContainer.removeAllViews()
|
||||||
|
imageContainer.addView(imageContainerLayout)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recreate the image container every time a new pack is selected
|
* Recreate the image container every time a new pack is selected
|
||||||
*
|
*
|
||||||
* @param pack
|
* @param stickers
|
||||||
*/
|
*/
|
||||||
private fun recreateImageContainer(stickers: Array<File>) {
|
private fun createImageContainer(stickers: Array<File>): LinearLayout {
|
||||||
// Clear the image view
|
val tempImageContainer =
|
||||||
imageContainer!!.removeAllViewsInLayout()
|
View.inflate(applicationContext, R.layout.image_container, null) as LinearLayout
|
||||||
// And rebuild...
|
lateinit var imageContainerColumn: LinearLayout
|
||||||
var imageContainerColumn = layoutInflater.inflate(
|
|
||||||
R.layout.image_container_column,
|
|
||||||
imageContainer,
|
|
||||||
false
|
|
||||||
) as LinearLayout
|
|
||||||
for (i in stickers.indices) {
|
for (i in stickers.indices) {
|
||||||
if (i % iconsPerRow == 0) {
|
// Add a new column
|
||||||
|
if (i % iconsPerColumn == 0) {
|
||||||
imageContainerColumn = layoutInflater.inflate(
|
imageContainerColumn = layoutInflater.inflate(
|
||||||
R.layout.image_container_column,
|
R.layout.image_container_column,
|
||||||
imageContainer,
|
tempImageContainer,
|
||||||
false
|
false
|
||||||
) as LinearLayout
|
) as LinearLayout
|
||||||
|
tempImageContainer.addView(imageContainerColumn)
|
||||||
}
|
}
|
||||||
val imageCard = layoutInflater.inflate(
|
val imageCard = layoutInflater.inflate(
|
||||||
R.layout.sticker_card,
|
R.layout.sticker_card,
|
||||||
@ -302,7 +330,6 @@ class ImageKeyboard : InputMethodService() {
|
|||||||
imgButton.setOnClickListener { view: View ->
|
imgButton.setOnClickListener { view: View ->
|
||||||
val file = view.tag as File
|
val file = view.tag as File
|
||||||
recentCache.add(file.absolutePath)
|
recentCache.add(file.absolutePath)
|
||||||
Log.e("qwerty", recentCache.toSharedPref() )
|
|
||||||
val stickerType = supportedMimes[Utils.getFileExtension(file.name)]
|
val stickerType = supportedMimes[Utils.getFileExtension(file.name)]
|
||||||
if (stickerType == null) {
|
if (stickerType == null) {
|
||||||
// Sticker is unsupported by input
|
// Sticker is unsupported by input
|
||||||
@ -312,10 +339,8 @@ class ImageKeyboard : InputMethodService() {
|
|||||||
doCommitContent(file.name, stickerType, file)
|
doCommitContent(file.name, stickerType, file)
|
||||||
}
|
}
|
||||||
imageContainerColumn.addView(imageCard)
|
imageContainerColumn.addView(imageCard)
|
||||||
if (i % iconsPerRow == 0) {
|
|
||||||
imageContainer!!.addView(imageContainerColumn)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return tempImageContainer
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -323,7 +348,7 @@ class ImageKeyboard : InputMethodService() {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private fun recreatePackContainer() {
|
private fun recreatePackContainer() {
|
||||||
packContainer!!.removeAllViewsInLayout()
|
packContainer.removeAllViewsInLayout()
|
||||||
// Back button
|
// Back button
|
||||||
if (sharedPreferences.getBoolean("showBackButton", false)) {
|
if (sharedPreferences.getBoolean("showBackButton", false)) {
|
||||||
addBackButtonToContainer()
|
addBackButtonToContainer()
|
||||||
@ -338,7 +363,7 @@ class ImageKeyboard : InputMethodService() {
|
|||||||
addPackToContainer(loadedPacks[sortedPackName]!!)
|
addPackToContainer(loadedPacks[sortedPackName]!!)
|
||||||
}
|
}
|
||||||
if (sortedPackNames.isNotEmpty()) {
|
if (sortedPackNames.isNotEmpty()) {
|
||||||
recreateImageContainer(loadedPacks[sortedPackNames[0]]!!.stickerList)
|
switchImageContainer(loadedPacks[sortedPackNames[0]]!!.stickerList)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,18 +189,18 @@ class MainActivity : AppCompatActivity() {
|
|||||||
editor.putBoolean("disableAnimations", isChecked)
|
editor.putBoolean("disableAnimations", isChecked)
|
||||||
editor.apply()
|
editor.apply()
|
||||||
}
|
}
|
||||||
val iconsPerRowSeekBar = findViewById<SeekBar>(R.id.iconsPerRowSeekBar)
|
val iconsPerColumnSeekBar = findViewById<SeekBar>(R.id.iconsPerColumnSeekBar)
|
||||||
iconsPerRowSeekBar.progress = sharedPreferences.getInt("iconsPerRow", 3)
|
iconsPerColumnSeekBar.progress = sharedPreferences.getInt("iconsPerColumn", 3)
|
||||||
iconsPerRowSeekBar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
|
iconsPerColumnSeekBar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
|
||||||
var iconsPerRow = 3
|
var iconsPerColumn = 3
|
||||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||||
iconsPerRow = progress
|
iconsPerColumn = progress
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStartTrackingTouch(seekBar: SeekBar) {}
|
override fun onStartTrackingTouch(seekBar: SeekBar) {}
|
||||||
override fun onStopTrackingTouch(seekBar: SeekBar) {
|
override fun onStopTrackingTouch(seekBar: SeekBar) {
|
||||||
val editor = sharedPreferences.edit()
|
val editor = sharedPreferences.edit()
|
||||||
editor.putInt("iconsPerRow", iconsPerRow)
|
editor.putInt("iconsPerColumn", iconsPerColumn)
|
||||||
editor.apply()
|
editor.apply()
|
||||||
refreshKeyboardConfig()
|
refreshKeyboardConfig()
|
||||||
showChangedPrefText()
|
showChangedPrefText()
|
||||||
@ -229,9 +229,9 @@ class MainActivity : AppCompatActivity() {
|
|||||||
* Refreshes config from preferences
|
* Refreshes config from preferences
|
||||||
*/
|
*/
|
||||||
fun refreshKeyboardConfig() {
|
fun refreshKeyboardConfig() {
|
||||||
val iconsPerRow = sharedPreferences.getInt("iconsPerRow", 3)
|
val iconsPerColumn = sharedPreferences.getInt("iconsPerColumn", 3)
|
||||||
val iconsPerRowValue = findViewById<TextView>(R.id.iconsPerRowValue)
|
val iconsPerColumnValue = findViewById<TextView>(R.id.iconsPerColumnValue)
|
||||||
iconsPerRowValue.text = iconsPerRow.toString()
|
iconsPerColumnValue.text = iconsPerColumn.toString()
|
||||||
val iconSize = sharedPreferences.getInt("iconSize", 160)
|
val iconSize = sharedPreferences.getInt("iconSize", 160)
|
||||||
val iconSizeValue = findViewById<TextView>(R.id.iconSizeValue)
|
val iconSizeValue = findViewById<TextView>(R.id.iconSizeValue)
|
||||||
iconSizeValue.text = String.format("%dpx", iconSize)
|
iconSizeValue.text = String.format("%dpx", iconSize)
|
||||||
|
@ -102,14 +102,14 @@
|
|||||||
android:text="@string/icons_per_row_status" />
|
android:text="@string/icons_per_row_status" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/iconsPerRowValue"
|
android:id="@+id/iconsPerColumnValue"
|
||||||
style="@style/body_text"
|
style="@style/body_text"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textIsSelectable="false" />
|
android:textIsSelectable="false" />
|
||||||
|
|
||||||
<SeekBar
|
<SeekBar
|
||||||
android:id="@+id/iconsPerRowSeekBar"
|
android:id="@+id/iconsPerColumnSeekBar"
|
||||||
style="@style/body_text"
|
style="@style/body_text"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -187,6 +187,3 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
7
app/src/main/res/layout/image_container.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:orientation="horizontal" />
|
||||||
|
|
@ -13,7 +13,7 @@
|
|||||||
<string name="sub_options"> Options</string>
|
<string name="sub_options"> Options</string>
|
||||||
<string name="show_back_button">Show back button in navbar?</string>
|
<string name="show_back_button">Show back button in navbar?</string>
|
||||||
<string name="disable_animations">Disable Animations?</string>
|
<string name="disable_animations">Disable Animations?</string>
|
||||||
<string name="icons_per_row_status">"Icons per row: "</string>
|
<string name="icons_per_row_status">"Icons per column: "</string>
|
||||||
<string name="icon_size_status">"Icon size: "</string>
|
<string name="icon_size_status">"Icon size: "</string>
|
||||||
|
|
||||||
<!-- About -->
|
<!-- About -->
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = "1.5.10"
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.0.0'
|
classpath 'com.android.tools.build:gradle:7.0.0'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21"
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
16
metadata/en-US/changelogs/20210810.txt
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<ul>
|
||||||
|
<li>Code optimisations
|
||||||
|
<ul>
|
||||||
|
<li>Code clean-up</li>
|
||||||
|
<li>Removed APNG animation due to memory leak</li>
|
||||||
|
<li>Linting fixes</li>
|
||||||
|
</ul></li>
|
||||||
|
<li>Added caching functionality
|
||||||
|
<ul>
|
||||||
|
<li>to improve performance of fallback stickers</li>
|
||||||
|
<li>to enable addition of recent list</li>
|
||||||
|
<li>to improve switching packs performance</li>
|
||||||
|
</ul></li>
|
||||||
|
<li>Updated gradle and deps</li>
|
||||||
|
<li>Add recent icon</li>
|
||||||
|
</ul>
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 126 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 191 KiB |