Как округлить изображение с помощью библиотеки Glide?


198

Итак, кто-нибудь знает, как отобразить изображение с закругленными углами с помощью Glide? Я загружаю изображение с Glide, но я не знаю, как передать округлые параметры в эту библиотеку.

Мне нужно отобразить изображение, как в следующем примере:

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


2
я использую github.com/hdodenhof/CircleImageView для просмотра округлых изображений
MilapTank

1
Я знаю, как использовать Glide lib с CircleImageView, но я ищу возможный способ сделать это только с Glide lib. Есть ли какой-либо метод в Glide lib, чтобы сделать это, или это не поддерживается?
mr.boyfox

Ответы:


491

Glide V4:

    Glide.with(context)
        .load(url)
        .circleCrop()
        .into(imageView);

Glide V3:

Вы можете использовать RoundedBitmapDrawableдля круговых изображений с Glide. Никаких пользовательских ImageView не требуется.

 Glide.with(context).load(url).asBitmap().centerCrop().into(new BitmapImageViewTarget(imageView) {
        @Override
        protected void setResource(Bitmap resource) {
            RoundedBitmapDrawable circularBitmapDrawable =
                    RoundedBitmapDrawableFactory.create(context.getResources(), resource);
            circularBitmapDrawable.setCircular(true);
            imageView.setImageDrawable(circularBitmapDrawable);
        }
    });

6
это не создает границы, хотя.
ZakTaccardi

1
@ jimmy0251 Нет, ты не можешь. Drawables скольжения не являются BitmapDrawables. Это переходные рисунки и скользящие объекты, которые переходят от заполнителя к реальному изображению. RoundedBitmapDrawable не может справиться с этим.
Грег Эннис

7
установить фон с рисованной формы овала. и добавьте отступ для viewview для создания границы.
Лалит Ядав

2
Если у вас возникли проблемы, пожалуйста, проверьте следующее решение Романа Самойленко, что работает.
Pabel

1
Вместо .centerCrop()вас, наверное, имеется в виду.circleCrop()
Танасис Капелонис

66

Проверьте этот пост, скользите против Пикассо ...
Редактировать : связанный пост не вызывает существенного различия в библиотеках. Glide выполняет утилизацию автоматически. Смотрите комментарий TWiStErRob для получения дополнительной информации.

Glide.with(this).load(URL).transform(new CircleTransform(context)).into(imageView);

public static class CircleTransform extends BitmapTransformation {
    public CircleTransform(Context context) {
        super(context);
    }

    @Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        return circleCrop(pool, toTransform);
    }

    private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
        if (source == null) return null;

        int size = Math.min(source.getWidth(), source.getHeight());
        int x = (source.getWidth() - size) / 2;
        int y = (source.getHeight() - size) / 2;

        // TODO this could be acquired from the pool too
        Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);

        Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
        if (result == null) {
            result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
        }

        Canvas canvas = new Canvas(result);
        Paint paint = new Paint();
        paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
        paint.setAntiAlias(true);
        float r = size / 2f;
        canvas.drawCircle(r, r, r, paint);
        return result;
    }

    @Override public String getId() {
        return getClass().getName();
    }
} 

звучит интересно. Хорошо ли это работает с Outline API 21?
Теовалд

хм, я мог бы использовать это тогда. Я попытаюсь просто использовать пользовательский вид, хотя я бы не хотел создавать второе растровое изображение :). Кроме того, вы всегда должны использовать пул растровых изображений, чтобы попытаться получить растровое изображение оттуда :)
Teovald

Остерегайтесь использования public String getId()способа, показанного в коде, поскольку он возвращает один и тот же идентификатор для всех изображений, и, таким образом, может случиться, что глиссад установит старые округленные изображения, а без преобразований установит правильное изображение! Я не знаю, как работает glide, но похоже, что он кеширует преобразования изображений (я полагаю, чтобы избежать сложных вычислений). И идентификатор используется как идентификатор преобразованного изображения. Я добавил URL-адрес изображения в конструктор и сделал упомянутый метод, возвращающий полученный идентификатор, например:this.id = String.format("%s:%s",this.getClass().getSimpleName(),id);
Stan

2
Единственное требование для идентификаторов Transformation заключается в том, что они уникальны среди всех Transformations, поэтому их использование здесь корректно. Ключи кеша будут включать в себя как исходный идентификатор, так и идентификатор преобразования, поэтому идентификатор преобразования является смешанным, а не заменой. См. Github.com/bumptech/glide/wiki/…
Сэм Джадд

4
Есть ли способ применить преобразование к заполнителю?
Синигами

46

Самый простой способ (требуется Glide 4.xx)

Glide.with(context).load(uri).apply(RequestOptions().circleCrop()).into(imageView)

это даже не компилируется ... RequestOptions ()?
Рафаэль Лима

3
@RafaelLima Это написано на Kotlin.
Роман Самойленко

1
Обратите внимание, что .apply()идет после .load().
Джонни

это RequestOptions.circleCropTransform (), а не RequestOptions ().
улыбается

вам нужно написать Glide.with (context) .load (uri) .apply (circleCrop ()). into (imageView) посмотреть на функцию apply.
Джаспал

25

Попробуй так

код

Glide.with(this)
    .load(R.drawable.thumbnail)
    .bitmapTransform(new CropCircleTransformation(this))
    .into(mProfile);

XML

<ImageView
  android:id="@+id/img_profile"
  android:layout_width="76dp"
  android:layout_height="76dp"
  android:background="@drawable/all_circle_white_bg"
  android:padding="1dp"/>

all_circle_white_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item>
    <shape android:shape="oval">
      <solid android:color="@android:color/white"/>
  </shape>
  </item>
</selector>

9

это очень просто, я видел библиотеку Glide, это очень хорошая библиотека и база эссе на библиотеке залпа Google

используйте эту библиотеку для округленного изображения

https://github.com/hdodenhof/CircleImageView

сейчас

// Для простого просмотра:

 @Override
 public void onCreate(Bundle savedInstanceState) {
  ...

  CircleImageView civProfilePic = (CircleImageView)findViewById(R.id.ivProfile);
  Glide.load("http://goo.gl/h8qOq7").into(civProfilePic);
}

// Для списка:

@Override
public View getView(int position, View recycled, ViewGroup container) {
final ImageView myImageView;
 if (recycled == null) {
    myImageView = (CircleImageView) inflater.inflate(R.layout.my_image_view,
            container, false);
} else {
    myImageView = (CircleImageView) recycled;
}

String url = myUrls.get(position);

Glide.load(url)
    .centerCrop()
    .placeholder(R.drawable.loading_spinner)
    .animate(R.anim.fade_in)
    .into(myImageView);

  return myImageView;
}

и в XML

<de.hdodenhof.circleimageview.CircleImageView
   android:id="@+id/ivProfile
   android:layout_width="160dp"
   android:layout_height="160dp"
   android:layout_centerInParent="true"
   android:src="@drawable/hugh"
   app:border_width="2dp"
   app:border_color="@color/dark" />

2
Как упомянуто в предыдущем ответном комментарии, этот способ тоже не работает. По крайней мере, для 'de.hdodenhof: circleimageview: 1.2.2' + 'com.github.bumptech.glide: glide: 3.5.2'. Проверено и дважды проверено. Кроме того , та же проблема с скольжением 3.4 + и circleimageview 1.2.1.
Стан

+1 для .centerCrop (). Работал для меня с DiamondImageView плюс .asBitmap ().
Felippe

1
Требует вызова .dontAnimate () на глиссаде, что недопустимо
Грег Эннис

+1 Но также обратите внимание, что загрузка интернет-изображений с Glide
еж

9

Другие решения не работали для меня. Я обнаружил, что все они имеют существенные недостатки:

  • Решения, использующие преобразования глиссады, не работают с заполнителями
  • Решения, использующие округленные изображения, не работают с анимацией (например, с кроссфейдом)
  • Решения, использующие универсальный метод родителя, который обрезает своих потомков (т.е. принятый здесь ответ ), плохо работают с glide

Действительно интересно, что, возившись с этим, я нашел страницу библиотеки Fresco о закругленных углах и кругах, в которой они перечисляют в основном те же самые ограничения и заканчивают утверждением:

действительно нет хорошего решения для скругления углов на Android, и нужно выбирать между вышеупомянутыми компромиссами

Невероятно, что в настоящее время у нас все еще нет реального решения. У меня есть альтернативное решение, основанное на ссылке, которую я поставил выше. Недостаток этого подхода в том, что он предполагает, что ваш фон является сплошным цветом (углы на самом деле не прозрачные). Вы бы использовали это так:

<RoundedCornerLayout ...>
    <ImageView ...>
</RoundedCornerLayout>

Суть здесь и полный код здесь:

public class RoundedCornerLayout extends RelativeLayout {
    private Bitmap maskBitmap;
    private Paint paint;
    private float cornerRadius;

    public RoundedCornerLayout(Context context) {
        super(context);
        init(context, null, 0);
    }

    public RoundedCornerLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    }

    private void init(Context context, AttributeSet attrs, int defStyle) {
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);

        setWillNotDraw(false);
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);

        if (maskBitmap == null) {
            // This corner radius assumes the image width == height and you want it to be circular
            // Otherwise, customize the radius as needed
            cornerRadius = canvas.getWidth() / 2;
            maskBitmap = createMask(canvas.getWidth(), canvas.getHeight());
        }

        canvas.drawBitmap(maskBitmap, 0f, 0f, paint);
    }

    private Bitmap createMask(int width, int height) {
        Bitmap mask = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(mask);

        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.WHITE); // TODO set your background color as needed

        canvas.drawRect(0, 0, width, height, paint);

        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        canvas.drawRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, paint);

        return mask;
    }
}

6

Теперь в Glide V4 вы можете напрямую использовать CircleCrop ()

Glide.with(fragment)
  .load(url)
  .circleCrop()
  .into(imageView);

Встроенные типы

  • CenterCrop
  • FitCenter
  • CircleCrop

5

Используйте это преобразование, оно будет работать нормально.

public class CircleTransform extends BitmapTransformation {
public CircleTransform(Context context) {
    super(context);
}

@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
    return circleCrop(pool, toTransform);
}

private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
    if (source == null) return null;

    int borderColor = ColorUtils.setAlphaComponent(Color.WHITE, 0xFF);
    int borderRadius = 3;

    int size = Math.min(source.getWidth(), source.getHeight());
    int x = (source.getWidth() - size) / 2;
    int y = (source.getHeight() - size) / 2;

    // TODO this could be acquired from the pool too
    Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);
    if (squared != source) {
        source.recycle();
    }

    Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
    if (result == null) {
        result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
    }

    Canvas canvas = new Canvas(result);
    Paint paint = new Paint();
    paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
    paint.setAntiAlias(true);
    float r = size / 2f;
    canvas.drawCircle(r, r, r, paint);

    // Prepare the background
    Paint paintBg = new Paint();
    paintBg.setColor(borderColor);
    paintBg.setAntiAlias(true);

    // Draw the background circle
    canvas.drawCircle(r, r, r, paintBg);

    // Draw the image smaller than the background so a little border will be seen
    canvas.drawCircle(r, r, r - borderRadius, paint);

    squared.recycle();

    return result;
}

@Override
public String getId() {
    return getClass().getName();
}} 

5

Для Glide 4.xx

использование

Glide
  .with(context)
  .load(uri)
  .apply(
      RequestOptions()
        .circleCrop())
  .into(imageView)

из документа он заявил, что

Округлые изображения: известно, что у CircleImageView / CircularImageView / RoundedImageView есть проблемы с TransitionDrawable (.crossFade () с .thumbnail () или .placeholder ()) и анимированными GIF- файлами , используйте BitmapTransformation (.circleCrop () будет доступно в v4) или .dontAnimate (), чтобы исправить проблему


4

Согласно этому ответу, самый простой способ на обоих языках:

Котлин:

Glide.with(context).load(uri).apply(RequestOptions().circleCrop()).into(imageView)

Ява:

Glide.with(context).load(uri).apply(new RequestOptions().circleCrop()).into(imageView)

Это работает на Glide 4.XX


4

Ответ Романа Самойленко был верным, за исключением того, что функция изменилась. Правильный ответ

Glide.with(context)
                .load(yourImage)
                .apply(RequestOptions.circleCropTransform())
                .into(imageView);

3

Я нашел одно простое и простое решение для добавления границы над изображением, в котором цвет хотите установить или добавить градиент над изображением.

ШАГИ:

  1. Возьмите один макет кадра и добавьте два изображения. Вы можете установить размер согласно вашему требованию. Для imgPlaceHolder, вам нужно одно белое изображение или цвет, который вы хотите установить.

        <ImageView
            android:id="@+id/imgPlaceHolder"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:src="@drawable/white_bg"/>

        <ImageView
            android:id="@+id/imgPic"
            android:layout_width="190dp"
            android:layout_height="190dp"
            android:layout_gravity="center"
            android:src="@drawable/image01"/>
    </FrameLayout>
  1. Поместив этот код в файл XML, поместите строку ниже в файл Java.

    Glide.with(this).load(R.drawable.image01).asBitmap().centerCrop().into(new BitmapImageViewTarget(imgPic) {
        @Override
        protected void setResource(Bitmap resource) {
            RoundedBitmapDrawable circularBitmapDrawable =
                    RoundedBitmapDrawableFactory.create(getResources(), resource);
            circularBitmapDrawable.setCircular(true);
            imageView.setImageDrawable(circularBitmapDrawable);
        }
    });
    
    Glide.with(this).load(R.drawable.white_bg).asBitmap().centerCrop().into(new BitmapImageViewTarget(imgPlaceHolder) {
        @Override
        protected void setResource(Bitmap resource) {
            RoundedBitmapDrawable circularBitmapDrawable =
                    RoundedBitmapDrawableFactory.create(getResources(), resource);
            circularBitmapDrawable.setCircular(true);
            imgTemp2.setImageDrawable(circularBitmapDrawable);
        }
    });

Это сделает границы изображения просто без каких-либо дополнительных отступов и полей.

ПРИМЕЧАНИЕ . Белое изображение обязательно для рамки, иначе оно не будет работать.

Удачной кодировки :)


3

С библиотекой glide вы можете использовать этот код:

Glide.with(context)
    .load(imageUrl)
    .asBitmap()
    .placeholder(R.drawable.user_pic)
    .centerCrop()
    .into(new BitmapImageViewTarget(img_profPic) {
        @Override
        protected void setResource(Bitmap resource) {
            RoundedBitmapDrawable circularBitmapDrawable = RoundedBitmapDrawableFactory.create(context.getResources(), resource);

            circularBitmapDrawable.setCircular(true);
            img_profPic.setImageDrawable(circularBitmapDrawable);
        }
    });

Вы также можете сделать округленное изображение, используя библиотеку Glid.
Прити

2

Я искал это раньше и сделал это очень просто, надеюсь, вам понравится.

 //crete this method into your Utils class and call this method wherever you want to use.
    //you can set these placeHolder() and error() image static as well. I made it as comment inside this method, then no need to use [placeHolderUrl and errorImageUrl] parameters. remove it from this method.
    public static void loadImage(final Activity context, ImageView imageView, String url, int placeHolderUrl, int errorImageUrl) {
        if (context == null || context.isDestroyed()) return;

        //placeHolderUrl=R.drawable.ic_user;
        //errorImageUrl=R.drawable.ic_error;
            Glide.with(context) //passing context
                    .load(getFullUrl(url)) //passing your url to load image.
                    .placeholder(placeHolderUrl) //this would be your default image (like default profile or logo etc). it would be loaded at initial time and it will replace with your loaded image once glide successfully load image using url.
                    .error(errorImageUrl)//in case of any glide exception or not able to download then this image will be appear . if you won't mention this error() then nothing to worry placeHolder image would be remain as it is.
                    .diskCacheStrategy(DiskCacheStrategy.ALL) //using to load into cache then second time it will load fast.
                    .transform(new CircleTransform(context))//this CircleTransform class help to crop an image as circle.
                    .animate(R.anim.fade_in) // when image (url) will be loaded by glide then this face in animation help to replace url image in the place of placeHolder (default) image.
                    .fitCenter()//this method help to fit image into center of your ImageView
                    .into(imageView); //pass imageView reference to appear the image.
    } 

CircleTransform.java

  public class CircleTransform extends BitmapTransformation {
    public CircleTransform(Context context) {
        super(context);

        if(context==null)
            return;
    }

    private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
        if (source == null) return null;

        int size = Math.min(source.getWidth(), source.getHeight());
        int x = (source.getWidth() - size) / 2;
        int y = (source.getHeight() - size) / 2;


        Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);

        Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
        if (result == null) {
            result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
        }

        Canvas canvas = new Canvas(result);
        Paint paint = new Paint();
        paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
        paint.setAntiAlias(true);
        float r = size / 2f;
        canvas.drawCircle(r, r, r, paint);
        return result;
    }

    @Override
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        return circleCrop(pool, toTransform);
    }

    @Override
    public String getId() {
        return getClass().getName();
    }
}

fade_in.xml для затухания в анимации.

    <set xmlns:android="http://schemas.android.com/apk/res/android">
<!--THIS ANIMATION IS USING FOR FADE IN -->

<alpha
    android:duration="800"
    android:fromAlpha="0.0"
    android:interpolator="@android:anim/decelerate_interpolator"
    android:toAlpha="1.0" />

наконец, чтобы вызвать этот метод.

Utils.loadImage(YourClassName.this,mImageView,url,R.drawable.ic_user,R.drawable.ic_error);

2

Вы можете просто вызвать конструктор RoundedCornersTransformation, у которого есть ввод перечисления cornerType. Как это:

Glide.with(context)
            .load(bizList.get(position).getCover())
            .bitmapTransform(new RoundedCornersTransformation(context,20,0, RoundedCornersTransformation.CornerType.TOP))
            .into(holder.bizCellCoverImg);

но сначала вы должны добавить Glide Transformations в ваш проект.


2

Вот более модульный и более чистый способ обрезать круговую картинку в Glide:

  1. Создайте пользовательское преобразование, расширив BitmapTransformationзатем transformметод переопределения следующим образом:

Для Glide 4.xx

public class CircularTransformation extends BitmapTransformation {

@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
    RoundedBitmapDrawable circularBitmapDrawable =
            RoundedBitmapDrawableFactory.create(null, toTransform);
    circularBitmapDrawable.setCircular(true);
    Bitmap bitmap = pool.get(outWidth, outHeight, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    circularBitmapDrawable.setBounds(0, 0, outWidth, outHeight);
    circularBitmapDrawable.draw(canvas);
    return bitmap;
    }

@Override
public void updateDiskCacheKey(MessageDigest messageDigest) {}

}

Для Glide 3.xx

public class CircularTransformation extends BitmapTransformation {

@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
    RoundedBitmapDrawable circularBitmapDrawable =
            RoundedBitmapDrawableFactory.create(null, toTransform);
    circularBitmapDrawable.setCircular(true);
    Bitmap bitmap = pool.get(outWidth, outHeight, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    circularBitmapDrawable.setBounds(0, 0, outWidth, outHeight);
    circularBitmapDrawable.draw(canvas);
    return bitmap;
    }

@Override
public String getId() {
    // Return some id that uniquely identifies your transformation.
    return "CircularTransformation";
    }

}
  1. Затем установите его в Glide Builder, где вам это нужно:
Glide.with(yourActivity)
   .load(yourUrl)
   .asBitmap()
   .transform(new CircularTransformation())
   .into(yourView);

Надеюсь это поможет :)


2
private void setContactImage(@NonNull ViewHolder holder, ClsContactDetails clsContactDetails) {
    Glide.with(context).load(clsContactDetails.getPic())
        .apply(new RequestOptions().centerCrop().circleCrop().placeholder(R.mipmap.ic_launcher)).into(holder.ivPersonImage);
}

2
implementation 'com.github.bumptech.glide:glide:4.8.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'


RequestOptions options=new RequestOptions();
        options.centerCrop().placeholder(getResources().getDrawable(R.drawable.user_placeholder));
        Glide.with(this)
                .load(preferenceSingleTon.getImage())
                .apply(options)
                .into(ProfileImage);

2

Круг на полях + заполнитель + перекрестное затухание

 Glide.with(context!!)
                    .load(randomImage)
                    .apply(RequestOptions.bitmapTransform(CircleCrop()).error(R.drawable.nyancat_animated))
                    .transition(DrawableTransitionOptions()
                            .crossFade())
                    .into(picture)

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


1

Glide версия 4.6.1

Glide.with(context)
.load(url)
.apply(RequestOptions.bitmapTransform(new CircleCrop()))
.into(imageView);

1

В этом случае мне нужно добавить тени, а высота изображения не работает

реализация "com.github.bumptech.glide: glide: 4.10.0"

XML

<FrameLayout
    android:id="@+id/fl_image"
    android:layout_width="60dp"
    android:layout_height="60dp"
    android:layout_margin="10dp"
    android:background="@drawable/card_circle_background"
    android:elevation="8dp">

    <ImageView
        android:id="@+id/iv_item_employee"
        android:layout_width="60dp"
        android:layout_height="60dp"
        tools:background="@color/colorPrimary" />
</FrameLayout>

Форма нарисованная

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="oval">
     <solid android:color="@color/white"/>
</shape>

Конфигурация Glide

Glide.with(this)
    .asBitmap()
    .load(item.image)
    .apply(RequestOptions.circleCropTransform())
    .into(iv_item_employee)

0

Вы должны использовать CircularImageView для отображения этого типа изображения ...

Вы используете библиотеку Glide которая использовалась для загрузки изображений.

Создайте один ClassFile в своем проекте и загрузите его в Imageview ... и вы получите желаемый результат ...

Попробуйте следующий код ...

XML

 <com.yourpackage.CircularImageView
    android:id="@+id/imageview"
    android:layout_width="96dp"
    android:layout_height="96dp"
    app:border="true"
    app:border_width="3dp"
    app:border_color="@color/white"
    android:src="@drawable/image" />

CircularImageView.java

public class CircularImageView extends ImageView {
    private int borderWidth;
    private int canvasSize;
    private Bitmap image;
    private Paint paint;
    private Paint paintBorder;

    public CircularImageView(final Context context) {
        this(context, null);
    }

    public CircularImageView(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.circularImageViewStyle);
    }

    public CircularImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        // init paint
        paint = new Paint();
        paint.setAntiAlias(true);

        paintBorder = new Paint();
        paintBorder.setAntiAlias(true);

        // load the styled attributes and set their properties
        TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.CircularImageView, defStyle, 0);

        if(attributes.getBoolean(R.styleable.CircularImageView_border, true)) {
            int defaultBorderSize = (int) (4 * getContext().getResources().getDisplayMetrics().density + 0.5f);
            setBorderWidth(attributes.getDimensionPixelOffset(R.styleable.CircularImageView_border_width, defaultBorderSize));
            setBorderColor(attributes.getColor(R.styleable.CircularImageView_border_color, Color.WHITE));
        }

        if(attributes.getBoolean(R.styleable.CircularImageView_shadow, false))
            addShadow();
    }

    public void setBorderWidth(int borderWidth) {
        this.borderWidth = borderWidth;
        this.requestLayout();
        this.invalidate();
    }

    public void setBorderColor(int borderColor) {
        if (paintBorder != null)
            paintBorder.setColor(borderColor);
        this.invalidate();
    }

    public void addShadow() {
        setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
        paintBorder.setShadowLayer(4.0f, 0.0f, 2.0f, Color.BLACK);
    }

    @Override
    public void onDraw(Canvas canvas) {
        // load the bitmap
        image = drawableToBitmap(getDrawable());

        // init shader
        if (image != null) {

            canvasSize = canvas.getWidth();
            if(canvas.getHeight()<canvasSize)
                canvasSize = canvas.getHeight();

            BitmapShader shader = new BitmapShader(Bitmap.createScaledBitmap(image, canvasSize, canvasSize, false), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            paint.setShader(shader);

            // circleCenter is the x or y of the view's center
            // radius is the radius in pixels of the cirle to be drawn
            // paint contains the shader that will texture the shape
            int circleCenter = (canvasSize - (borderWidth * 2)) / 2;
            canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) + borderWidth - 4.0f, paintBorder);
            canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) - 4.0f, paint);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = measureWidth(widthMeasureSpec);
        int height = measureHeight(heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

    private int measureWidth(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            // The parent has determined an exact size for the child.
            result = specSize;
        } else if (specMode == MeasureSpec.AT_MOST) {
            // The child can be as large as it wants up to the specified size.
            result = specSize;
        } else {
            // The parent has not imposed any constraint on the child.
            result = canvasSize;
        }

        return result;
    }

    private int measureHeight(int measureSpecHeight) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpecHeight);
        int specSize = MeasureSpec.getSize(measureSpecHeight);

        if (specMode == MeasureSpec.EXACTLY) {
            // We were told how big to be
            result = specSize;
        } else if (specMode == MeasureSpec.AT_MOST) {
            // The child can be as large as it wants up to the specified size.
            result = specSize;
        } else {
            // Measure the text (beware: ascent is a negative number)
            result = canvasSize;
        }

        return (result + 2);
    }

    public Bitmap drawableToBitmap(Drawable drawable) {
        if (drawable == null) {
            return null;
        } else if (drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable) drawable).getBitmap();
        }

        Bitmap 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);

        return bitmap;
    }
}

Примечание :

Ты можешь использовать

CircularImageView imgIcon = (CircularImageView)findViewById(R.id.imageview);

или

ImageView imgIcon = (ImageView)findViewById(R.id.imageview);

это не повлияет на другие ваши библиотеки ... вам не нужно менять код для загрузки изображения или чего-то еще ... его просто можно определить с помощью XML тоже ...


3
Я пробовал Glide + CircularImageView (и RoundedImageView), и он не работает должным образом, если вы начинаете использовать заполнитель (в то время как изображение загружается) и анимацию внешнего вида. Пикассо не имеет этой проблемы. Вы можете узнать больше об этом здесь: github.com/vinc3m1/RoundedImageView/issues/76
zmicer

Просто используйте .asBitmap в вызове Glide, и он будет работать нормально.
granko87

Требует вызова .dontAnimate () на глиссаде, что недопустимо
Грег Эннис
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.