dandelion/app/src/main/java/net/gsantner/opoc/util/ContextUtils.java

594 lines
23 KiB
Java
Raw Normal View History

2018-03-12 00:05:53 +01:00
/*#######################################################
2017-05-29 19:05:37 +02:00
*
2018-03-12 00:05:53 +01:00
* Maintained by Gregor Santner, 2016-
* https://gsantner.net/
*
* License: Apache 2.0
* https://github.com/gsantner/opoc/#licensing
* https://www.apache.org/licenses/LICENSE-2.0
*
#########################################################*/
2017-09-09 17:09:04 +02:00
package net.gsantner.opoc.util;
2017-05-29 19:05:37 +02:00
import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
2017-10-28 09:56:05 +02:00
import android.content.ClipData;
2017-05-29 19:05:37 +02:00
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
2017-08-24 13:34:32 +02:00
import android.content.res.Resources;
2017-09-09 17:09:04 +02:00
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
2017-09-09 17:09:04 +02:00
import android.graphics.Matrix;
2017-10-28 09:56:05 +02:00
import android.graphics.Paint;
import android.graphics.Rect;
2017-09-09 17:09:04 +02:00
import android.graphics.drawable.BitmapDrawable;
2017-05-29 19:05:37 +02:00
import android.graphics.drawable.Drawable;
2017-09-09 17:09:04 +02:00
import android.graphics.drawable.VectorDrawable;
2017-05-29 19:05:37 +02:00
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
2017-09-09 17:09:04 +02:00
import android.os.Build;
import android.support.annotation.ColorInt;
2017-05-29 19:05:37 +02:00
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
2017-09-09 17:09:04 +02:00
import android.support.annotation.Nullable;
2017-05-29 19:05:37 +02:00
import android.support.annotation.RawRes;
import android.support.annotation.StringRes;
2017-09-09 17:09:04 +02:00
import android.support.graphics.drawable.VectorDrawableCompat;
2017-05-29 19:05:37 +02:00
import android.support.v4.content.ContextCompat;
2017-09-09 17:09:04 +02:00
import android.support.v4.graphics.drawable.DrawableCompat;
2017-07-29 04:44:28 +02:00
import android.text.Html;
import android.text.SpannableString;
import android.text.Spanned;
2017-05-29 19:05:37 +02:00
import android.text.TextUtils;
2017-07-29 04:44:28 +02:00
import android.text.method.LinkMovementMethod;
2017-05-29 19:05:37 +02:00
import android.util.DisplayMetrics;
2018-03-12 00:05:53 +01:00
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
2017-09-09 17:09:04 +02:00
import android.widget.ImageView;
2017-07-29 04:44:28 +02:00
import android.widget.TextView;
2017-05-29 19:05:37 +02:00
import net.gsantner.opoc.format.markdown.SimpleMarkdownParser;
2017-05-29 19:05:37 +02:00
import java.io.BufferedReader;
2017-09-09 17:09:04 +02:00
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
2017-05-29 19:05:37 +02:00
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
2018-03-12 00:05:53 +01:00
import java.util.ArrayList;
import java.util.List;
2017-05-29 19:05:37 +02:00
import java.util.Locale;
2018-03-12 00:05:53 +01:00
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
2017-09-09 17:09:04 +02:00
import static android.graphics.Bitmap.CompressFormat;
2018-03-12 00:05:53 +01:00
@SuppressWarnings({"WeakerAccess", "unused", "SameParameterValue", "ObsoleteSdkInt", "deprecation", "SpellCheckingInspection"})
2017-09-09 17:09:04 +02:00
public class ContextUtils {
2017-08-09 17:23:19 +02:00
//########################
//## Members, Constructors
//########################
protected Context _context;
2017-05-29 19:05:37 +02:00
2017-09-09 17:09:04 +02:00
public ContextUtils(Context context) {
2017-08-09 17:23:19 +02:00
_context = context;
2017-05-29 19:05:37 +02:00
}
public Context context() {
return _context;
2017-05-29 19:05:37 +02:00
}
//########################
//## Resources
//########################
2017-08-09 17:23:19 +02:00
static class ResType {
public static final String DRAWABLE = "drawable";
public static final String STRING = "string";
public static final String PLURAL = "plural";
public static final String COLOR = "color";
public static final String STYLE = "style";
public static final String ARRAY = "array";
public static final String DIMEN = "dimen";
public static final String MENU = "menu";
2018-03-05 23:37:24 +01:00
public static final String BOOL = "bool";
2017-08-09 17:23:19 +02:00
public static final String RAW = "raw";
2017-05-29 19:05:37 +02:00
}
2018-03-05 23:37:24 +01:00
public String rstr(@StringRes int strResId) {
return _context.getString(strResId);
}
2018-03-05 23:37:24 +01:00
public String rstr(String strResKey) {
return rstr(getResId(ResType.STRING, strResKey));
}
public Drawable rdrawable(@DrawableRes int resId) {
2017-08-09 17:23:19 +02:00
return ContextCompat.getDrawable(_context, resId);
2017-05-29 19:05:37 +02:00
}
2018-03-05 23:37:24 +01:00
public int rcolor(@ColorRes int resId) {
2017-08-09 17:23:19 +02:00
return ContextCompat.getColor(_context, resId);
2017-05-29 19:05:37 +02:00
}
public int getResId(final String type, final String name) {
return _context.getResources().getIdentifier(name, type, _context.getPackageName());
}
public boolean areResIdsAvailable(final String type, final String... names) {
for (String name : names) {
if (getResId(type, name) == 0) {
return false;
}
}
return true;
2017-05-29 19:05:37 +02:00
}
//########################
//## Methods
//########################
2017-05-29 19:05:37 +02:00
public String colorToHexString(int intColor) {
return String.format("#%06X", 0xFFFFFF & intColor);
}
public String getAppVersionName() {
try {
2017-08-09 17:23:19 +02:00
PackageManager manager = _context.getPackageManager();
PackageInfo info = manager.getPackageInfo(_context.getPackageName(), 0);
2017-05-29 19:05:37 +02:00
return info.versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
2017-08-09 17:23:19 +02:00
return "?";
2017-05-29 19:05:37 +02:00
}
}
2017-08-09 17:23:19 +02:00
public void openWebpageInExternalBrowser(final String url) {
2017-05-29 19:05:37 +02:00
Uri uri = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
2018-03-12 00:05:53 +01:00
intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
try {
_context.startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
}
2017-08-09 17:23:19 +02:00
}
/**
2018-03-05 23:37:24 +01:00
* Get field from ${applicationId}.BuildConfig
2017-08-24 13:34:32 +02:00
* May be helpful in libraries, where a access to
* BuildConfig would only get values of the library
2018-03-05 23:37:24 +01:00
* rather than the app ones. It awaits a string resource
* of the package set in manifest (root element).
* Falls back to applicationId of the app which may differ from manifest.
2017-08-09 17:23:19 +02:00
*/
public Object getBuildConfigValue(String fieldName) {
2018-03-05 23:37:24 +01:00
String pkg;
2017-08-09 17:23:19 +02:00
try {
2018-03-05 23:37:24 +01:00
pkg = rstr("manifest_package_id");
} catch (Resources.NotFoundException ex) {
pkg = _context.getPackageName();
}
pkg += ".BuildConfig";
try {
Class<?> c = Class.forName(pkg);
2017-08-24 13:34:32 +02:00
return c.getField(fieldName).get(null);
} catch (Exception e) {
2017-08-09 17:23:19 +02:00
e.printStackTrace();
2017-08-24 13:34:32 +02:00
return null;
2017-08-09 17:23:19 +02:00
}
}
2018-03-05 23:37:24 +01:00
public boolean bcbool(String fieldName, boolean defaultValue) {
2017-08-09 17:23:19 +02:00
Object field = getBuildConfigValue(fieldName);
if (field != null && field instanceof Boolean) {
return (Boolean) field;
}
return defaultValue;
}
2018-03-05 23:37:24 +01:00
public String bcstr(String fieldName, String defaultValue) {
Object field = getBuildConfigValue(fieldName);
if (field != null && field instanceof String) {
return (String) field;
}
return defaultValue;
}
2017-08-09 17:23:19 +02:00
public boolean isGooglePlayBuild() {
2018-03-05 23:37:24 +01:00
return bcbool("IS_GPLAY_BUILD", true);
2017-05-29 19:05:37 +02:00
}
2017-08-09 17:23:19 +02:00
public boolean isFossBuild() {
2018-03-05 23:37:24 +01:00
return bcbool("IS_FOSS_BUILD", false);
2017-08-09 17:23:19 +02:00
}
// Requires donate__bitcoin_* resources (see below) to be available as string resource
public void showDonateBitcoinRequest(@StringRes final int strResBitcoinId, @StringRes final int strResBitcoinAmount, @StringRes final int strResBitcoinMessage, @StringRes final int strResAlternativeDonateUrl) {
if (!isGooglePlayBuild()) {
2017-05-29 19:05:37 +02:00
String btcUri = String.format("bitcoin:%s?amount=%s&label=%s&message=%s",
2018-03-05 23:37:24 +01:00
rstr(strResBitcoinId), rstr(strResBitcoinAmount),
rstr(strResBitcoinMessage), rstr(strResBitcoinMessage));
2017-05-29 19:05:37 +02:00
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(btcUri));
2018-03-12 00:05:53 +01:00
intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
2017-05-29 19:05:37 +02:00
try {
2017-08-09 17:23:19 +02:00
_context.startActivity(intent);
2017-05-29 19:05:37 +02:00
} catch (ActivityNotFoundException e) {
2018-03-05 23:37:24 +01:00
openWebpageInExternalBrowser(rstr(strResAlternativeDonateUrl));
2017-05-29 19:05:37 +02:00
}
}
}
public String readTextfileFromRawRes(@RawRes int rawResId, String linePrefix, String linePostfix) {
StringBuilder sb = new StringBuilder();
BufferedReader br = null;
String line;
linePrefix = linePrefix == null ? "" : linePrefix;
linePostfix = linePostfix == null ? "" : linePostfix;
try {
2017-08-09 17:23:19 +02:00
br = new BufferedReader(new InputStreamReader(_context.getResources().openRawResource(rawResId)));
2017-05-29 19:05:37 +02:00
while ((line = br.readLine()) != null) {
sb.append(linePrefix);
sb.append(line);
sb.append(linePostfix);
sb.append("\n");
}
} catch (Exception ignored) {
} finally {
if (br != null) {
try {
br.close();
} catch (IOException ignored) {
}
}
}
return sb.toString();
}
2018-03-12 00:05:53 +01:00
/**
* Get internet connection state - the permission ACCESS_NETWORK_STATE is required
*
* @return True if internet connection available
*/
2017-05-29 19:05:37 +02:00
public boolean isConnectedToInternet() {
2018-03-12 00:05:53 +01:00
try {
ConnectivityManager con = (ConnectivityManager) _context.getSystemService(Context.CONNECTIVITY_SERVICE);
@SuppressLint("MissingPermission") NetworkInfo activeNetInfo =
con == null ? null : con.getActiveNetworkInfo();
return activeNetInfo != null && activeNetInfo.isConnectedOrConnecting();
} catch (Exception ignored) {
throw new RuntimeException("Error: Developer forgot to declare a permission");
}
2017-05-29 19:05:37 +02:00
}
2018-03-12 00:05:53 +01:00
public boolean isAppInstalled(String packageName) {
PackageManager pm = _context.getApplicationContext().getPackageManager();
try {
pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
2017-09-09 17:09:04 +02:00
}
2018-03-12 00:05:53 +01:00
public void restartApp(Class classToStart) {
Intent inte = new Intent(_context, classToStart);
PendingIntent inteP = PendingIntent.getActivity(_context, 555, inte, PendingIntent.FLAG_CANCEL_CURRENT);
2017-08-09 17:23:19 +02:00
AlarmManager mgr = (AlarmManager) _context.getSystemService(Context.ALARM_SERVICE);
2018-03-12 00:05:53 +01:00
if (mgr != null) {
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, inteP);
} else {
inte.addFlags(FLAG_ACTIVITY_NEW_TASK);
_context.startActivity(inte);
}
Runtime.getRuntime().exit(0);
2017-05-29 19:05:37 +02:00
}
public String loadMarkdownForTextViewFromRaw(@RawRes int rawMdFile, String prepend) {
try {
return new SimpleMarkdownParser()
2017-08-09 17:23:19 +02:00
.parse(_context.getResources().openRawResource(rawMdFile),
2017-07-29 04:44:28 +02:00
prepend, SimpleMarkdownParser.FILTER_ANDROID_TEXTVIEW)
2018-03-05 23:37:24 +01:00
.replaceColor("#000001", rcolor(getResId(ResType.COLOR, "accent")))
2017-05-29 19:05:37 +02:00
.removeMultiNewlines().replaceBulletCharacter("*").getHtml();
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
2017-07-29 04:44:28 +02:00
public void setHtmlToTextView(TextView textView, String html) {
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(new SpannableString(htmlToSpanned(html)));
2017-07-29 04:44:28 +02:00
}
2017-05-29 19:05:37 +02:00
public double getEstimatedScreenSizeInches() {
2017-08-09 17:23:19 +02:00
DisplayMetrics dm = _context.getResources().getDisplayMetrics();
2017-05-29 19:05:37 +02:00
double density = dm.density * 160;
double x = Math.pow(dm.widthPixels / density, 2);
double y = Math.pow(dm.heightPixels / density, 2);
double screenInches = Math.sqrt(x + y) * 1.16; // 1.16 = est. Nav/Statusbar
screenInches = screenInches < 4.0 ? 4.0 : screenInches;
screenInches = screenInches > 12.0 ? 12.0 : screenInches;
return screenInches;
}
public boolean isInPortraitMode() {
2017-08-09 17:23:19 +02:00
return _context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
2017-05-29 19:05:37 +02:00
}
public Locale getLocaleByAndroidCode(String code) {
if (!TextUtils.isEmpty(code)) {
return code.contains("-r")
? new Locale(code.substring(0, 2), code.substring(4, 6)) // de-rAt
: new Locale(code); // de
}
2017-08-24 13:34:32 +02:00
return Resources.getSystem().getConfiguration().locale;
2017-05-29 19:05:37 +02:00
}
2017-08-24 13:34:32 +02:00
// en/de/de-rAt ; Empty string -> default locale
2017-05-29 19:05:37 +02:00
public void setAppLanguage(String androidLocaleString) {
Locale locale = getLocaleByAndroidCode(androidLocaleString);
2017-08-09 17:23:19 +02:00
Configuration config = _context.getResources().getConfiguration();
2017-08-24 13:34:32 +02:00
config.locale = (locale != null && !androidLocaleString.isEmpty())
? locale : Resources.getSystem().getConfiguration().locale;
2017-08-09 17:23:19 +02:00
_context.getResources().updateConfiguration(config, null);
}
// Find out if color above the given color should be light or dark. true if light
public boolean shouldColorOnTopBeLight(@ColorInt int colorOnBottomInt) {
return 186 > (((0.299 * Color.red(colorOnBottomInt))
+ ((0.587 * Color.green(colorOnBottomInt))
+ (0.114 * Color.blue(colorOnBottomInt)))));
}
public Spanned htmlToSpanned(String html) {
Spanned result;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
result = Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY);
} else {
result = Html.fromHtml(html);
}
return result;
}
2017-08-24 13:34:32 +02:00
2018-03-12 00:05:53 +01:00
public boolean setClipboard(String text) {
2017-10-28 09:56:05 +02:00
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
2018-03-12 00:05:53 +01:00
android.text.ClipboardManager cm = ((android.text.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE));
if (cm != null) {
cm.setText(text);
return true;
}
2017-10-28 09:56:05 +02:00
} else {
2018-03-12 00:05:53 +01:00
android.content.ClipboardManager cm = ((android.content.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE));
if (cm != null) {
ClipData clip = ClipData.newPlainText(_context.getPackageName(), text);
cm.setPrimaryClip(clip);
return true;
}
2017-10-28 09:56:05 +02:00
}
2018-03-12 00:05:53 +01:00
return false;
2017-10-28 09:56:05 +02:00
}
2018-03-12 00:05:53 +01:00
public List<String> getClipboard() {
List<String> clipper = new ArrayList<>();
2017-10-28 09:56:05 +02:00
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
2018-03-12 00:05:53 +01:00
android.text.ClipboardManager cm = ((android.text.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE));
if (cm != null) {
clipper.add(cm.getText().toString());
}
2017-10-28 09:56:05 +02:00
} else {
2018-03-12 00:05:53 +01:00
android.content.ClipboardManager cm = ((android.content.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE));
if (cm != null && cm.hasPrimaryClip()) {
ClipData data = cm.getPrimaryClip();
for (int i = 0; i < data.getItemCount() && i < data.getItemCount(); i++) {
clipper.add(data.getItemAt(i).getText().toString());
}
2017-10-28 09:56:05 +02:00
}
2018-03-12 00:05:53 +01:00
2017-10-28 09:56:05 +02:00
}
2018-03-12 00:05:53 +01:00
return clipper;
2017-10-28 09:56:05 +02:00
}
2018-03-12 00:05:53 +01:00
public float convertPxToDp(final float px) {
2017-08-09 17:23:19 +02:00
return px / _context.getResources().getDisplayMetrics().density;
}
2018-03-12 00:05:53 +01:00
public float convertDpToPx(final float dp) {
2017-08-09 17:23:19 +02:00
return dp * _context.getResources().getDisplayMetrics().density;
2017-05-29 19:05:37 +02:00
}
2017-09-09 17:09:04 +02:00
public static void setDrawableWithColorToImageView(ImageView imageView, @DrawableRes int drawableResId, @ColorRes int colorResId) {
imageView.setImageResource(drawableResId);
imageView.setColorFilter(ContextCompat.getColor(imageView.getContext(), colorResId));
}
public Bitmap drawableToBitmap(Drawable drawable) {
Bitmap bitmap = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && (drawable instanceof VectorDrawable || drawable instanceof VectorDrawableCompat)) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
drawable = (DrawableCompat.wrap(drawable)).mutate();
}
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
} else if (drawable instanceof BitmapDrawable) {
bitmap = ((BitmapDrawable) drawable).getBitmap();
}
return bitmap;
}
2017-09-23 20:33:28 +02:00
public Bitmap loadImageFromFilesystem(File imagePath, int maxDimen) {
2017-09-09 17:09:04 +02:00
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
2017-09-23 20:33:28 +02:00
BitmapFactory.decodeFile(imagePath.getAbsolutePath(), options);
2017-09-09 17:09:04 +02:00
options.inSampleSize = calculateInSampleSize(options, maxDimen);
options.inJustDecodeBounds = false;
2017-09-23 20:33:28 +02:00
return BitmapFactory.decodeFile(imagePath.getAbsolutePath(), options);
2017-09-09 17:09:04 +02:00
}
/**
* Calculates the scaling factor so the bitmap is maximal as big as the maxDimen
*
* @param options Bitmap-options that contain the current dimensions of the bitmap
* @param maxDimen Max size of the Bitmap (width or height)
* @return the scaling factor that needs to be applied to the bitmap
*/
public int calculateInSampleSize(BitmapFactory.Options options, int maxDimen) {
2017-10-28 09:56:05 +02:00
// Raw height and width of image
2017-09-09 17:09:04 +02:00
int height = options.outHeight;
int width = options.outWidth;
int inSampleSize = 1;
if (Math.max(height, width) > maxDimen) {
inSampleSize = Math.round(1f * Math.max(height, width) / maxDimen);
}
return inSampleSize;
}
public Bitmap scaleBitmap(Bitmap bitmap, int maxDimen) {
int picSize = Math.min(bitmap.getHeight(), bitmap.getWidth());
float scale = 1.f * maxDimen / picSize;
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
2018-03-12 00:05:53 +01:00
public boolean writeImageToFileJpeg(File imageFile, Bitmap image) {
2017-09-23 20:33:28 +02:00
return writeImageToFile(imageFile, image, Bitmap.CompressFormat.JPEG, 95);
2017-09-09 17:09:04 +02:00
}
2018-03-12 00:05:53 +01:00
/**
* Write bitmap to the filesystem
*
* @param targetFile The file to be written in
* @param image The image as android {@link Bitmap}
* @param format One format of {@link CompressFormat}, null will determine based on filename
* @param quality Quality level, defaults to 95
* @return True if writing was successful
*/
public boolean writeImageToFile(File targetFile, Bitmap image, CompressFormat format, Integer quality) {
File folder = new File(targetFile.getParent());
if (quality == null || quality < 0 || quality > 100) {
quality = 95;
2017-09-23 20:33:28 +02:00
}
2018-03-12 00:05:53 +01:00
if (format == null) {
format = CompressFormat.JPEG;
String lc = targetFile.getAbsolutePath().toLowerCase(Locale.ROOT);
if (lc.endsWith(".png")) {
format = CompressFormat.PNG;
}
if (lc.endsWith(".webp")) {
format = CompressFormat.WEBP;
}
2017-09-23 20:33:28 +02:00
}
if (folder.exists() || folder.mkdirs()) {
2017-09-09 17:09:04 +02:00
FileOutputStream stream = null;
try {
2018-03-12 00:05:53 +01:00
stream = new FileOutputStream(targetFile); // overwrites this image every time
2017-09-09 17:09:04 +02:00
image.compress(format, quality, stream);
2018-03-12 00:05:53 +01:00
return true;
2017-09-09 17:09:04 +02:00
} catch (FileNotFoundException ignored) {
} finally {
try {
if (stream != null) {
stream.close();
}
} catch (IOException ignored) {
}
}
}
2018-03-12 00:05:53 +01:00
return false;
2017-09-09 17:09:04 +02:00
}
2017-10-28 09:56:05 +02:00
2018-03-12 00:05:53 +01:00
public Bitmap drawTextOnDrawable(@DrawableRes int resId, String text, int textSize) {
2017-10-28 09:56:05 +02:00
Resources resources = _context.getResources();
float scale = resources.getDisplayMetrics().density;
2018-03-12 00:05:53 +01:00
Bitmap bitmap = bitmapToDrawable(resId);
2017-10-28 09:56:05 +02:00
bitmap = bitmap.copy(bitmap.getConfig(), true);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.rgb(61, 61, 61));
paint.setTextSize((int) (textSize * scale));
paint.setShadowLayer(1f, 0f, 1f, Color.WHITE);
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
int x = (bitmap.getWidth() - bounds.width()) / 2;
int y = (bitmap.getHeight() + bounds.height()) / 2;
canvas.drawText(text, x, y, paint);
return bitmap;
}
2018-03-12 00:05:53 +01:00
public Bitmap bitmapToDrawable(@DrawableRes int drawableId) {
2017-10-28 09:56:05 +02:00
Bitmap bitmap = null;
Drawable drawable = ContextCompat.getDrawable(_context, drawableId);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && (drawable instanceof VectorDrawable || drawable instanceof VectorDrawableCompat)) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
drawable = (DrawableCompat.wrap(drawable)).mutate();
}
2018-03-12 00:05:53 +01:00
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
2017-10-28 09:56:05 +02:00
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
} else if (drawable instanceof BitmapDrawable) {
bitmap = ((BitmapDrawable) drawable).getBitmap();
}
return bitmap;
}
2018-03-12 00:05:53 +01:00
@SuppressWarnings("ConstantConditions")
public void tintMenuItems(Menu menu, boolean recurse, @ColorInt int iconColor) {
for (int i = 0; i < menu.size(); i++) {
MenuItem item = menu.getItem(i);
tintDrawable(item.getIcon(), iconColor);
if (item.hasSubMenu() && recurse) {
tintMenuItems(item.getSubMenu(), recurse, iconColor);
}
}
}
public Drawable tintDrawable(@DrawableRes int drawableRes, @ColorInt int color) {
return tintDrawable(_context.getResources().getDrawable(drawableRes), color);
}
public Drawable tintDrawable(@Nullable Drawable drawable, @ColorInt int color) {
if (drawable != null) {
drawable = DrawableCompat.wrap(drawable);
DrawableCompat.setTint(drawable.mutate(), color);
}
return drawable;
}
2018-03-12 00:05:53 +01:00
public void setSubMenuIconsVisiblity(Menu menu, boolean visible) {
if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
try {
2018-03-12 00:05:53 +01:00
@SuppressLint("PrivateApi") Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, visible);
} catch (Exception ignored) {
2018-03-12 00:05:53 +01:00
Log.d(getClass().getName(), "Error: 'setSubMenuIconsVisiblity' not supported on this device");
}
}
}
2017-05-29 19:05:37 +02:00
}