我可以使用 Glide 让 CircleImage 像在 Facebook Messenger 中一样具有重叠图标吗?
Can I use Glide to have CircleImage with overlapping icon like in Facebook messenger?
我正在寻找一个库,它可以帮助我在 Facebook Messenger 中制作我的关键图像视图(带有 z 蓝色 Messenger 图标或灰色 Facebook 图标)。他们是怎么想出来的?可以用 Glide 做吗?如果不是,那用什么?
如果您的目标是 仅 让 CircleImage 尝试一下:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.widget.ImageView;
public class RoundedImageView extends ImageView
{
public RoundedImageView(Context context)
{
super(context);
}
public RoundedImageView(Context context, @Nullable AttributeSet attrs)
{
super(context, attrs);
}
public RoundedImageView(Context context, @Nullable AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
public RoundedImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes)
{
super(context, attrs, defStyleAttr, defStyleRes);
}
public static Bitmap getCroppedBitmap(Bitmap bmp, int radius)
{
Bitmap sbmp;
if (bmp.getWidth() != radius || bmp.getHeight() != radius)
{
float smallest = Math.min(bmp.getWidth(), bmp.getHeight());
float factor = smallest / radius;
sbmp = Bitmap.createScaledBitmap(bmp, (int) (bmp.getWidth() / factor), (int) (bmp.getHeight() / factor), false);
}
else
{
sbmp = bmp;
}
Bitmap output = Bitmap.createBitmap(radius, radius,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xffa19774;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, radius, radius);
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
canvas.drawCircle(radius / 2 + 0.7f,
radius / 2 + 0.7f, radius / 2 + 0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(sbmp, rect, rect, paint);
return output;
}
@Override
protected void onDraw(Canvas canvas)
{
Drawable drawable = getDrawable();
if (drawable == null)
{
return;
}
if (getWidth() == 0 || getHeight() == 0)
{
return;
}
Bitmap b = ((BitmapDrawable) drawable).getBitmap();
Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);
int w = getWidth(), h = getHeight();
Bitmap roundBitmap = getCroppedBitmap(bitmap, w);
canvas.drawBitmap(roundBitmap, 0, 0, null);
}
}
在你的布局中你可以使用这个:
<mypkg.example.RoundedImageView
android:id="@+id/roundimg"
android:layout_width="54dp"
android:layout_height="54dp"
android:layout_gravity="center"/>
您可以通过编程方式设置一个字母..
Rect textBounds = new Rect();
String text = "N"
Bitmap bitmap = Bitmap.createBitmap(imageView.getLayoutParams().width, imageView.getLayoutParams().height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.DKGRAY);
TextPaint p = new TextPaint();
p.setColor(Color.WHITE);
p.setTextSize(imageView.getLayoutParams().height / 2);
p.setAntiAlias(true);
p.setTextAlign(Paint.Align.LEFT);
p.getTextBounds(text, 0, text.length(), textBounds);
int cx = imageView.getLayoutParams().width / 2;
int cy = imageView.getLayoutParams().height / 2;
canvas.drawText(text, cx - textBounds.exactCenterX(), cy - textBounds.exactCenterY(), p);
imageView.setImageBitmap(bitmap);
或一张图片..
// image grabbed from an input stream
Bitmap photo = BitmapFactory.decodeStream(inputStream);
imageView.setImageBitmap(photo);
这个有用吗?更多信息和学分在这里 How to create a circular ImageView in Android?
不建议使用 CircleImageView
/CircularImageView
/RoundedImageView
,we have many people reporting issues 主要是因为他们将 Bitmap 从 Drawable 中破解出来,这与大多数不兼容Glide 的基本功能:.crossFade()
,GIF 动画也可能与它们不兼容。
正确的Glide方法是使用Transformations,你可以在这里找到一个足够好的方法:
Glide 4.0 将内置 CircleCrop 转换。
叠加图标
覆盖图标也可以添加变形:
// .transform(new CircleTransform(context)), new StatusTransform(context, user.getStatus()))
public static class StatusTransform extends BitmapTransformation {
private final Status status;
public StatusTransform(Context context, Status status) {
super(context);
this.status = status;
}
@Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
int w = toTransform.getWidth(), h = toTransform.getHeight();
Bitmap result = pool.get(w, h, Bitmap.Config.ARGB_8888);
if (result == null) {
result = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(result);
canvas.drawBitmap(toTransform);
switch(status) {
case Online:
canvas.draw*(online graphics);
break;
case Offline:
canvas.draw*(offline graphics);
break;
}
return result;
}
@Override public String getId() {
return getClass().getName() + status;
}
}
或者只是有两个 ImageView
:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/user_profile_size"
android:layout_height="@dimen/user_profile_size"
>
<ImageView
android:id="@id/user_profile"
android:layout_width="@dimen/user_profile_size"
android:layout_height="@dimen/user_profile_size"
/>
<ImageView
android:id="@id/user_status"
android:layout_width="@dimen/user_status_size"
android:layout_height="@dimen/user_status_size"
android:layout_gravity="bottom|end"
/>
</FrameLayout>
两者各有优缺点:转换结果可以缓存,所以如果你有 3 个状态,Glide 会存储每个用户的个人资料图像 3 次,并用一个小图标覆盖,所以它可能只会应用一次,然后它只是解码缓存的 PNG(不是 JPEG,因为圆圈强制透明)的问题。如果有两个 ImageView,则必须有两个 Glide 加载线(或一个 Glide 和一个 setImageResource),绘制和布局可能会慢一点。因此,您可以使用这两种方法将处理器时间与磁盘 space 进行交易。使用 ImageView 方法,您还可以为状态更改之间的转换设置动画,并始终显示状态,即使个人资料图像由于网络不佳而加载缓慢也是如此。
如果 transform
方法的代码发生变化,则需要使缓存无效,这可以通过以下方式实现:
.signature(ApplicationVersionSignature.obatain(context)) // every release
// or
.signature(new StringSignature(String.valueOf( System.currentTimeMillies() / (10 * 60 * 1000) ))) // every 10 minutes
或者,这种失效可以以某种方式内置到 getId()
方法中。
1.I 建议您查看 Facebook 的 图片管理库 Fresco 与其他图片加载库相比,它非常棒且成熟.
2.Fresco 具有 SimpleDraweeView
作为自定义图像视图,支持 Rounded Corners and Circles
link 并支持动画(.gif、.webp)以及普通图像(.jpg , .png).
3.Fresco 使用 3 层架构(BITMAP_MEMORY_CACHE
、ENCODED_MEMORY_CACHE
和 DISK_CACHE
)处理所有图像缓存。它还减少了 OOM(内存不足)问题。当视图中的图像超出屏幕时,它会自动回收位图,从而释放内存。
我正在寻找一个库,它可以帮助我在 Facebook Messenger 中制作我的关键图像视图(带有 z 蓝色 Messenger 图标或灰色 Facebook 图标)。他们是怎么想出来的?可以用 Glide 做吗?如果不是,那用什么?
如果您的目标是 仅 让 CircleImage 尝试一下:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.widget.ImageView;
public class RoundedImageView extends ImageView
{
public RoundedImageView(Context context)
{
super(context);
}
public RoundedImageView(Context context, @Nullable AttributeSet attrs)
{
super(context, attrs);
}
public RoundedImageView(Context context, @Nullable AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
public RoundedImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes)
{
super(context, attrs, defStyleAttr, defStyleRes);
}
public static Bitmap getCroppedBitmap(Bitmap bmp, int radius)
{
Bitmap sbmp;
if (bmp.getWidth() != radius || bmp.getHeight() != radius)
{
float smallest = Math.min(bmp.getWidth(), bmp.getHeight());
float factor = smallest / radius;
sbmp = Bitmap.createScaledBitmap(bmp, (int) (bmp.getWidth() / factor), (int) (bmp.getHeight() / factor), false);
}
else
{
sbmp = bmp;
}
Bitmap output = Bitmap.createBitmap(radius, radius,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xffa19774;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, radius, radius);
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
canvas.drawCircle(radius / 2 + 0.7f,
radius / 2 + 0.7f, radius / 2 + 0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(sbmp, rect, rect, paint);
return output;
}
@Override
protected void onDraw(Canvas canvas)
{
Drawable drawable = getDrawable();
if (drawable == null)
{
return;
}
if (getWidth() == 0 || getHeight() == 0)
{
return;
}
Bitmap b = ((BitmapDrawable) drawable).getBitmap();
Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);
int w = getWidth(), h = getHeight();
Bitmap roundBitmap = getCroppedBitmap(bitmap, w);
canvas.drawBitmap(roundBitmap, 0, 0, null);
}
}
在你的布局中你可以使用这个:
<mypkg.example.RoundedImageView
android:id="@+id/roundimg"
android:layout_width="54dp"
android:layout_height="54dp"
android:layout_gravity="center"/>
您可以通过编程方式设置一个字母..
Rect textBounds = new Rect();
String text = "N"
Bitmap bitmap = Bitmap.createBitmap(imageView.getLayoutParams().width, imageView.getLayoutParams().height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.DKGRAY);
TextPaint p = new TextPaint();
p.setColor(Color.WHITE);
p.setTextSize(imageView.getLayoutParams().height / 2);
p.setAntiAlias(true);
p.setTextAlign(Paint.Align.LEFT);
p.getTextBounds(text, 0, text.length(), textBounds);
int cx = imageView.getLayoutParams().width / 2;
int cy = imageView.getLayoutParams().height / 2;
canvas.drawText(text, cx - textBounds.exactCenterX(), cy - textBounds.exactCenterY(), p);
imageView.setImageBitmap(bitmap);
或一张图片..
// image grabbed from an input stream
Bitmap photo = BitmapFactory.decodeStream(inputStream);
imageView.setImageBitmap(photo);
这个有用吗?更多信息和学分在这里 How to create a circular ImageView in Android?
不建议使用 CircleImageView
/CircularImageView
/RoundedImageView
,we have many people reporting issues 主要是因为他们将 Bitmap 从 Drawable 中破解出来,这与大多数不兼容Glide 的基本功能:.crossFade()
,GIF 动画也可能与它们不兼容。
正确的Glide方法是使用Transformations,你可以在这里找到一个足够好的方法:
Glide 4.0 将内置 CircleCrop 转换。
叠加图标
覆盖图标也可以添加变形:
// .transform(new CircleTransform(context)), new StatusTransform(context, user.getStatus()))
public static class StatusTransform extends BitmapTransformation {
private final Status status;
public StatusTransform(Context context, Status status) {
super(context);
this.status = status;
}
@Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
int w = toTransform.getWidth(), h = toTransform.getHeight();
Bitmap result = pool.get(w, h, Bitmap.Config.ARGB_8888);
if (result == null) {
result = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(result);
canvas.drawBitmap(toTransform);
switch(status) {
case Online:
canvas.draw*(online graphics);
break;
case Offline:
canvas.draw*(offline graphics);
break;
}
return result;
}
@Override public String getId() {
return getClass().getName() + status;
}
}
或者只是有两个 ImageView
:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/user_profile_size"
android:layout_height="@dimen/user_profile_size"
>
<ImageView
android:id="@id/user_profile"
android:layout_width="@dimen/user_profile_size"
android:layout_height="@dimen/user_profile_size"
/>
<ImageView
android:id="@id/user_status"
android:layout_width="@dimen/user_status_size"
android:layout_height="@dimen/user_status_size"
android:layout_gravity="bottom|end"
/>
</FrameLayout>
两者各有优缺点:转换结果可以缓存,所以如果你有 3 个状态,Glide 会存储每个用户的个人资料图像 3 次,并用一个小图标覆盖,所以它可能只会应用一次,然后它只是解码缓存的 PNG(不是 JPEG,因为圆圈强制透明)的问题。如果有两个 ImageView,则必须有两个 Glide 加载线(或一个 Glide 和一个 setImageResource),绘制和布局可能会慢一点。因此,您可以使用这两种方法将处理器时间与磁盘 space 进行交易。使用 ImageView 方法,您还可以为状态更改之间的转换设置动画,并始终显示状态,即使个人资料图像由于网络不佳而加载缓慢也是如此。
如果 transform
方法的代码发生变化,则需要使缓存无效,这可以通过以下方式实现:
.signature(ApplicationVersionSignature.obatain(context)) // every release
// or
.signature(new StringSignature(String.valueOf( System.currentTimeMillies() / (10 * 60 * 1000) ))) // every 10 minutes
或者,这种失效可以以某种方式内置到 getId()
方法中。
1.I 建议您查看 Facebook 的 图片管理库 Fresco 与其他图片加载库相比,它非常棒且成熟.
2.Fresco 具有 SimpleDraweeView
作为自定义图像视图,支持 Rounded Corners and Circles
link 并支持动画(.gif、.webp)以及普通图像(.jpg , .png).
3.Fresco 使用 3 层架构(BITMAP_MEMORY_CACHE
、ENCODED_MEMORY_CACHE
和 DISK_CACHE
)处理所有图像缓存。它还减少了 OOM(内存不足)问题。当视图中的图像超出屏幕时,它会自动回收位图,从而释放内存。