Merge pull request #232 from esensar/feature/229-emoji-categories
Add emoji categories to emoji list
This commit is contained in:
commit
25918d4660
16 changed files with 232 additions and 22 deletions
|
@ -6,39 +6,72 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.emoji2.text.EmojiCompat
|
import androidx.emoji2.text.EmojiCompat
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.simplemobiletools.commons.databinding.DividerBinding
|
||||||
|
import com.simplemobiletools.commons.extensions.beInvisible
|
||||||
import com.simplemobiletools.keyboard.databinding.ItemEmojiBinding
|
import com.simplemobiletools.keyboard.databinding.ItemEmojiBinding
|
||||||
|
import com.simplemobiletools.keyboard.helpers.EmojiData
|
||||||
|
|
||||||
class EmojisAdapter(val context: Context, var items: List<String>, val itemClick: (emoji: String) -> Unit) : RecyclerView.Adapter<EmojisAdapter.ViewHolder>() {
|
class EmojisAdapter(val context: Context, private val items: List<Item>, val itemClick: (emoji: EmojiData) -> Unit) :
|
||||||
|
RecyclerView.Adapter<EmojisAdapter.ViewHolder>() {
|
||||||
private val layoutInflater = LayoutInflater.from(context)
|
private val layoutInflater = LayoutInflater.from(context)
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EmojisAdapter.ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EmojisAdapter.ViewHolder {
|
||||||
|
return when (viewType) {
|
||||||
|
ITEM_TYPE_EMOJI -> {
|
||||||
val view = ItemEmojiBinding.inflate(layoutInflater, parent, false).root
|
val view = ItemEmojiBinding.inflate(layoutInflater, parent, false).root
|
||||||
return ViewHolder(view)
|
ViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
val view = DividerBinding.inflate(layoutInflater, parent, false).root.apply { beInvisible() }
|
||||||
|
ViewHolder(view)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: EmojisAdapter.ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: EmojisAdapter.ViewHolder, position: Int) {
|
||||||
val item = items[position]
|
val item = items[position]
|
||||||
|
if (item is Item.Emoji) {
|
||||||
holder.bindView(item) { itemView ->
|
holder.bindView(item) { itemView ->
|
||||||
setupEmoji(itemView, item)
|
setupEmoji(itemView, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemViewType(position: Int): Int {
|
||||||
|
return if (items[position] is Item.Emoji) {
|
||||||
|
ITEM_TYPE_EMOJI
|
||||||
|
} else {
|
||||||
|
ITEM_TYPE_CATEGORY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun getItemCount() = items.size
|
override fun getItemCount() = items.size
|
||||||
|
|
||||||
private fun setupEmoji(view: View, emoji: String) {
|
private fun setupEmoji(view: View, emoji: Item.Emoji) {
|
||||||
val processed = EmojiCompat.get().process(emoji)
|
val processed = EmojiCompat.get().process(emoji.value.emoji)
|
||||||
ItemEmojiBinding.bind(view).emojiValue.text = processed
|
ItemEmojiBinding.bind(view).emojiValue.text = processed
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
fun bindView(emoji: String, callback: (itemView: View) -> Unit): View {
|
fun bindView(emoji: Item.Emoji, callback: (itemView: View) -> Unit): View {
|
||||||
return itemView.apply {
|
return itemView.apply {
|
||||||
callback(this)
|
callback(this)
|
||||||
|
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
itemClick.invoke(emoji)
|
itemClick.invoke(emoji.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed interface Item {
|
||||||
|
data class Emoji(val value: EmojiData) : Item
|
||||||
|
data class Category(val value: String) : Item
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val ITEM_TYPE_EMOJI = 0
|
||||||
|
private const val ITEM_TYPE_CATEGORY = 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
package com.simplemobiletools.keyboard.helpers
|
package com.simplemobiletools.keyboard.helpers
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import com.simplemobiletools.keyboard.R
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
private var cachedEmojiData: MutableList<String>? = null
|
private var cachedEmojiData: MutableList<EmojiData>? = null
|
||||||
val cachedVNTelexData: HashMap<String, String> = HashMap()
|
val cachedVNTelexData: HashMap<String, String> = HashMap()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,18 +15,21 @@ val cachedVNTelexData: HashMap<String, String> = HashMap()
|
||||||
* @param context The initiating view's context.
|
* @param context The initiating view's context.
|
||||||
* @param path The path to the asset file.
|
* @param path The path to the asset file.
|
||||||
*/
|
*/
|
||||||
fun parseRawEmojiSpecsFile(context: Context, path: String): MutableList<String> {
|
fun parseRawEmojiSpecsFile(context: Context, path: String): MutableList<EmojiData> {
|
||||||
if (cachedEmojiData != null) {
|
if (cachedEmojiData != null) {
|
||||||
return cachedEmojiData!!
|
return cachedEmojiData!!
|
||||||
}
|
}
|
||||||
|
|
||||||
val emojis = mutableListOf<String>()
|
val emojis = mutableListOf<EmojiData>()
|
||||||
var emojiEditorList: MutableList<String>? = null
|
var emojiEditorList: MutableList<String>? = null
|
||||||
|
var category: String? = null
|
||||||
|
|
||||||
fun commitEmojiEditorList() {
|
fun commitEmojiEditorList() {
|
||||||
emojiEditorList?.let {
|
emojiEditorList?.let {
|
||||||
// add only the base emoji for now, ignore the variations
|
// add only the base emoji for now, ignore the variations
|
||||||
emojis.add(it.first())
|
val base = it.first()
|
||||||
|
val variants = it.drop(1)
|
||||||
|
emojis.add(EmojiData(category ?: "none", base, variants))
|
||||||
}
|
}
|
||||||
emojiEditorList = null
|
emojiEditorList = null
|
||||||
}
|
}
|
||||||
|
@ -36,6 +40,7 @@ fun parseRawEmojiSpecsFile(context: Context, path: String): MutableList<String>
|
||||||
// Comment line
|
// Comment line
|
||||||
} else if (line.startsWith("[")) {
|
} else if (line.startsWith("[")) {
|
||||||
commitEmojiEditorList()
|
commitEmojiEditorList()
|
||||||
|
category = line.replace("[", "").replace("]", "")
|
||||||
} else if (line.trim().isEmpty()) {
|
} else if (line.trim().isEmpty()) {
|
||||||
// Empty line
|
// Empty line
|
||||||
continue
|
continue
|
||||||
|
@ -84,3 +89,22 @@ fun parseRawJsonSpecsFile(context: Context, path: String): HashMap<String, Strin
|
||||||
}
|
}
|
||||||
return cachedVNTelexData
|
return cachedVNTelexData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class EmojiData(
|
||||||
|
val category: String,
|
||||||
|
val emoji: String,
|
||||||
|
val variants: List<String>
|
||||||
|
) {
|
||||||
|
fun getCategoryIcon(): Int =
|
||||||
|
when (category) {
|
||||||
|
"people_body" -> R.drawable.ic_emoji_category_people
|
||||||
|
"animals_nature" -> R.drawable.ic_emoji_category_animals
|
||||||
|
"food_drink" -> R.drawable.ic_emoji_category_food
|
||||||
|
"travel_places" -> R.drawable.ic_emoji_category_travel
|
||||||
|
"activities" -> R.drawable.ic_emoji_category_activities
|
||||||
|
"objects" -> R.drawable.ic_emoji_category_objects
|
||||||
|
"symbols" -> R.drawable.ic_emoji_category_symbols
|
||||||
|
"flags" -> R.drawable.ic_emoji_category_flags
|
||||||
|
else -> R.drawable.ic_emoji_category_smileys
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import android.content.ClipData
|
||||||
import android.content.ClipboardManager
|
import android.content.ClipboardManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.res.ColorStateList
|
||||||
import android.graphics.*
|
import android.graphics.*
|
||||||
import android.graphics.Paint.Align
|
import android.graphics.Paint.Align
|
||||||
import android.graphics.drawable.*
|
import android.graphics.drawable.*
|
||||||
|
@ -19,6 +20,7 @@ import android.util.TypedValue
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.view.animation.AccelerateInterpolator
|
import android.view.animation.AccelerateInterpolator
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
|
import android.widget.ImageButton
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.PopupWindow
|
import android.widget.PopupWindow
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
@ -29,6 +31,9 @@ import androidx.core.animation.doOnStart
|
||||||
import androidx.core.view.*
|
import androidx.core.view.*
|
||||||
import androidx.emoji2.text.EmojiCompat
|
import androidx.emoji2.text.EmojiCompat
|
||||||
import androidx.emoji2.text.EmojiCompat.EMOJI_SUPPORTED
|
import androidx.emoji2.text.EmojiCompat.EMOJI_SUPPORTED
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.simplemobiletools.commons.extensions.*
|
import com.simplemobiletools.commons.extensions.*
|
||||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||||
import com.simplemobiletools.commons.helpers.isPiePlus
|
import com.simplemobiletools.commons.helpers.isPiePlus
|
||||||
|
@ -37,6 +42,7 @@ import com.simplemobiletools.keyboard.activities.ManageClipboardItemsActivity
|
||||||
import com.simplemobiletools.keyboard.activities.SettingsActivity
|
import com.simplemobiletools.keyboard.activities.SettingsActivity
|
||||||
import com.simplemobiletools.keyboard.adapters.ClipsKeyboardAdapter
|
import com.simplemobiletools.keyboard.adapters.ClipsKeyboardAdapter
|
||||||
import com.simplemobiletools.keyboard.adapters.EmojisAdapter
|
import com.simplemobiletools.keyboard.adapters.EmojisAdapter
|
||||||
|
import com.simplemobiletools.keyboard.databinding.ItemEmojiCategoryBinding
|
||||||
import com.simplemobiletools.keyboard.databinding.KeyboardKeyPreviewBinding
|
import com.simplemobiletools.keyboard.databinding.KeyboardKeyPreviewBinding
|
||||||
import com.simplemobiletools.keyboard.databinding.KeyboardPopupKeyboardBinding
|
import com.simplemobiletools.keyboard.databinding.KeyboardPopupKeyboardBinding
|
||||||
import com.simplemobiletools.keyboard.databinding.KeyboardViewKeyboardBinding
|
import com.simplemobiletools.keyboard.databinding.KeyboardViewKeyboardBinding
|
||||||
|
@ -1468,9 +1474,8 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||||
emojiPaletteLabel.setTextColor(textColor)
|
emojiPaletteLabel.setTextColor(textColor)
|
||||||
|
|
||||||
emojiPaletteBottomBar.background = ColorDrawable(backgroundColor)
|
emojiPaletteBottomBar.background = ColorDrawable(backgroundColor)
|
||||||
val bottomTextColor = textColor.darkenColor()
|
|
||||||
emojiPaletteModeChange.apply {
|
emojiPaletteModeChange.apply {
|
||||||
setTextColor(bottomTextColor)
|
setTextColor(textColor)
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
vibrateIfNeeded()
|
vibrateIfNeeded()
|
||||||
closeEmojiPalette()
|
closeEmojiPalette()
|
||||||
|
@ -1478,7 +1483,7 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||||
}
|
}
|
||||||
|
|
||||||
emojiPaletteBackspace.apply {
|
emojiPaletteBackspace.apply {
|
||||||
applyColorFilter(bottomTextColor)
|
applyColorFilter(textColor)
|
||||||
setOnTouchListener { _, event ->
|
setOnTouchListener { _, event ->
|
||||||
when (event.action) {
|
when (event.action) {
|
||||||
MotionEvent.ACTION_DOWN -> {
|
MotionEvent.ACTION_DOWN -> {
|
||||||
|
@ -1529,8 +1534,8 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||||
}
|
}
|
||||||
|
|
||||||
val emojis = fullEmojiList.filter { emoji ->
|
val emojis = fullEmojiList.filter { emoji ->
|
||||||
systemFontPaint.hasGlyph(emoji) || (EmojiCompat.get().loadState == EmojiCompat.LOAD_STATE_SUCCEEDED && EmojiCompat.get()
|
systemFontPaint.hasGlyph(emoji.emoji) || (EmojiCompat.get().loadState == EmojiCompat.LOAD_STATE_SUCCEEDED && EmojiCompat.get()
|
||||||
.getEmojiMatch(emoji, emojiCompatMetadataVersion) == EMOJI_SUPPORTED)
|
.getEmojiMatch(emoji.emoji, emojiCompatMetadataVersion) == EMOJI_SUPPORTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
Handler(Looper.getMainLooper()).post {
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
@ -1546,19 +1551,80 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupEmojiAdapter(emojis: List<String>) {
|
private fun setupEmojiAdapter(emojis: List<EmojiData>) {
|
||||||
|
val categories = emojis.groupBy { it.category }
|
||||||
|
val allItems = mutableListOf<EmojisAdapter.Item>()
|
||||||
|
categories.entries.forEach { (category, emojis) ->
|
||||||
|
allItems.add(EmojisAdapter.Item.Category(category))
|
||||||
|
allItems.addAll(emojis.map(EmojisAdapter.Item::Emoji))
|
||||||
|
}
|
||||||
|
val checkIds = mutableMapOf<Int, String>()
|
||||||
|
keyboardViewBinding?.emojiCategoriesStrip?.apply {
|
||||||
|
weightSum = categories.count().toFloat()
|
||||||
|
val strip = this
|
||||||
|
removeAllViews()
|
||||||
|
categories.entries.forEach { (category, emojis) ->
|
||||||
|
ItemEmojiCategoryBinding.inflate(LayoutInflater.from(context), this, true).apply {
|
||||||
|
root.id = generateViewId()
|
||||||
|
checkIds[root.id] = category
|
||||||
|
root.setImageResource(emojis.first().getCategoryIcon())
|
||||||
|
root.layoutParams = LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
1f
|
||||||
|
)
|
||||||
|
root.setOnClickListener {
|
||||||
|
strip.children.filterIsInstance<ImageButton>().forEach {
|
||||||
|
it.imageTintList = ColorStateList.valueOf(mTextColor)
|
||||||
|
}
|
||||||
|
root.imageTintList = ColorStateList.valueOf(context.getProperPrimaryColor())
|
||||||
|
keyboardViewBinding?.emojisList?.stopScroll()
|
||||||
|
(keyboardViewBinding?.emojisList?.layoutManager as? GridLayoutManager)?.scrollToPositionWithOffset(
|
||||||
|
allItems.indexOfFirst { it is EmojisAdapter.Item.Category && it.value == category },
|
||||||
|
0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
root.imageTintList = ColorStateList.valueOf(mTextColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
keyboardViewBinding?.emojisList?.apply {
|
keyboardViewBinding?.emojisList?.apply {
|
||||||
val emojiItemWidth = context.resources.getDimensionPixelSize(R.dimen.emoji_item_size)
|
val emojiItemWidth = context.resources.getDimensionPixelSize(R.dimen.emoji_item_size)
|
||||||
val emojiTopBarElevation = context.resources.getDimensionPixelSize(R.dimen.emoji_top_bar_elevation).toFloat()
|
val emojiTopBarElevation = context.resources.getDimensionPixelSize(R.dimen.emoji_top_bar_elevation).toFloat()
|
||||||
|
|
||||||
layoutManager = AutoGridLayoutManager(context, emojiItemWidth)
|
layoutManager = AutoGridLayoutManager(context, emojiItemWidth).apply {
|
||||||
adapter = EmojisAdapter(context = context, items = emojis) { emoji ->
|
spanSizeLookup = object : SpanSizeLookup() {
|
||||||
mOnKeyboardActionListener!!.onText(emoji)
|
override fun getSpanSize(position: Int): Int =
|
||||||
|
if (allItems[position] is EmojisAdapter.Item.Category) {
|
||||||
|
spanCount
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
adapter = EmojisAdapter(context = context, items = allItems) { emoji ->
|
||||||
|
mOnKeyboardActionListener!!.onText(emoji.emoji)
|
||||||
vibrateIfNeeded()
|
vibrateIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearOnScrollListeners()
|
||||||
onScroll {
|
onScroll {
|
||||||
keyboardViewBinding!!.emojiPaletteTopBar.elevation = if (it > 4) emojiTopBarElevation else 0f
|
keyboardViewBinding!!.emojiPaletteTopBar.elevation = if (it > 4) emojiTopBarElevation else 0f
|
||||||
|
(keyboardViewBinding?.emojisList?.layoutManager as? LinearLayoutManager)?.findFirstCompletelyVisibleItemPosition()?.also { firstVisibleIndex ->
|
||||||
|
allItems
|
||||||
|
.withIndex()
|
||||||
|
.lastOrNull { it.value is EmojisAdapter.Item.Category && it.index <= firstVisibleIndex }
|
||||||
|
?.also { activeCategory ->
|
||||||
|
val id = checkIds.entries.first { it.value == (activeCategory.value as EmojisAdapter.Item.Category).value }.key
|
||||||
|
keyboardViewBinding?.emojiCategoriesStrip?.children?.filterIsInstance<ImageButton>()?.forEach {
|
||||||
|
if (it.id == id) {
|
||||||
|
it.imageTintList = ColorStateList.valueOf(context.getProperPrimaryColor())
|
||||||
|
} else {
|
||||||
|
it.imageTintList = ColorStateList.valueOf(mTextColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M19,5h-2V3H7v2H5C3.9,5 3,5.9 3,7v1c0,2.55 1.92,4.63 4.39,4.94c0.63,1.5 1.98,2.63 3.61,2.96V19H7v2h10v-2h-4v-3.1c1.63,-0.33 2.98,-1.46 3.61,-2.96C19.08,12.63 21,10.55 21,8V7C21,5.9 20.1,5 19,5zM5,8V7h2v3.82C5.84,10.4 5,9.3 5,8zM19,8c0,1.3 -0.84,2.4 -2,2.82V7h2V8z"/>
|
||||||
|
</vector>
|
6
app/src/main/res/drawable/ic_emoji_category_animals.xml
Normal file
6
app/src/main/res/drawable/ic_emoji_category_animals.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M21.94,4.88C21.76,4.35 21.25,4 20.68,4c-0.03,0 -0.06,0 -0.09,0H19.6l-0.31,-0.97C19.15,2.43 18.61,2 18,2h0c-0.61,0 -1.15,0.43 -1.29,1.04L16.4,4h-0.98c-0.03,0 -0.06,0 -0.09,0c-0.57,0 -1.08,0.35 -1.26,0.88c-0.19,0.56 0.04,1.17 0.56,1.48l0.87,0.52L15.1,8.12c-0.23,0.58 -0.04,1.25 0.45,1.62C15.78,9.91 16.06,10 16.33,10c0.31,0 0.61,-0.11 0.86,-0.32L18,8.98l0.81,0.7C19.06,9.89 19.36,10 19.67,10c0.27,0 0.55,-0.09 0.78,-0.26c0.5,-0.37 0.68,-1.04 0.45,-1.62l-0.39,-1.24l0.87,-0.52C21.89,6.05 22.12,5.44 21.94,4.88zM18,7c-0.55,0 -1,-0.45 -1,-1c0,-0.55 0.45,-1 1,-1s1,0.45 1,1C19,6.55 18.55,7 18,7z"/>
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M13.49,10.51c-0.43,-0.43 -0.94,-0.73 -1.49,-0.93V8h-1v1.38c-0.11,-0.01 -0.23,-0.03 -0.34,-0.03c-1.02,0 -2.05,0.39 -2.83,1.17c-0.16,0.16 -0.3,0.34 -0.43,0.53L6,10.52c-1.56,-0.55 -3.28,0.27 -3.83,1.82c0,0 0,0 0,0c-0.27,0.75 -0.23,1.57 0.12,2.29c0.23,0.48 0.58,0.87 1,1.16c-0.38,1.35 -0.06,2.85 1,3.91c1.06,1.06 2.57,1.38 3.91,1c0.29,0.42 0.68,0.77 1.16,1C9.78,21.9 10.21,22 10.65,22c0.34,0 0.68,-0.06 1.01,-0.17c0,0 0,0 0,0c1.56,-0.55 2.38,-2.27 1.82,-3.85l-0.52,-1.37c0.18,-0.13 0.36,-0.27 0.53,-0.43c0.87,-0.87 1.24,-2.04 1.14,-3.17H16v-1h-1.59C14.22,11.46 13.92,10.95 13.49,10.51zM4.67,14.29c-0.25,-0.09 -0.45,-0.27 -0.57,-0.51s-0.13,-0.51 -0.04,-0.76c0.19,-0.52 0.76,-0.79 1.26,-0.61l3.16,1.19C7.33,14.2 5.85,14.71 4.67,14.29zM10.99,19.94c-0.25,0.09 -0.52,0.08 -0.76,-0.04c-0.24,-0.11 -0.42,-0.32 -0.51,-0.57c-0.42,-1.18 0.09,-2.65 0.7,-3.8l1.18,3.13C11.78,19.18 11.51,19.76 10.99,19.94zM12.2,14.6l-0.61,-1.61c0,-0.01 -0.01,-0.02 -0.02,-0.03c-0.02,-0.04 -0.04,-0.08 -0.06,-0.12c-0.02,-0.04 -0.04,-0.07 -0.07,-0.11c-0.03,-0.03 -0.06,-0.06 -0.09,-0.09c-0.03,-0.03 -0.06,-0.06 -0.09,-0.09c-0.03,-0.03 -0.07,-0.05 -0.11,-0.07c-0.04,-0.02 -0.07,-0.05 -0.12,-0.06c-0.01,0 -0.02,-0.01 -0.03,-0.02L9.4,11.8c0.36,-0.29 0.79,-0.46 1.26,-0.46c0.53,0 1.04,0.21 1.41,0.59C12.8,12.66 12.84,13.81 12.2,14.6z"/>
|
||||||
|
</vector>
|
5
app/src/main/res/drawable/ic_emoji_category_flags.xml
Normal file
5
app/src/main/res/drawable/ic_emoji_category_flags.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M14.4,6L14,4H5v17h2v-7h5.6l0.4,2h7V6z"/>
|
||||||
|
</vector>
|
6
app/src/main/res/drawable/ic_emoji_category_food.xml
Normal file
6
app/src/main/res/drawable/ic_emoji_category_food.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M20,3H9v2.4l1.81,1.45C10.93,6.94 11,7.09 11,7.24v4.26c0,0.28 -0.22,0.5 -0.5,0.5h-4C6.22,12 6,11.78 6,11.5V7.24c0,-0.15 0.07,-0.3 0.19,-0.39L8,5.4V3H4v10c0,2.21 1.79,4 4,4h6c2.21,0 4,-1.79 4,-4v-3h2c1.11,0 2,-0.9 2,-2V5C22,3.89 21.11,3 20,3zM20,8h-2V5h2V8z"/>
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M4,19h16v2h-16z"/>
|
||||||
|
</vector>
|
5
app/src/main/res/drawable/ic_emoji_category_objects.xml
Normal file
5
app/src/main/res/drawable/ic_emoji_category_objects.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M12,3c-0.46,0 -0.93,0.04 -1.4,0.14C7.84,3.67 5.64,5.9 5.12,8.66c-0.48,2.61 0.48,5.01 2.22,6.56C7.77,15.6 8,16.13 8,16.69V19c0,1.1 0.9,2 2,2h0.28c0.35,0.6 0.98,1 1.72,1s1.38,-0.4 1.72,-1H14c1.1,0 2,-0.9 2,-2v-2.31c0,-0.55 0.22,-1.09 0.64,-1.46C18.09,13.95 19,12.08 19,10C19,6.13 15.87,3 12,3zM14,19h-4v-1h4V19zM14,17h-4v-1h4V17zM12.5,11.41V14h-1v-2.59L9.67,9.59l0.71,-0.71L12,10.5l1.62,-1.62l0.71,0.71L12.5,11.41z"/>
|
||||||
|
</vector>
|
6
app/src/main/res/drawable/ic_emoji_category_people.xml
Normal file
6
app/src/main/res/drawable/ic_emoji_category_people.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M12,4m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M15.89,8.11C15.5,7.72 14.83,7 13.53,7c-0.21,0 -1.42,0 -2.54,0C8.24,6.99 6,4.75 6,2H4c0,3.16 2.11,5.84 5,6.71V22h2v-6h2v6h2V10.05L18.95,14l1.41,-1.41L15.89,8.11z"/>
|
||||||
|
</vector>
|
5
app/src/main/res/drawable/ic_emoji_category_smileys.xml
Normal file
5
app/src/main/res/drawable/ic_emoji_category_smileys.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M11.99,2C6.47,2 2,6.48 2,12c0,5.52 4.47,10 9.99,10C17.52,22 22,17.52 22,12C22,6.48 17.52,2 11.99,2zM8.5,8C9.33,8 10,8.67 10,9.5S9.33,11 8.5,11S7,10.33 7,9.5S7.67,8 8.5,8zM12,18c-2.28,0 -4.22,-1.66 -5,-4h10C16.22,16.34 14.28,18 12,18zM15.5,11c-0.83,0 -1.5,-0.67 -1.5,-1.5S14.67,8 15.5,8S17,8.67 17,9.5S16.33,11 15.5,11z"/>
|
||||||
|
</vector>
|
11
app/src/main/res/drawable/ic_emoji_category_symbols.xml
Normal file
11
app/src/main/res/drawable/ic_emoji_category_symbols.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M3,2h8v2h-8z"/>
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M6,11l2,0l0,-4l3,0l0,-2l-8,0l0,2l3,0z"/>
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M12.4036,20.1819l7.7781,-7.7781l1.4142,1.4142l-7.7781,7.7781z"/>
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M14.5,14.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M19.5,19.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M15.5,11c1.38,0 2.5,-1.12 2.5,-2.5V4h3V2h-4v4.51C16.58,6.19 16.07,6 15.5,6C14.12,6 13,7.12 13,8.5C13,9.88 14.12,11 15.5,11z"/>
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M9.74,15.96l-1.41,1.41l-0.71,-0.71l0.35,-0.35c0.98,-0.98 0.98,-2.56 0,-3.54c-0.49,-0.49 -1.13,-0.73 -1.77,-0.73c-0.64,0 -1.28,0.24 -1.77,0.73c-0.98,0.98 -0.98,2.56 0,3.54l0.35,0.35l-1.06,1.06c-0.98,0.98 -0.98,2.56 0,3.54C4.22,21.76 4.86,22 5.5,22s1.28,-0.24 1.77,-0.73l1.06,-1.06l1.41,1.41l1.41,-1.41l-1.41,-1.41l1.41,-1.41L9.74,15.96zM5.85,14.2c0.12,-0.12 0.26,-0.15 0.35,-0.15s0.23,0.03 0.35,0.15c0.19,0.2 0.19,0.51 0,0.71l-0.35,0.35L5.85,14.9C5.66,14.71 5.66,14.39 5.85,14.2zM5.85,19.85C5.73,19.97 5.59,20 5.5,20s-0.23,-0.03 -0.35,-0.15c-0.19,-0.19 -0.19,-0.51 0,-0.71l1.06,-1.06l0.71,0.71L5.85,19.85z"/>
|
||||||
|
</vector>
|
5
app/src/main/res/drawable/ic_emoji_category_travel.xml
Normal file
5
app/src/main/res/drawable/ic_emoji_category_travel.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M19.3,16.9c0.4,-0.7 0.7,-1.5 0.7,-2.4c0,-2.5 -2,-4.5 -4.5,-4.5S11,12 11,14.5s2,4.5 4.5,4.5c0.9,0 1.7,-0.3 2.4,-0.7l3.2,3.2l1.4,-1.4L19.3,16.9zM15.5,17c-1.4,0 -2.5,-1.1 -2.5,-2.5s1.1,-2.5 2.5,-2.5s2.5,1.1 2.5,2.5S16.9,17 15.5,17zM12,20v2C6.48,22 2,17.52 2,12C2,6.48 6.48,2 12,2c4.84,0 8.87,3.44 9.8,8h-2.07c-0.64,-2.46 -2.4,-4.47 -4.73,-5.41V5c0,1.1 -0.9,2 -2,2h-2v2c0,0.55 -0.45,1 -1,1H8v2h2v3H9l-4.79,-4.79C4.08,10.79 4,11.38 4,12C4,16.41 7.59,20 12,20z"/>
|
||||||
|
</vector>
|
8
app/src/main/res/layout/emoji_list.xml
Normal file
8
app/src/main/res/layout/emoji_list.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<com.simplemobiletools.commons.views.MyRecyclerView
|
||||||
|
android:id="@+id/emojis_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:padding="@dimen/small_margin"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android" />
|
11
app/src/main/res/layout/item_emoji_category.xml
Normal file
11
app/src/main/res/layout/item_emoji_category.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/emoji_value"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/ripple_all_corners_medium"
|
||||||
|
android:gravity="center"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
|
android:padding="@dimen/tiny_margin"
|
||||||
|
android:scaleType="centerInside"
|
||||||
|
android:src="@drawable/ic_emoji_category_activities" />
|
|
@ -202,6 +202,18 @@
|
||||||
android:text="@string/abc"
|
android:text="@string/abc"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/emoji_categories_strip"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginStart="@dimen/medium_margin"
|
||||||
|
android:layout_marginEnd="@dimen/medium_margin"
|
||||||
|
android:layout_toStartOf="@+id/emoji_palette_backspace"
|
||||||
|
android:layout_toEndOf="@+id/emoji_palette_mode_change"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/emoji_palette_backspace"
|
android:id="@+id/emoji_palette_backspace"
|
||||||
android:layout_width="@dimen/emoji_palette_btn_size"
|
android:layout_width="@dimen/emoji_palette_btn_size"
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
<dimen name="vertical_correction">-10dp</dimen>
|
<dimen name="vertical_correction">-10dp</dimen>
|
||||||
<dimen name="clip_pin_size">28dp</dimen>
|
<dimen name="clip_pin_size">28dp</dimen>
|
||||||
<dimen name="emoji_item_size">46dp</dimen>
|
<dimen name="emoji_item_size">46dp</dimen>
|
||||||
|
<dimen name="emoji_category_item_size">24dp</dimen>
|
||||||
<dimen name="emoji_top_bar_elevation">4dp</dimen>
|
<dimen name="emoji_top_bar_elevation">4dp</dimen>
|
||||||
<dimen name="emoji_palette_btn_size">42dp</dimen>
|
<dimen name="emoji_palette_btn_size">42dp</dimen>
|
||||||
<dimen name="suggestion_max_width">200dp</dimen>
|
<dimen name="suggestion_max_width">200dp</dimen>
|
||||||
|
@ -17,4 +18,5 @@
|
||||||
<dimen name="preview_text_size">26sp</dimen>
|
<dimen name="preview_text_size">26sp</dimen>
|
||||||
<dimen name="label_text_size">16sp</dimen> <!-- text size used at keys with longer labels, like "123" -->
|
<dimen name="label_text_size">16sp</dimen> <!-- text size used at keys with longer labels, like "123" -->
|
||||||
<dimen name="emoji_text_size">28sp</dimen>
|
<dimen name="emoji_text_size">28sp</dimen>
|
||||||
|
<dimen name="emoji_category_text_size">14sp</dimen>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue