Better draw factory implementation

This commit is contained in:
J-Jamet
2021-03-06 10:48:05 +01:00
parent be7cd3275a
commit 42e2a49af6
2 changed files with 82 additions and 129 deletions

View File

@@ -84,6 +84,24 @@ object AutofillHelper {
return ""
}
private fun newRemoteViews(context: Context,
remoteViewsText: String,
remoteViewsIcon: IconImage? = null): RemoteViews {
val presentation = RemoteViews(context.packageName, R.layout.item_autofill_entry)
presentation.setTextViewText(R.id.autofill_entry_text, remoteViewsText)
if (remoteViewsIcon != null) {
try {
Database.getInstance().iconDrawableFactory.getBitmapFromIcon(context,
remoteViewsIcon, ContextCompat.getColor(context, R.color.green))?.let { bitmap ->
presentation.setImageViewBitmap(R.id.autofill_entry_icon, bitmap)
}
} catch (e: Exception) {
Log.e(RemoteViews::class.java.name, "Unable to assign icon in remote view", e)
}
}
return presentation
}
private fun buildDataset(context: Context,
entryInfo: EntryInfo,
struct: StructureParser.Result,
@@ -114,6 +132,21 @@ object AutofillHelper {
}
}
/**
* Method to assign a drawable to a new icon from a database icon
*/
private fun buildIconFromEntry(context: Context, entryInfo: EntryInfo): Icon? {
try {
Database.getInstance().iconDrawableFactory.getBitmapFromIcon(context,
entryInfo.icon, ContextCompat.getColor(context, R.color.green))?.let { bitmap ->
return Icon.createWithBitmap(bitmap)
}
} catch (e: Exception) {
Log.e(RemoteViews::class.java.name, "Unable to assign icon in remote view", e)
}
return null
}
@RequiresApi(Build.VERSION_CODES.R)
@SuppressLint("RestrictedApi")
private fun buildInlinePresentationForEntry(context: Context,
@@ -265,25 +298,4 @@ object AutofillHelper {
activity.finish()
}
}
private fun newRemoteViews(context: Context,
remoteViewsText: String,
remoteViewsIcon: IconImage? = null): RemoteViews {
val presentation = RemoteViews(context.packageName, R.layout.item_autofill_entry)
presentation.setTextViewText(R.id.autofill_entry_text, remoteViewsText)
if (remoteViewsIcon != null) {
Database.getInstance().iconDrawableFactory.assignDatabaseIcon(context,
presentation,
R.id.autofill_entry_icon,
remoteViewsIcon,
ContextCompat.getColor(context, R.color.green))
}
return presentation
}
private fun buildIconFromEntry(context: Context, entryInfo: EntryInfo): Icon? {
return Database.getInstance().iconDrawableFactory.createIconFromDatabaseIcon(context,
entryInfo.icon,
ContextCompat.getColor(context, R.color.green))
}
}

View File

@@ -64,80 +64,23 @@ class IconDrawableFactory(private val retrieveCipherKey : () -> Database.LoadedK
*/
private val standardIconMap = HashMap<CacheKey, WeakReference<Drawable>>()
/**
* Utility method to assign a drawable to an ImageView and tint it
*/
private fun assignDrawableToImageView(superDrawable: SuperDrawable, imageView: ImageView?, tint: Boolean, tintColor: Int) {
if (imageView != null) {
imageView.setImageDrawable(superDrawable.drawable)
if (superDrawable.tintable && tint) {
ImageViewCompat.setImageTintList(imageView, ColorStateList.valueOf(tintColor))
} else {
ImageViewCompat.setImageTintList(imageView, null)
}
}
}
/**
* Utility method to assign a drawable to a RemoteView and tint it
*/
private fun assignDrawableToRemoteViews(superDrawable: SuperDrawable,
remoteViews: RemoteViews,
imageId: Int,
tintColor: Int = Color.BLACK) {
val bitmap = superDrawable.drawable.toBitmap()
// Tint bitmap if it's not a custom icon
if (superDrawable.tintable && bitmap.isMutable) {
Canvas(bitmap).drawBitmap(bitmap, 0.0F, 0.0F, Paint().apply {
colorFilter = PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN)
})
}
remoteViews.setImageViewBitmap(imageId, bitmap)
}
/**
* Utility method to assign a drawable to a icon and tint it
*/
@RequiresApi(Build.VERSION_CODES.M)
private fun assignDrawableToIcon(superDrawable: SuperDrawable,
tintColor: Int = Color.BLACK): Icon {
val bitmap = superDrawable.drawable.toBitmap()
// Tint bitmap if it's not a custom icon
if (superDrawable.tintable && bitmap.isMutable) {
Canvas(bitmap).drawBitmap(bitmap, 0.0F, 0.0F, Paint().apply {
colorFilter = PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN)
})
}
return Icon.createWithBitmap(bitmap)
}
/**
* Get the [SuperDrawable] [iconDraw] (from cache, or build it and add it to the cache if not exists yet), then [tint] it with [tintColor] if needed
*/
private fun getIconSuperDrawable(context: Context, iconDraw: IconImageDraw, width: Int, tint: Boolean = false, tintColor: Int = Color.WHITE): SuperDrawable {
private fun getIconSuperDrawable(context: Context, iconDraw: IconImageDraw, width: Int, tintColor: Int = Color.WHITE): SuperDrawable {
val icon = iconDraw.getIconImageToDraw()
return if (!icon.custom.isUnknown) {
SuperDrawable(getIconDrawable(context.resources, icon.custom))
} else {
val iconPack = IconPackChooser.getSelectedIconPack(context)
iconPack?.iconToResId(icon.standard.id)?.let { iconId ->
SuperDrawable(getIconDrawable(context.resources, iconId, width, tint, tintColor), iconPack.tintable())
SuperDrawable(getIconDrawable(context.resources, iconId, width, tintColor), iconPack.tintable())
} ?: run {
SuperDrawable(PatternIcon(context.resources).blankDrawable)
}
}
}
/**
* Simple method to init the cache with the custom icon and be much faster next time
*/
private fun addToCache(resources: Resources, iconDraw: IconImageDraw) {
val icon = iconDraw.getIconImageToDraw()
if (icon.custom.binaryFile.length > 0
&& !customIconMap.containsKey(icon.custom.uuid))
getIconDrawable(resources, icon.custom)
}
/**
* Build a custom [Drawable] from custom [icon]
*/
@@ -165,8 +108,8 @@ class IconDrawableFactory(private val retrieveCipherKey : () -> Database.LoadedK
* Get the standard [Drawable] icon from [iconId] (cache or build it and add it to the cache if not exists yet)
* , then [tint] it with [tintColor] if needed
*/
private fun getIconDrawable(resources: Resources, iconId: Int, width: Int, tint: Boolean, tintColor: Int): Drawable {
val newCacheKey = CacheKey(iconId, width, tint, tintColor)
private fun getIconDrawable(resources: Resources, iconId: Int, width: Int, tintColor: Int): Drawable {
val newCacheKey = CacheKey(iconId, width, true, tintColor)
var draw: Drawable? = standardIconMap[newCacheKey]?.get()
if (draw == null) {
@@ -205,14 +148,6 @@ class IconDrawableFactory(private val retrieveCipherKey : () -> Database.LoadedK
}
/**
* Clear the cache of icons
*/
fun clearCache() {
standardIconMap.clear()
customIconMap.clear()
}
/**
* Assign a database [icon] to an ImageView and tint it with [tintColor] if needed
*/
@@ -225,15 +160,16 @@ class IconDrawableFactory(private val retrieveCipherKey : () -> Database.LoadedK
addToCache(context.resources, icon)
withContext(Dispatchers.Main) {
IconPackChooser.getSelectedIconPack(context)?.let { selectedIconPack ->
assignDrawableToImageView(
getIconSuperDrawable(context,
icon,
imageView.width,
true,
tintColor),
imageView,
selectedIconPack.tintable(),
val superDrawable = getIconSuperDrawable(context,
icon,
imageView.width,
tintColor)
imageView.setImageDrawable(superDrawable.drawable)
if (superDrawable.tintable && selectedIconPack.tintable()) {
ImageViewCompat.setImageTintList(imageView, ColorStateList.valueOf(tintColor))
} else {
ImageViewCompat.setImageTintList(imageView, null)
}
}
}
}
@@ -242,44 +178,49 @@ class IconDrawableFactory(private val retrieveCipherKey : () -> Database.LoadedK
}
}
fun assignDatabaseIcon(context: Context,
remoteViews: RemoteViews,
imageId: Int,
icon: IconImageDraw,
tintColor: Int = Color.BLACK) {
/**
* Build a bitmap from a database [icon]
*/
fun getBitmapFromIcon(context: Context,
icon: IconImageDraw,
tintColor: Int = Color.BLACK): Bitmap? {
try {
assignDrawableToRemoteViews(
getIconSuperDrawable(context,
icon,
24,
true,
tintColor),
remoteViews,
imageId,
val superDrawable = getIconSuperDrawable(context,
icon,
24,
tintColor)
val bitmap = superDrawable.drawable.toBitmap()
// Tint bitmap if it's not a custom icon
if (superDrawable.tintable && bitmap.isMutable) {
Canvas(bitmap).drawBitmap(bitmap, 0.0F, 0.0F, Paint().apply {
colorFilter = PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN)
})
}
return bitmap
} catch (e: Exception) {
Log.e(RemoteViews::class.java.name, "Unable to assign icon in remote view", e)
}
}
@RequiresApi(Build.VERSION_CODES.M)
fun createIconFromDatabaseIcon(context: Context,
icon: IconImageDraw,
tintColor: Int = Color.BLACK): Icon? {
try {
return assignDrawableToIcon(
getIconSuperDrawable(context,
icon,
24,
true,
tintColor),
tintColor)
} catch (e: Exception) {
Log.e(RemoteViews::class.java.name, "Unable to assign icon in remote view", e)
Log.e(RemoteViews::class.java.name, "Unable to create bitmap from icon", e)
}
return null
}
/**
* Simple method to init the cache with the custom icon and be much faster next time
*/
private fun addToCache(resources: Resources, iconDraw: IconImageDraw) {
val icon = iconDraw.getIconImageToDraw()
if (icon.custom.binaryFile.length > 0
&& !customIconMap.containsKey(icon.custom.uuid))
getIconDrawable(resources, icon.custom)
}
/**
* Clear the cache of icons
*/
fun clearCache() {
standardIconMap.clear()
customIconMap.clear()
}
/**
* Build a blankDrawable drawable
* @param res Resource to build the drawable