Add tint for icon pack

This commit is contained in:
J-Jamet
2018-04-12 19:21:53 +02:00
parent d5b0ee9371
commit b6b7e61cfb
8 changed files with 119 additions and 22 deletions

View File

@@ -23,7 +23,8 @@ package com.kunzisoft.keepass.activities;
import android.app.Activity; import android.app.Activity;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.Drawable; import android.content.res.TypedArray;
import android.graphics.Color;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
@@ -45,6 +46,7 @@ import com.kunzisoft.keepass.database.ExtraFields;
import com.kunzisoft.keepass.database.PwDatabase; import com.kunzisoft.keepass.database.PwDatabase;
import com.kunzisoft.keepass.database.PwEntry; import com.kunzisoft.keepass.database.PwEntry;
import com.kunzisoft.keepass.database.security.ProtectedString; import com.kunzisoft.keepass.database.security.ProtectedString;
import com.kunzisoft.keepass.icons.IconPackChooser;
import com.kunzisoft.keepass.notifications.NotificationCopyingService; import com.kunzisoft.keepass.notifications.NotificationCopyingService;
import com.kunzisoft.keepass.notifications.NotificationField; import com.kunzisoft.keepass.notifications.NotificationField;
import com.kunzisoft.keepass.settings.PreferencesUtil; import com.kunzisoft.keepass.settings.PreferencesUtil;
@@ -277,20 +279,25 @@ public class EntryActivity extends LockingHideActivity {
} }
} }
private void populateTitle(Drawable drawIcon, String text) {
titleIconView.setImageDrawable(drawIcon);
titleView.setText(text);
}
protected void fillData() { protected void fillData() {
Database db = App.getDB(); Database db = App.getDB();
PwDatabase pm = db.getPwDatabase(); PwDatabase pm = db.getPwDatabase();
mEntry.startToManageFieldReferences(pm); mEntry.startToManageFieldReferences(pm);
// Assign title // Assign title icon
populateTitle(db.getDrawFactory().getIconDrawable(this, mEntry.getIcon()), if (IconPackChooser.getDefaultIconPack(this).tintable()) {
mEntry.getTitle()); // Retrieve the textColor to tint the icon
int[] attrs = {R.attr.textColorInverse};
TypedArray ta = getTheme().obtainStyledAttributes(attrs);
int iconColor = ta.getColor(0, Color.WHITE);
App.getDB().getDrawFactory().assignDrawableTo(this, titleIconView, mEntry.getIcon(), true, iconColor);
} else {
App.getDB().getDrawFactory().assignDrawableTo(this, titleIconView, mEntry.getIcon());
}
// Assign title text
titleView.setText(mEntry.getTitle());
// Assign basic fields // Assign basic fields
entryContentsView.assignUserName(mEntry.getUsername()); entryContentsView.assignUserName(mEntry.getUsername());

View File

@@ -27,6 +27,8 @@ import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
@@ -60,6 +62,7 @@ import com.kunzisoft.keepass.dialogs.AssignMasterKeyDialogFragment;
import com.kunzisoft.keepass.dialogs.GroupEditDialogFragment; import com.kunzisoft.keepass.dialogs.GroupEditDialogFragment;
import com.kunzisoft.keepass.dialogs.IconPickerDialogFragment; import com.kunzisoft.keepass.dialogs.IconPickerDialogFragment;
import com.kunzisoft.keepass.dialogs.ReadOnlyDialog; import com.kunzisoft.keepass.dialogs.ReadOnlyDialog;
import com.kunzisoft.keepass.icons.IconPackChooser;
import com.kunzisoft.keepass.search.SearchResultsActivity; import com.kunzisoft.keepass.search.SearchResultsActivity;
import com.kunzisoft.keepass.settings.PreferencesUtil; import com.kunzisoft.keepass.settings.PreferencesUtil;
import com.kunzisoft.keepass.tasks.ProgressTask; import com.kunzisoft.keepass.tasks.ProgressTask;
@@ -407,7 +410,16 @@ public class GroupActivity extends ListNodesActivity
protected void setGroupIcon() { protected void setGroupIcon() {
if (mCurrentGroup != null) { if (mCurrentGroup != null) {
ImageView iv = findViewById(R.id.icon); ImageView iv = findViewById(R.id.icon);
App.getDB().getDrawFactory().assignDrawableTo(this, iv, mCurrentGroup.getIcon());
if (IconPackChooser.getDefaultIconPack(this).tintable()) {
// Retrieve the textColor to tint the icon
int[] attrs = {R.attr.textColorInverse};
TypedArray ta = getTheme().obtainStyledAttributes(attrs);
int iconColor = ta.getColor(0, Color.WHITE);
App.getDB().getDrawFactory().assignDrawableTo(this, iv, mCurrentGroup.getIcon(), true, iconColor);
} else {
App.getDB().getDrawFactory().assignDrawableTo(this, iv, mCurrentGroup.getIcon());
}
} }
} }

View File

@@ -20,6 +20,9 @@
package com.kunzisoft.keepass.adapters; package com.kunzisoft.keepass.adapters;
import android.content.Context; import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.support.annotation.NonNull;
import android.support.v7.util.SortedList; import android.support.v7.util.SortedList;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.util.SortedListAdapterCallback; import android.support.v7.widget.util.SortedListAdapterCallback;
@@ -36,6 +39,7 @@ import com.kunzisoft.keepass.app.App;
import com.kunzisoft.keepass.database.PwGroup; import com.kunzisoft.keepass.database.PwGroup;
import com.kunzisoft.keepass.database.PwNode; import com.kunzisoft.keepass.database.PwNode;
import com.kunzisoft.keepass.database.SortNodeEnum; import com.kunzisoft.keepass.database.SortNodeEnum;
import com.kunzisoft.keepass.icons.IconPackChooser;
import com.kunzisoft.keepass.settings.PreferencesUtil; import com.kunzisoft.keepass.settings.PreferencesUtil;
public class NodeAdapter extends RecyclerView.Adapter<BasicViewHolder> { public class NodeAdapter extends RecyclerView.Adapter<BasicViewHolder> {
@@ -54,6 +58,9 @@ public class NodeAdapter extends RecyclerView.Adapter<BasicViewHolder> {
private NodeMenuListener nodeMenuListener; private NodeMenuListener nodeMenuListener;
private boolean activateContextMenu; private boolean activateContextMenu;
private int iconGroupColor;
private int iconEntryColor;
/** /**
* Create node list adapter with contextMenu or not * Create node list adapter with contextMenu or not
* @param context Context to use * @param context Context to use
@@ -81,6 +88,12 @@ public class NodeAdapter extends RecyclerView.Adapter<BasicViewHolder> {
return item1.equals(item2); return item1.equals(item2);
} }
}); });
// Retrieve the color to tint the icon
int[] attrs = {android.R.attr.textColorPrimary, android.R.attr.textColor};
TypedArray ta = context.getTheme().obtainStyledAttributes(attrs);
this.iconGroupColor = ta.getColor(0, Color.BLACK);
this.iconEntryColor = ta.getColor(1, Color.BLACK);
} }
public void setActivateContextMenu(boolean activate) { public void setActivateContextMenu(boolean activate) {
@@ -158,7 +171,7 @@ public class NodeAdapter extends RecyclerView.Adapter<BasicViewHolder> {
} }
@Override @Override
public BasicViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { public BasicViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
BasicViewHolder basicViewHolder; BasicViewHolder basicViewHolder;
View view; View view;
if (viewType == PwNode.Type.GROUP.ordinal()) { if (viewType == PwNode.Type.GROUP.ordinal()) {
@@ -172,10 +185,23 @@ public class NodeAdapter extends RecyclerView.Adapter<BasicViewHolder> {
} }
@Override @Override
public void onBindViewHolder(BasicViewHolder holder, int position) { public void onBindViewHolder(@NonNull BasicViewHolder holder, int position) {
PwNode subNode = nodeSortedList.get(position); PwNode subNode = nodeSortedList.get(position);
// Assign image // Assign image
App.getDB().getDrawFactory().assignDrawableTo(context, holder.icon, subNode.getIcon()); if (IconPackChooser.getDefaultIconPack(context).tintable()) {
int iconColor = Color.BLACK;
switch (subNode.getType()) {
case GROUP:
iconColor = iconGroupColor;
break;
case ENTRY:
iconColor = iconEntryColor;
break;
}
App.getDB().getDrawFactory().assignDrawableTo(context, holder.icon, subNode.getIcon(), true, iconColor);
} else {
App.getDB().getDrawFactory().assignDrawableTo(context, holder.icon, subNode.getIcon());
}
// Assign text // Assign text
holder.text.setText(subNode.getDisplayTitle()); holder.text.setText(subNode.getDisplayTitle());
// Assign click // Assign click

View File

@@ -21,9 +21,13 @@ package com.kunzisoft.keepass.dialogs;
import android.app.Dialog; import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v4.widget.ImageViewCompat;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@@ -124,6 +128,16 @@ public class IconPickerDialogFragment extends DialogFragment {
ImageView iv = currView.findViewById(R.id.icon_image); ImageView iv = currView.findViewById(R.id.icon_image);
iv.setImageResource(iconPack.iconToResId(position)); iv.setImageResource(iconPack.iconToResId(position));
// Assign color if icons are tintable
if (iconPack.tintable()) {
// Retrieve the textColor to tint the icon
int[] attrs = {android.R.attr.textColor};
assert getContext() != null;
TypedArray ta = getContext().getTheme().obtainStyledAttributes(attrs);
int iconColor = ta.getColor(0, Color.BLACK);
ImageViewCompat.setImageTintList(iv, ColorStateList.valueOf(iconColor));
}
return currView; return currView;
} }
} }

View File

@@ -20,12 +20,14 @@
package com.kunzisoft.keepass.icons; package com.kunzisoft.keepass.icons;
import android.content.Context; import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.support.v4.widget.ImageViewCompat;
import android.widget.ImageView; import android.widget.ImageView;
import com.kunzisoft.keepass.R; import com.kunzisoft.keepass.R;
@@ -41,6 +43,7 @@ public class DrawableFactory {
private static Drawable blank = null; private static Drawable blank = null;
private static int blankWidth = -1; private static int blankWidth = -1;
private static int blankHeight = -1; private static int blankHeight = -1;
private boolean iconStandardToTint = false;
/** customIconMap /** customIconMap
* Cache for icon drawable. * Cache for icon drawable.
@@ -53,19 +56,33 @@ public class DrawableFactory {
* Keys: Integer, Values: Drawables * Keys: Integer, Values: Drawables
*/ */
private ReferenceMap standardIconMap = new ReferenceMap(AbstractReferenceMap.HARD, AbstractReferenceMap.WEAK); private ReferenceMap standardIconMap = new ReferenceMap(AbstractReferenceMap.HARD, AbstractReferenceMap.WEAK);
public void assignDrawableTo(Context context, ImageView iv, PwIcon icon) { public void assignDrawableTo(Context context, ImageView iv, PwIcon icon) {
Drawable draw = getIconDrawable(context, icon); assignDrawableTo(context, iv, icon, false, -1);
if (iv != null && draw != null)
iv.setImageDrawable(draw);
} }
public void assignDrawableTo(Context context, ImageView iv, PwIcon icon, boolean tint, int tintColor) {
Drawable draw = getIconDrawable(context, icon);
if (iv != null && draw != null) {
iv.setImageDrawable(draw);
if (iconStandardToTint && tint) {
ImageViewCompat.setImageTintList(iv, ColorStateList.valueOf(tintColor));
}
}
iconStandardToTint = false;
}
public Drawable getIconDrawable(Context context, PwIcon icon) { public Drawable getIconDrawable(Context context, PwIcon icon) {
Drawable sharedDrawable;
if (icon instanceof PwIconStandard) { if (icon instanceof PwIconStandard) {
return getIconDrawable(context, (PwIconStandard) icon); iconStandardToTint = true;
sharedDrawable = getIconDrawable(context, (PwIconStandard) icon);
} else { } else {
return getIconDrawable(context, (PwIconCustom) icon); iconStandardToTint = false;
sharedDrawable = getIconDrawable(context, (PwIconCustom) icon);
} }
assert sharedDrawable.getConstantState() != null;
return sharedDrawable.getConstantState().newDrawable();
} }
private static void initBlank(Resources res) { private static void initBlank(Resources res) {
@@ -119,6 +136,7 @@ public class DrawableFactory {
} }
/** Resize the custom icon to match the built in icons /** Resize the custom icon to match the built in icons
*
* @param bitmap * @param bitmap
* @return * @return
*/ */

View File

@@ -44,9 +44,11 @@ public class IconPack {
private static final int NB_ICONS = 68; private static final int NB_ICONS = 68;
private static SparseIntArray icons = null; private static SparseIntArray icons = null;
private boolean tintable = false;
private Resources resources; private Resources resources;
/** /**
* Construct dynamically the icon pack provide by the default string resource "resource_prefix" * Construct dynamically the icon pack provide by the default string resource "resource_prefix"
* *
@@ -71,12 +73,28 @@ public class IconPack {
icons = new SparseIntArray(); icons = new SparseIntArray();
while(num <= NB_ICONS) { while(num <= NB_ICONS) {
// To construct the id with prefix_ic_XX_32dp (ex : classic_ic_08_32dp ) // To construct the id with prefix_ic_XX_32dp (ex : classic_ic_08_32dp )
String drawableIdString = new DecimalFormat("00").format(num) + "_32dp"; int resId = resources.getIdentifier(
String drawableIdStringWithPrefix = context.getString(resourcePrefixId) + drawableIdString; context.getString(resourcePrefixId) + new DecimalFormat("00").format(num) + "_32dp",
int resId = resources.getIdentifier(drawableIdStringWithPrefix, "drawable", context.getPackageName()); "drawable",
context.getPackageName());
icons.put(num, resId); icons.put(num, resId);
num++; num++;
} }
// If icons are tintable
tintable = resources.getBoolean(
resources.getIdentifier(
context.getString(resourcePrefixId) + "tintable",
"bool",
context.getPackageName()) );
}
/**
* Determine if each icon in the pack can be tint
*
* @return true if icons are tintable
*/
public boolean tintable() {
return tintable;
} }
/** /**

View File

@@ -20,4 +20,5 @@
<resources <resources
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<string name="resource_prefix" tools:ignore="ResourceName">classic_</string> <string name="resource_prefix" tools:ignore="ResourceName">classic_</string>
<bool name="classic_tintable">false</bool>
</resources> </resources>

View File

@@ -20,4 +20,5 @@
<resources <resources
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<string name="resource_prefix" tools:ignore="ResourceName">material_</string> <string name="resource_prefix" tools:ignore="ResourceName">material_</string>
<bool name="material_tintable">true</bool>
</resources> </resources>