Nice color default icons for bookmarks
This commit is contained in:
parent
3b8f85a86a
commit
0e55c653b0
@ -3,6 +3,7 @@ package acr.browser.lightning.favicon;
|
|||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.support.annotation.ColorInt;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -22,6 +23,8 @@ import java.io.IOException;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import acr.browser.lightning.R;
|
||||||
|
import acr.browser.lightning.utils.DrawableUtils;
|
||||||
import acr.browser.lightning.utils.FileUtils;
|
import acr.browser.lightning.utils.FileUtils;
|
||||||
import acr.browser.lightning.utils.Preconditions;
|
import acr.browser.lightning.utils.Preconditions;
|
||||||
import acr.browser.lightning.utils.Utils;
|
import acr.browser.lightning.utils.Utils;
|
||||||
@ -44,10 +47,13 @@ public class FaviconModel {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private final int mBookmarkIconSize;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
FaviconModel(@NonNull Application application) {
|
FaviconModel(@NonNull Application application) {
|
||||||
mImageFetcher = new ImageFetcher();
|
mImageFetcher = new ImageFetcher();
|
||||||
mApplication = application;
|
mApplication = application;
|
||||||
|
mBookmarkIconSize = mApplication.getResources().getDimensionPixelSize(R.dimen.bookmark_item_icon_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,6 +74,16 @@ public class FaviconModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private Bitmap getDefaultBitmapForCharacter(@NonNull Character character) {
|
||||||
|
@ColorInt int defaultFaviconColor = DrawableUtils.characterToColorHash(character, mApplication);
|
||||||
|
|
||||||
|
return DrawableUtils.getRoundedLetterImage(character,
|
||||||
|
mBookmarkIconSize,
|
||||||
|
mBookmarkIconSize,
|
||||||
|
defaultFaviconColor);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a bitmap to the memory cache
|
* Adds a bitmap to the memory cache
|
||||||
* for the given URL.
|
* for the given URL.
|
||||||
@ -106,18 +122,15 @@ public class FaviconModel {
|
|||||||
* Retrieves the favicon for a URL,
|
* Retrieves the favicon for a URL,
|
||||||
* may be from network or cache.
|
* may be from network or cache.
|
||||||
*
|
*
|
||||||
* @param url the URL that we should retrieve the
|
* @param url The URL that we should retrieve the
|
||||||
* favicon for.
|
* favicon for.
|
||||||
* @param defaultFavicon the default favicon if no
|
* @param title The title for the web page.
|
||||||
* favicon is found.
|
* @param allowGoogleService True to allow grabbing favicons
|
||||||
* @param allowGoogleService true to allow grabbing favicons
|
* from Google, false otherwise. @return an observable that emits a bitmap if one is found,
|
||||||
* from Google, false otherwise.
|
|
||||||
* @return an observable that emits a bitmap if one is found,
|
|
||||||
* or the default if none was found.
|
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Single<Bitmap> faviconForUrl(@NonNull final String url,
|
public Single<Bitmap> faviconForUrl(@NonNull final String url,
|
||||||
@NonNull final Bitmap defaultFavicon,
|
@NonNull final String title,
|
||||||
final boolean allowGoogleService) {
|
final boolean allowGoogleService) {
|
||||||
return Single.create(new SingleAction<Bitmap>() {
|
return Single.create(new SingleAction<Bitmap>() {
|
||||||
@Override
|
@Override
|
||||||
@ -126,7 +139,7 @@ public class FaviconModel {
|
|||||||
|
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
|
|
||||||
Bitmap newFavicon = Utils.padFavicon(defaultFavicon);
|
Bitmap newFavicon = Utils.padFavicon(getDefaultBitmapForCharacter('?'));
|
||||||
|
|
||||||
subscriber.onItem(newFavicon);
|
subscriber.onItem(newFavicon);
|
||||||
subscriber.onComplete();
|
subscriber.onComplete();
|
||||||
@ -134,6 +147,9 @@ public class FaviconModel {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Character firstTitleCharacter = !title.isEmpty() ? title.charAt(0) : '?';
|
||||||
|
|
||||||
|
|
||||||
File faviconCacheFile = createFaviconCacheFile(mApplication, uri);
|
File faviconCacheFile = createFaviconCacheFile(mApplication, uri);
|
||||||
|
|
||||||
Bitmap favicon = getFaviconFromMemCache(url);
|
Bitmap favicon = getFaviconFromMemCache(url);
|
||||||
@ -168,7 +184,7 @@ public class FaviconModel {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// if (favicon == null) {
|
// if (favicon == null) {
|
||||||
favicon = defaultFavicon;
|
favicon = getDefaultBitmapForCharacter(firstTitleCharacter);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
Bitmap newFavicon = Utils.padFavicon(favicon);
|
Bitmap newFavicon = Utils.padFavicon(favicon);
|
||||||
|
@ -537,7 +537,7 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener,
|
|||||||
Subscription oldSubscription = mFaviconFetchSubscriptions.get(url);
|
Subscription oldSubscription = mFaviconFetchSubscriptions.get(url);
|
||||||
SubscriptionUtils.safeUnsubscribe(oldSubscription);
|
SubscriptionUtils.safeUnsubscribe(oldSubscription);
|
||||||
|
|
||||||
final Subscription faviconSubscription = mFaviconModel.faviconForUrl(url, mWebpageBitmap, true)
|
final Subscription faviconSubscription = mFaviconModel.faviconForUrl(url, web.getTitle(), true)
|
||||||
.subscribeOn(Schedulers.worker())
|
.subscribeOn(Schedulers.worker())
|
||||||
.observeOn(Schedulers.main())
|
.observeOn(Schedulers.main())
|
||||||
.subscribe(new SingleOnSubscribe<Bitmap>() {
|
.subscribe(new SingleOnSubscribe<Bitmap>() {
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package acr.browser.lightning.utils;
|
package acr.browser.lightning.utils;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.PorterDuffXfermode;
|
import android.graphics.PorterDuffXfermode;
|
||||||
@ -9,12 +11,17 @@ import android.graphics.RectF;
|
|||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.support.annotation.ColorInt;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
|
import acr.browser.lightning.R;
|
||||||
|
|
||||||
public class DrawableUtils {
|
public class DrawableUtils {
|
||||||
|
|
||||||
|
@NonNull
|
||||||
public static Bitmap getRoundedNumberImage(int number, int width, int height, int color, int thickness) {
|
public static Bitmap getRoundedNumberImage(int number, int width, int height, int color, int thickness) {
|
||||||
String text;
|
String text;
|
||||||
|
|
||||||
@ -56,6 +63,68 @@ public class DrawableUtils {
|
|||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a rounded square of a certain color with
|
||||||
|
* a character imprinted in white on it.
|
||||||
|
*
|
||||||
|
* @param character the character to write on the image.
|
||||||
|
* @param width the width of the final image.
|
||||||
|
* @param height the height of the final image.
|
||||||
|
* @param color the background color of the rounded square.
|
||||||
|
* @return a valid bitmap of a rounded square with a character on it.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static Bitmap getRoundedLetterImage(@NonNull Character character, int width, int height, int color) {
|
||||||
|
Bitmap image = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||||
|
Canvas canvas = new Canvas(image);
|
||||||
|
Paint paint = new Paint();
|
||||||
|
paint.setColor(color);
|
||||||
|
Typeface boldText = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD);
|
||||||
|
paint.setTypeface(boldText);
|
||||||
|
paint.setTextSize(Utils.dpToPx(14));
|
||||||
|
paint.setAntiAlias(true);
|
||||||
|
paint.setTextAlign(Paint.Align.CENTER);
|
||||||
|
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
|
||||||
|
|
||||||
|
int radius = Utils.dpToPx(2);
|
||||||
|
|
||||||
|
RectF outer = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
|
||||||
|
canvas.drawRoundRect(outer, radius, radius, paint);
|
||||||
|
|
||||||
|
int xPos = (canvas.getWidth() / 2);
|
||||||
|
int yPos = (int) ((canvas.getHeight() / 2) - ((paint.descent() + paint.ascent()) / 2));
|
||||||
|
|
||||||
|
paint.setColor(Color.WHITE);
|
||||||
|
canvas.drawText(character.toString(), xPos, yPos, paint);
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hashes a character to one of four colors:
|
||||||
|
* blue, green, red, or orange.
|
||||||
|
*
|
||||||
|
* @param character the character to hash.
|
||||||
|
* @param app the application needed to get the color.
|
||||||
|
* @return one of the above colors, or black something goes wrong.
|
||||||
|
*/
|
||||||
|
@ColorInt
|
||||||
|
public static int characterToColorHash(@NonNull Character character, @NonNull Application app) {
|
||||||
|
int smallHash = Character.getNumericValue(character) % 4;
|
||||||
|
switch (Math.abs(smallHash)) {
|
||||||
|
case 0:
|
||||||
|
return ContextCompat.getColor(app, R.color.bookmark_default_blue);
|
||||||
|
case 1:
|
||||||
|
return ContextCompat.getColor(app, R.color.bookmark_default_green);
|
||||||
|
case 2:
|
||||||
|
return ContextCompat.getColor(app, R.color.bookmark_default_red);
|
||||||
|
case 3:
|
||||||
|
return ContextCompat.getColor(app, R.color.bookmark_default_orange);
|
||||||
|
default:
|
||||||
|
return Color.BLACK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static int mixColor(float fraction, int startValue, int endValue) {
|
public static int mixColor(float fraction, int startValue, int endValue) {
|
||||||
int startA = (startValue >> 24) & 0xff;
|
int startA = (startValue >> 24) & 0xff;
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/faviconBookmark"
|
android:id="@+id/faviconBookmark"
|
||||||
android:layout_width="24dp"
|
android:layout_width="@dimen/bookmark_item_icon_size"
|
||||||
android:layout_height="24dp"
|
android:layout_height="@dimen/bookmark_item_icon_size"
|
||||||
android:layout_marginLeft="16dp"
|
android:layout_marginLeft="16dp"
|
||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="16dp"
|
||||||
android:contentDescription="Favicon"
|
android:contentDescription="Favicon"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{"url": "https://twitter.com/RestainoAnthony", "title": "Contact Me", "folder": "", "order": 0}
|
{"url": "https://twitter.com/RestainoAnthony", "title": "Contact Me", "folder": "", "order": 0}
|
||||||
{"url": "https://www.facebook.com/", "title": "Facebook", "folder": "", "order": 2}
|
{"url": "https://www.facebook.com/", "title": "Facebook", "folder": "", "order": 1}
|
||||||
{"url": "https://twitter.com", "title": "Twitter", "folder": "", "order": 3}
|
{"url": "https://twitter.com", "title": "Twitter", "folder": "", "order": 2}
|
||||||
{"url": "https://www.google.com/", "title": "Google", "folder": "", "order": 4}
|
{"url": "https://www.google.com/", "title": "Google", "folder": "", "order": 3}
|
||||||
{"url": "https://www.yahoo.com/", "title": "Yahoo", "folder": "", "order": 5}
|
{"url": "https://www.wikipedia.org/", "title": "Wikipedia", "folder": "", "order": 4}
|
||||||
|
@ -37,4 +37,9 @@
|
|||||||
|
|
||||||
<color name="error_red">#F44336</color>
|
<color name="error_red">#F44336</color>
|
||||||
|
|
||||||
|
<color name="bookmark_default_blue">#2196F3</color>
|
||||||
|
<color name="bookmark_default_green">#4CAF50</color>
|
||||||
|
<color name="bookmark_default_red">#EF5350</color>
|
||||||
|
<color name="bookmark_default_orange">#FF9800</color>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
@ -10,4 +10,6 @@
|
|||||||
<dimen name="default_padding">8dp</dimen>
|
<dimen name="default_padding">8dp</dimen>
|
||||||
<dimen name="extra_padding">16dp</dimen>
|
<dimen name="extra_padding">16dp</dimen>
|
||||||
|
|
||||||
|
<dimen name="bookmark_item_icon_size">24dp</dimen>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user