Как создать изображение с круглым углом, используя библиотеку volley android

Я получаю URL-адреса изображений с сервера с квадратной формой. Я должен сделать это для изображений с закругленными углами. На самом деле я использую библиотеку залпа, я знаю, как создавать изображения с круглыми углами, используя универсальный загрузчик изображений и библиотеки Пикассо. В библиотеке залпа я устанавливаю изображение в сетевом изображении, таком как setimageUrl, пожалуйста, помогите мне

 holder.ivImage.setImageUrl(url, imageLoader);

person skyshine    schedule 13.08.2014    source источник
comment
Volley — это сетевая библиотека, которая не имеет ничего общего с манипуляциями с изображениями. Проверьте этот ответ: stackoverflow.com/questions/ 16208365/   -  person mata    schedule 13.08.2014
comment
@mata да, но если пользователь использует NetworkImageView из библиотеки volley, ему нужно знать, как манипулировать изображением. Ответ, который вы связали, использует getDrawable() в onDraw() для доступа к изображению, но drawable устанавливается только в том случае, если изображение было установлено из ресурса drawable. В NetworkImageView устанавливается только URL-адрес изображения, и когда изображение завершает загрузку, вызывается setBitmap для установки изображения, а объект рисования не устанавливается.   -  person Siavash    schedule 12.12.2014


Ответы (7)


Я нашел исходный код, который делает изображение округлой формы, например. https://github.com/hdodenhof/CircleImageView. который расширял изображение, я просто расширяю NetworkImageView. У меня все работает нормально. Если вы не хотите использовать вышеуказанное круглое представление изображения, вам необходимо расширить класс NetworkImageView и настроить его в соответствии с вашими потребностями.

person Prashanth Debbadwar    schedule 05.05.2015
comment
Как это было сделано? Вы просто скопировали и вставили код в свой проект? Если да, то как вы ссылались на свой класс в макете xml? - person Brandon; 25.08.2015
comment
Я скопировал код. Я ссылался на это в макете ‹com.gwf.circleview.app.view.Card android:layout_width=wrap_content android:layout_height=wrap_content/› - person Prashanth Debbadwar; 25.08.2015
comment
Это сработало отлично, спасибо Прашант. Затем мне пришлось добавить атрибут xml и разместить его, используя custom:attr_name=attr_value в моем XML. - person Brandon; 26.08.2015
comment
Если это действительно помогло вам, пожалуйста, проголосуйте за ответ. - person Prashanth Debbadwar; 26.08.2015
comment
@PrashanthDebbadwar Вау, я использовал Volley's NetworkImageView и хотел, чтобы он был круглым. Я использую этот класс и extends в NetworkImageView вместо ImageView, и это сработало! Спасибо чувак. . Вы можете принять этот ответ, может быть, вы можете попробовать, как я. @Питер - person GreenROBO; 07.09.2015
comment
Имейте в виду, что CircleImageView поддерживает только CENTER_CROP. и мы не можем это изменить. Он подходит для изображений профиля, но бесполезен, если у вас есть какие-либо другие требования. - person Gem; 30.09.2015
comment
Не могли бы вы ответить на этот вопрос stackoverflow. ком/вопросы/35124025/ - person casillas; 01.02.2016

вам нужно расширить класс NetworkImageView и создать собственное представление

Java: CircularNetworkImageView

import 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);
person kathir    schedule 04.02.2016

Вы можете создать собственный класс, который расширяет NetworkImageView (Volley).

Код

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;
    }
}
person Jinosh P    schedule 02.03.2015
comment
Хотя это может ответить на вопрос, было бы предпочтительнее включить сюда основные части ответа и предоставить ссылку для Справка. - person Nathan Tuggy; 02.03.2015
comment
Да, но только основные части. - person Nathan Tuggy; 02.03.2015
comment
Нужно также указать, как его использовать? - person Jinosh P; 02.03.2015
comment
Это было бы неплохо, но текущий код очень длинный и содержит много в основном нерелевантного кода поддержки; Сокращение его до ключевых разделов было бы очень полезно. - person Nathan Tuggy; 02.03.2015

Вы можете использовать CardView.

<android.support.v7.widget.CardView 
    app:cardCornerRadius="@dimen/spacing_tiny">

    <com.android.volley.toolbox.NetworkImageView>
    ...
    />
</android.support.v7.widget.CardView>
person light    schedule 23.02.2016

Вот как я это сделал:

  • В библиотеке volley скопируйте класс с именем «NetworkImageView» и назовите его «NetworkImageViewCircle».

    private void setAnimateImageBitmap(final Bitmap bitmap, boolean fadeIn) {
    
    final Bitmap bmp;
    
    bmp = Bitmap.createBitmap(bitmap.getWidth(),
            bitmap.getHeight(), Bitmap.Config.ARGB_8888);
    BitmapShader shader = new BitmapShader(bitmap,
            BitmapShader.TileMode.CLAMP,
            BitmapShader.TileMode.CLAMP);
    
    float radius = Math.min(bitmap.getWidth(), bitmap.getHeight()) / 5;
    Canvas canvas = new Canvas(bmp);
    Paint paint = new Paint();
    paint.setAntiAlias(true);
    paint.setShader(shader);
    
    RectF rect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());
    canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2, bitmap.getWidth() / 2, paint);
    .
    .
    .
    

Это помогло мне. Надеюсь, поможет.

person Sha3banly    schedule 18.09.2014

Это сработало для меня

    <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>
person Cedriga    schedule 19.04.2019

Залп не имеет ничего общего с изображением круглого угла.

Вы можете сделать простой круг с белой рамкой и прозрачным содержимым с формой.

// 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>

Затем сделайте список слоев доступным для рисования и поместите его в качестве фона для вашего сетевого изображения.

// 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>

и поместите его в качестве фона для вашего сетевого изображения.

 <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" />

У вас будет что-то подобное.

введите здесь описание изображения

person Deep Shah    schedule 13.08.2014
comment
ваш хардкод ic_launcher.png в img.xm, нам нужно округлить скачанный из сети образ - person Bala Vishnu; 27.08.2014