我从服务器获取的图像 URL 是方形的,我需要将它们变成圆角图像。实际上,我正在使用 Volley 库,我知道如何使用 Universal Image Loader 和 Picasso 库创建圆角图像。在 Volley 库中,我使用 setimageUrl 将图像设置到网络 ImageView 中,请帮助我。
holder.ivImage.setImageUrl(url, imageLoader);
我从服务器获取的图像 URL 是方形的,我需要将它们变成圆角图像。实际上,我正在使用 Volley 库,我知道如何使用 Universal Image Loader 和 Picasso 库创建圆角图像。在 Volley 库中,我使用 setimageUrl 将图像设置到网络 ImageView 中,请帮助我。
holder.ivImage.setImageUrl(url, imageLoader);
我找到了一份源代码,可以让ImageView变成圆角形状,例如https://github.com/hdodenhof/CircleImageView 。 它是继承自ImageView的,我只是将其改为了继承NetworkImageView。 一切运作良好。如果您不想使用上面提供的圆形图片视图,则必须扩展NetworkImageView类并进行自定义以满足您的需求。
extends
到 NetworkImageView
而不是 ImageView
,然后它就起作用了!谢谢你啊。
。
你可以接受这个答案,也许你可以像我一样尝试一下。@Peter - GreenROBOimport android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import com.android.volley.toolbox.NetworkImageView;
public class CircularNetworkImageView extends NetworkImageView {
Context mContext;
public CircularNetworkImageView(Context context) {
super(context);
mContext = context;
}
public CircularNetworkImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
mContext = context;
}
public CircularNetworkImageView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
mContext = context;
}
@Override
public void setImageBitmap(Bitmap bm) {
if(bm==null) return;
setImageDrawable(new BitmapDrawable(mContext.getResources(),
getCircularBitmap(bm)));
}
/**
* Creates a circular bitmap and uses whichever dimension is smaller to determine the width
* <br/>Also constrains the circle to the leftmost part of the image
*
* @param bitmap
* @return bitmap
*/
public Bitmap getCircularBitmap(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
int width = bitmap.getWidth();
if(bitmap.getWidth()>bitmap.getHeight())
width = bitmap.getHeight();
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, width, width);
final RectF rectF = new RectF(rect);
final float roundPx = width / 2;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
}
XML
<com.example.own.CircularNetworkImageView
android:id="@+id/image"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginRight="10dp"/>
用法:
CircularNetworkImageView image = (CircularNetworkImageView) view.findViewById(R.id.image);
private ImageLoader netImageLoader=AppController.getInstance().getImageLoader();
image.setImageUrl("imageurl", netImageLoader);
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageLoader.ImageContainer;
import com.android.volley.toolbox.ImageLoader.ImageListener;
import java.lang.reflect.InvocationTargetException;
/**
* Handles fetching an image from a URL as well as the life-cycle of the
* associated request.
*/
public class CircledNetworkImageView extends ImageView {
public boolean mCircled;
/** The URL of the network image to load */
private String mUrl;
/**
* Resource ID of the image to be used as a placeholder until the network image is loaded.
*/
private int mDefaultImageId;
/**
* Resource ID of the image to be used if the network response fails.
*/
private int mErrorImageId;
/** Local copy of the ImageLoader. */
private ImageLoader mImageLoader;
/** Current ImageContainer. (either in-flight or finished) */
private ImageContainer mImageContainer;
public CircledNetworkImageView(Context context) {
this(context, null);
}
public CircledNetworkImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircledNetworkImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* Sets URL of the image that should be loaded into this view. Note that calling this will
* immediately either set the cached image (if available) or the default image specified by
* {@link CircledNetworkImageView#setDefaultImageResId(int)} on the view.
*
* NOTE: If applicable, {@link CircledNetworkImageView#setDefaultImageResId(int)} and
* {@link CircledNetworkImageView#setErrorImageResId(int)} should be called prior to calling
* this function.
*
* @param url The URL that should be loaded into this ImageView.
* @param imageLoader ImageLoader that will be used to make the request.
*/
public void setImageUrl(String url, ImageLoader imageLoader) {
mUrl = url;
mImageLoader = imageLoader;
// The URL has potentially changed. See if we need to load it.
loadImageIfNecessary(false);
}
/**
* Sets the default image resource ID to be used for this view until the attempt to load it
* completes.
*/
public void setDefaultImageResId(int defaultImage) {
mDefaultImageId = defaultImage;
}
/**
* Sets the error image resource ID to be used for this view in the event that the image
* requested fails to load.
*/
public void setErrorImageResId(int errorImage) {
mErrorImageId = errorImage;
}
/**
* Loads the image for the view if it isn't already loaded.
* @param isInLayoutPass True if this was invoked from a layout pass, false otherwise.
*/
private void loadImageIfNecessary(final boolean isInLayoutPass) {
int width = getWidth();
int height = getHeight();
boolean isFullyWrapContent = getLayoutParams() != null
&& getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT
&& getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT;
// if the view's bounds aren't known yet, and this is not a wrap-content/wrap-content
// view, hold off on loading the image.
if (width == 0 && height == 0 && !isFullyWrapContent) {
return;
}
// if the URL to be loaded in this view is empty, cancel any old requests and clear the
// currently loaded image.
if (TextUtils.isEmpty(mUrl)) {
if (mImageContainer != null) {
mImageContainer.cancelRequest();
mImageContainer = null;
}
setImageBitmap(null);
return;
}
// if there was an old request in this view, check if it needs to be canceled.
if (mImageContainer != null && mImageContainer.getRequestUrl() != null) {
if (mImageContainer.getRequestUrl().equals(mUrl)) {
// if the request is from the same URL, return.
return;
} else {
// if there is a pre-existing request, cancel it if it's fetching a different URL.
mImageContainer.cancelRequest();
setImageBitmap(null);
}
}
// The pre-existing content of this view didn't match the current URL. Load the new image
// from the network.
ImageContainer newContainer = mImageLoader.get(mUrl,
new ImageListener() {
@Override
public void onErrorResponse(VolleyError error) {
if (mErrorImageId != 0) {
setImageResource(mErrorImageId);
}
}
@Override
public void onResponse(final ImageContainer response, boolean isImmediate) {
// If this was an immediate response that was delivered inside of a layout
// pass do not set the image immediately as it will trigger a requestLayout
// inside of a layout. Instead, defer setting the image by posting back to
// the main thread.
if (isImmediate && isInLayoutPass) {
post(new Runnable() {
@Override
public void run() {
onResponse(response, false);
}
});
return;
}
if (response.getBitmap() != null) {
setImageBitmap(response.getBitmap());
} else if (mDefaultImageId != 0) {
setImageResource(mDefaultImageId);
}
}
});
// update the ImageContainer to be the new bitmap container.
mImageContainer = newContainer;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
loadImageIfNecessary(true);
}
@Override
protected void onDetachedFromWindow() {
if (mImageContainer != null) {
// If the view was bound to an image request, cancel it and clear
// out the image from the view.
mImageContainer.cancelRequest();
setImageBitmap(null);
// also clear out the container so we can reload the image if necessary.
mImageContainer = null;
}
super.onDetachedFromWindow();
}
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
invalidate();
}
/**
* In case the bitmap is manually changed, we make sure to
* circle it on the next onDraw
*/
@Override
public void setImageBitmap(Bitmap bm) {
mCircled = false;
super.setImageBitmap(bm);
}
/**
* In case the bitmap is manually changed, we make sure to
* circle it on the next onDraw
*/
@Override
public void setImageResource(int resId) {
mCircled = false;
super.setImageResource(resId);
}
/**
* In case the bitmap is manually changed, we make sure to
* circle it on the next onDraw
*/
@Override
public void setImageDrawable(Drawable drawable) {
mCircled = false;
super.setImageDrawable(drawable);
}
/**
* We want to make sure that the ImageView has the same height and width
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Drawable drawable = getDrawable();
if (drawable != null) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int diw = drawable.getIntrinsicWidth();
if (diw > 0) {
int height = width * drawable.getIntrinsicHeight() / diw;
setMeasuredDimension(width, height);
} else
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} else
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
//Let's circle the image
if ( !mCircled && getDrawable() != null) {
Drawable d = getDrawable();
try {
//We use reflection here in case that the drawable isn't a
//BitmapDrawable but it contains a public getBitmap method.
Bitmap bitmap = (Bitmap) d.getClass().getMethod("getBitmap").invoke(d);
if(bitmap != null){
Bitmap circleBitmap = getCircleBitmap(bitmap);
setImageBitmap(circleBitmap);
}
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
} catch (NoSuchMethodException e) {
//Seems like the current drawable is not a BitmapDrawable or
//that is doesn't have a public getBitmap() method.
}
//Mark as circled even if it failed, because if it fails once,
//It will fail again.
mCircled = true;
}
super.onDraw(canvas);
}
/**
* Method used to circle a bitmap.
*
* @param bitmap The bitmap to circle
* @return The circled bitmap
*/
public static Bitmap getCircleBitmap(Bitmap bitmap) {
int size = Math.min(bitmap.getWidth(), bitmap.getHeight());
Bitmap output = Bitmap.createBitmap(size,
size, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
BitmapShader shader;
shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP,
Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(shader);
RectF rect = new RectF(0, 0 ,size,size);
int radius = size/2;
canvas.drawRoundRect(rect, radius,radius, paint);
return output;
}
}
<android.support.v7.widget.CardView
app:cardCornerRadius="@dimen/spacing_tiny">
<com.android.volley.toolbox.NetworkImageView>
...
/>
</android.support.v7.widget.CardView>
我能够制作圆形 NetworkImage 而不需要扩展 NetworkImage
<androidx.cardview.widget.CardView
android:id="@+id/myCardVi"
android:layout_width="188dp"
android:layout_height="188dp"
android:layout_centerHorizontal="true"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:alpha="0.95"
android:elevation="12dp"
android:innerRadius="0dp"
app:cardBackgroundColor="@color/white"
app:cardCornerRadius="94dp"
app:cardElevation="8dp">
<androidx.cardview.widget.CardView
android:id="@+id/myCardVie"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_margin="10dp"
android:alpha="0.95"
android:elevation="12dp"
android:innerRadius="0dp"
app:cardBackgroundColor="@color/cardview_dark_background"
app:cardCornerRadius="89dp"
app:cardElevation="8dp">
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/imageView"
android:layout_width="178dp"
android:layout_height="178dp"
android:scaleType="fitXY"
/>
</androidx.cardview.widget.CardView>
</androidx.cardview.widget.CardView>
这是我的做法:
在volley库中,复制名为“NetworkImageView”的类并将其命名为“NetworkImageViewCircle”。 private void setAnimateImageBitmap(final Bitmap bitmap, boolean fadeIn) {这对我很有帮助,希望它也能帮到你。
那对我有效
<android.support.v7.widget.CardView
android:id="@+id/container"
android:layout_width="80dp"
android:layout_height="80dp"
app:cardCornerRadius="5dp"
app:cardElevation="0dp" >
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/thumb"
android:layout_width="80dp"
android:layout_height="80dp"/>
</android.support.v7.widget.CardView>
Volley与圆角图片无关。
您可以使用shape制作具有白色边框和透明内容的简单圆形。
//res / drawable / circle.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="0dp"
android:shape="ring"
android:thicknessRatio="1.9"
android:useLevel="false" >
<solid android:color="@android:color/transparent" />
<stroke
android:width="10dp"
android:color="@android:color/white" />
</shape>
然后创建一个LayerList Drawable,并将其设置为NetworkImageView的背景。
// res/drawable/img.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/ic_launcher"/>
<item android:drawable="@drawable/circle"/>
</layer-list>
并将其作为背景放置在您的NetworkImageView上。
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/networkImageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:background="@drawable/img"
android:src="@drawable/ic_launcher" />
你会得到类似这样的东西。