Android 自定义圆形头像列表展示导致RecyclerView滑动卡顿和闪烁

编程入门 行业动态 更新时间:2024-10-11 17:24:28

Android <a href=https://www.elefans.com/category/jswz/34/1771438.html style=自定义圆形头像列表展示导致RecyclerView滑动卡顿和闪烁"/>

Android 自定义圆形头像列表展示导致RecyclerView滑动卡顿和闪烁

Android 自定义圆形头像列表展示导致RecyclerView滑动卡顿和闪烁

我们一提到圆形头像,就会想到自定义ImageView。而普通的自定义圆形头像一般都是如下定义的。

自定义的圆形ImageView
/*** 圆形ImageView,可设置最多两个宽度不同且颜色不同的圆形边框。 .这个控件在列表中会很卡!!!* 此自定义不允许在列表中使用,会造成列表卡顿严重* * @author*/
public class RoundImageView extends androidx.appcompat.widget.AppCompatImageView {private int mBorderThickness = 0;private Context mContext;private int defaultColor = 0xFFFFFFFF;// 如果只有其中一个有值,则只画一个圆形边框private int mBorderOutsideColor = 0;private int mBorderInsideColor = 0;// 控件默认长、宽private int defaultWidth = 0;private int defaultHeight = 0;public RoundImageView(Context context) {super(context);mContext = context;}public RoundImageView(Context context, AttributeSet attrs) {super(context, attrs);mContext = context;setCustomAttributes(attrs);}public RoundImageView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);mContext = context;setCustomAttributes(attrs);}private void setCustomAttributes(AttributeSet attrs) {TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.roundedimageview);mBorderThickness = a.getDimensionPixelSize(R.styleable.roundedimageview_border_thickness, 0);mBorderOutsideColor = a.getColor(R.styleable.roundedimageview_border_outside_color, defaultColor);mBorderInsideColor = a.getColor(R.styleable.roundedimageview_border_inside_color, defaultColor);a.recycle();}public static Bitmap drawableToBitmap(Drawable drawable) {try {Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);Canvas canvas = new Canvas(bitmap);// canvas.setBitmap(bitmap);drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());drawable.draw(canvas);return bitmap;} catch (Exception e) {return null;}}private Bitmap getBitmapFromDrawable(Drawable drawable) {if (drawable == null) {return null;}if (drawable instanceof BitmapDrawable) {return ((BitmapDrawable) drawable).getBitmap();}return drawableToBitmap(drawable);}@Overrideprotected void onDraw(Canvas canvas) {Drawable drawable = getDrawable();if (drawable == null) {return;}if (getWidth() <= 0 || getHeight() <= 0) {return;}this.measure(0, 0);// if (drawable.getClass() == NinePatchDrawable.class)// return;// Bitmap b = ((BitmapDrawable) drawable).getBitmap();Bitmap b = getBitmapFromDrawable(drawable);if (b!=null) {Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);if (defaultWidth == 0) {defaultWidth = getWidth();}if (defaultHeight == 0) {defaultHeight = getHeight();}int radius = 0;if (mBorderInsideColor != defaultColor && mBorderOutsideColor != defaultColor) {// 定义画两个边框,分别为外圆边框和内圆边框radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2 - 2 * mBorderThickness;// 画内圆drawCircleBorder(canvas, radius + mBorderThickness / 2, mBorderInsideColor);// 画外圆drawCircleBorder(canvas, radius + mBorderThickness + mBorderThickness / 2, mBorderOutsideColor);} else if (mBorderInsideColor != defaultColor && mBorderOutsideColor == defaultColor) {// 定义画一个边框radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2 - mBorderThickness;drawCircleBorder(canvas, radius + mBorderThickness / 2, mBorderInsideColor);} else if (mBorderInsideColor == defaultColor && mBorderOutsideColor != defaultColor) {// 定义画一个边框radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2 - mBorderThickness;drawCircleBorder(canvas, radius + mBorderThickness / 2, mBorderOutsideColor);} else {// 没有边框radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2;}Bitmap roundBitmap = getCroppedRoundBitmap(bitmap, radius);canvas.drawBitmap(roundBitmap, defaultWidth / 2 - radius, defaultHeight / 2 - radius, null);}}/*** 获取裁剪后的圆形图片* * @param radius*            半径*/public Bitmap getCroppedRoundBitmap(Bitmap bmp, int radius) {Bitmap scaledSrcBmp;int diameter = radius * 2;// 为了防止宽高不相等,造成圆形图片变形,因此截取长方形中处于中间位置最大的正方形图片int bmpWidth = bmp.getWidth();int bmpHeight = bmp.getHeight();int squareWidth = 0, squareHeight = 0;int x = 0, y = 0;Bitmap squareBitmap;if (bmpHeight > bmpWidth) {// 高大于宽squareWidth = squareHeight = bmpWidth;x = 0;y = (bmpHeight - bmpWidth) / 2;// 截取正方形图片squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth, squareHeight);} else if (bmpHeight < bmpWidth) {// 宽大于高squareWidth = squareHeight = bmpHeight;x = (bmpWidth - bmpHeight) / 2;y = 0;squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth, squareHeight);} else {squareBitmap = bmp;}if (squareBitmap.getWidth() != diameter || squareBitmap.getHeight() != diameter) {scaledSrcBmp = Bitmap.createScaledBitmap(squareBitmap, diameter, diameter, true);} else {scaledSrcBmp = squareBitmap;}Bitmap output = Bitmap.createBitmap(scaledSrcBmp.getWidth(), scaledSrcBmp.getHeight(), Config.ARGB_8888);Canvas canvas = new Canvas(output);Paint paint = new Paint();Rect rect = new Rect(0, 0, scaledSrcBmp.getWidth(), scaledSrcBmp.getHeight());paint.setAntiAlias(true);paint.setFilterBitmap(true);paint.setDither(true);canvas.drawARGB(0, 0, 0, 0);canvas.drawCircle(scaledSrcBmp.getWidth() / 2, scaledSrcBmp.getHeight() / 2, scaledSrcBmp.getWidth() / 2,paint);paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));canvas.drawBitmap(scaledSrcBmp, rect, rect, paint);// bitmap回收(recycle导致在布局文件XML看不到效果)// bmp.recycle();// squareBitmap.recycle();// scaledSrcBmp.recycle();bmp = null;squareBitmap = null;scaledSrcBmp = null;return output;}/*** 边缘画圆*/private void drawCircleBorder(Canvas canvas, int radius, int color) {Paint paint = new Paint();/* 去锯齿 */paint.setAntiAlias(true);paint.setFilterBitmap(true);paint.setDither(true);paint.setColor(color);/* 设置paint的 style 为STROKE:空心 */paint.setStyle(Paint.Style.STROKE);/* 设置paint的外框宽度 */paint.setStrokeWidth(mBorderThickness);canvas.drawCircle(defaultWidth / 2, defaultHeight / 2, radius, paint);}}

上面就是自定义的圆形头像,单独用一点儿问题都没有。可以定义白框,切图等,满足大部分圆形头像的需求。使用时,只需要在xml中引用即可。

 <com.android.redwine.ui.RoundImageViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="centerCrop"android:src="@drawable/head_default" />

但上面的自定义有一个很大的缺陷,并且是不可避免的。就是在RecyclerView和ListView中循环显示的时候会出现列表卡顿的十分的严重,并且显示的图片还是出现闪烁问题。闪烁问题我试过网上的各种解决办法:1.设置tag,2、设置默认图等等都不行。因为闪烁问题是ImageView的setImageDrawable导致的,而自定义RoundImageView设置图片也就是通过setImageDrawable来设置的。这就对立了,所以我想能不能换一种方式去显示列表的图片,我找到了。

在RecyclerView和ListView中显示圆形头像

在这里不得不说Glide框架的强大了,Glide中就有直接展示圆形图片的方法:

RoundedBitmapDrawable bitmapDrawable = RoundedBitmapDrawableFactory.create(context.getResources(), resource);bitmapDrawable.setCircular(true);imageView.setImageDrawable(bitmapDrawable);

我们来看看具体的使用:

/***头像,带默认图片的* BitmapImageViewTarget解决自定义圆形头像在RecyclerView中滑动卡顿以及出现闪烁问题* @param context* @param imageView* @param url* @param radius*/public static void initGlideRoundImageHead(Context context, ImageView imageView, String url,final float radius) {if (context!=null) {Glide.with(imageView.getContext()).load(url).asBitmap().placeholder(R.drawable.head_default).transform(new GlideRoundImage(context, radius)).diskCacheStrategy(DiskCacheStrategy.SOURCE).into(new BitmapImageViewTarget(imageView){@Overrideprotected void setResource(Bitmap resource) {RoundedBitmapDrawable bitmapDrawable = RoundedBitmapDrawableFactory.create(context.getResources(), resource);bitmapDrawable.setCircular(true);imageView.setImageDrawable(bitmapDrawable);}});}else {Log.i("Utils.class ", "Picture loading failed,context is null");}}

稍微懂一点儿代码的就能看懂,BitmapImageViewTarget就是用来设置圆形图片的,很简便的方法。这个时候在xml中就不要用自定义的圆形ImageView了,就用普通的ImageView就行。

综上所述,列表中自定义的圆形图片展示导致列表滑动卡顿验证并且闪烁。所以我们在页面上显示普通的圆形图像时,就用我们自定义的ImageView,这样就能自定义圆形的样式,而在列表中还是用普通的ImageView就行,通过Glide的BitmapImageViewTarget去设置圆形图片。这是我项目中的bug,亲测有效。

更多推荐

Android 自定义圆形头像列表展示导致RecyclerView滑动卡顿和闪烁

本文发布于:2024-03-10 03:22:52,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1726884.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:自定义   圆形   头像   列表   Android

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!