Як зробити ImageView із закругленими кутами?


573

В Android ImageView за замовчуванням є прямокутником. Як я можу зробити закруглений прямокутник (відрізати всі 4 кути моєї бітової карти, щоб бути закругленими прямокутниками) у ImageView?


Це може бути корисно stackoverflow.com/questions/26850780/…
Mangesh

Приховані нижче старіші, складніші відповіді - це, на мою думку, зараз має бути прийнята відповідь: RoundedBitmapDravable , доданий у версії бібліотеки підтримки версії 21.
Jonik,

Ви можете зробити це самий простий спосіб просто використовуючи CardView з ImageView всередині - дивись приклад тут stackoverflow.com/a/41479670/4516797
Тарас Vovkovych

Ця бібліотека дуже корисна.
grrigore

Перевірте це зараз ми повинні ShapeableImageViewзробити круглу або закруглену ImageView stackoverflow.com/a/61086632/7666442
Nilesh Rathod

Відповіді:


544

Це досить пізно у відповідь, але для тих, хто шукає цього, ви можете зробити наступний код, щоб вручну обвести кути ваших зображень.

http://www.ruibm.com/?p=184

Це не мій код, але я його використав, і він чудово працює. Я використовував його як помічник у класі ImageHelper і розширив його трохи, щоб передати кількість пір'я, що мені потрібно для даного зображення.

Кінцевий код виглядає приблизно так:

package com.company.app.utils;

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;

public class ImageHelper {
    public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap
                .getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        final RectF rectF = new RectF(rect);
        final float roundPx = pixels;

        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;
    }
}

Сподіваюся, це допоможе комусь!


4
Він не працює на всіх пристроях. Чи потрібно мені десь змінити?
Spring Breaker

7
На це потрібно майже 0,03 секунди, щоб зробити це для картини 200 * 200, тому я думаю, що це не найкраще рішення.
Джекі

2
Він обводить лише верхній лівий і верхній правий кути. Чому?
Prateek

1
@ vinc3m1 рішення тут github.com/makeramen/RoundedImageView працює дуже добре! також бачити його відповідь ( stackoverflow.com/a/15032283/2048266 )
nommer

16
Не працює добре, коли намагається встановити масштаб зображення, перегляньте зображення, працює лише fitXY, центрCrop та інші показують непередбачувані результати, у когось тут виникають ті самі проблеми?
Шиванш

211

Хоча вищезазначена відповідь працює, Ромен Гай (основний розробник Android) показує кращий метод у своєму блозі, який використовує менше пам’яті, використовуючи шейдер, не створюючи копію растрової карти. Загальна суть функціоналу тут:

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.0f, 0.0f, width, height);

// rect contains the bounds of the shape
// radius is the radius in pixels of the rounded corners
// paint contains the shader that will texture the shape
canvas.drawRoundRect(rect, radius, radius, paint);

Перевагами цього методу перед іншими методами є те, що він:

  • не створює окрему копію растрової карти, яка використовує багато пам'яті з великими зображеннями [проти більшості інших відповідей тут]
  • підтримує антиалізинг [метод clipPath]
  • підтримує альфа [проти xfermode + метод porterduff]
  • підтримує апаратне прискорення [метод clipPath]
  • малює лише один раз на полотні [проти методів xfermode та clippath]

Я створив RoundedImageView на основі цього коду, який обертає цю логіку у ImageView і додає належну ScaleTypeпідтримку та необов'язковий округлий кордон.


у своєму / example / res / layout / rounded_item.xml чому ви вказуєте src зображення, коли всі ваші джерела жорстко кодуються? Хороша демонстрація, просто спосіб перевиконання.
Хтось десь

ваш зразок має серйозну проблему з пам'яттю, як і оригінальний зразок Ромена Гая. Я досі не знаю, що це викликає, але, як і його код, це справді важко знайти. Якщо ви не можете побачити збій у програмі через OOM, ви можете повертати програму кілька разів, поки вона не відбудеться (залежить від вашого пристрою, ПЗУ тощо). Я про це раніше повідомляв тут: stackoverflow.com/questions/14109187/…
андроїд розробник

1
Ніхто інший не повідомляє про проблему з пам'яттю, тому це повинно бути щось, що ви робите поза кодом, неправильним. Приклад правильно містить обмежений набір растрових зображень в адаптері, не відтворюючи їх кожен раз, коли малюється вид. Наведений тут приклад - фрагмент методу draw () у програмі Dravable, який використовує посилання на оригінальну растрову карту, яку він містить і працює правильно. Це не призначене для зміни оригінальної растрової карти, а лише візуалізацію закругленими кутами. Центральний урожай добре працює і в прикладі.
vinc3m1

1
Якщо ви можете надати скріншоти чи пристрої там, де це не працює, або навіть зайти на прохання виправити і витягнути запит, це було б найбільш продуктивним. Я перевіряв обертання кілька разів на своїх пристроях, і пам'ять залишається однаковою.
vinc3m1

11
Зауважте, що воно не працюватиме, якщо розмір зображення перевищує 2048 пікселів. Шейдер не підтримує, щоб текстура була більшою за нього.
Габор

209

Ще один простий спосіб - використовувати CardView з радіусом кута та ImageView всередині:

  <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:cardCornerRadius="8dp"
            android:layout_margin="5dp"
            android:elevation="10dp">

            <ImageView
                android:id="@+id/roundedImageView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:src="@drawable/image"
                android:background="@color/white"
                android:scaleType="centerCrop"
                />
        </android.support.v7.widget.CardView>

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


5
Здається, хороший спосіб вирішення. Але він не відсікає зображення на попередніх Lollipops.
Микола

1
Що робити, якщо ми хочемо лише радіус у верхньому лівому та верхньому правому кутах, а не у всіх кутах?
Пратік Сінгал

3
Дуже простий та розумний спосіб застосувати межу кривої в будь-якому режимі.
АМІ ЧАРАДАВА

1
Хороше рішення, але піднесення підтримується лише на рівні api 21 і вище
Саад Білал

1
Щоб вимкнути піднесення картки, використовуйте додаток: cardElevation = "0dp" (не android: elevation)
Джонні П'ять,

148

Відсікання до округлих фігур було додано до Viewкласу в API 21.

Просто зробіть це:

  • Створіть закруглену форму, що можна намалювати, приблизно так:

res / dravable / round_outline.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="10dp" />
    ...
</shape>
  • Встановіть рисунок як тло вашого ImageView: android:background="@drawable/round_outline"
  • Відповідно до цієї документації , тоді все, що вам потрібно зробити, - це додатиandroid:clipToOutline="true"

На жаль, є помилка, і цей атрибут XML не розпізнається. На щастя, ми все ще можемо налаштувати відсікання на Java:

  • У вашій діяльності або фрагменті: ImageView.setClipToOutline(true)

Ось як це буде виглядати:

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

Примітка:

Цей метод працює для будь-якої форми, що малюється (не тільки округлої форми). Він зафіксує ImageView до будь-якого контуру форми, який ви визначили у своєму Dravable xml.

Спеціальна примітка про ImageViews

setClipToOutline()працює лише тоді, коли фон перегляду встановлений у формі, що малюється. Якщо така форма фону є, View розглядає обриси фігури як рамки для вирізання і затінення.

Це означає, що якщо ви хочете використовувати setClipToOutline()для округлення кутів на ImageView, ваше зображення потрібно встановити android:srcзамість android:background(оскільки фон повинен бути встановлений на вашу округлу форму). Якщо ОБОВ'ЯЗКОВО використовувати фон для встановлення зображення замість src, ви можете скористатися цим способом:

  • Створіть макет і встановіть його фон для вашої форми, що малюється
  • Оберніть цей макет навколо свого ImageView (без прокладки)
  • ImageView (включаючи все інше в макеті) тепер відображатиметься із закругленою формою макета.

10
Помилка: (x) Не знайдено ідентифікатор ресурсу для атрибута 'clipToOutline' в пакеті 'android'
Anu Martin

7
Натомість android:clipToOutlineтреба використовувати android:outlineProvider="background".
WindRider

2
Ще одна причина, по якій я так сильно люблю Google, - це те, що ця помилка майже мого віку і все ще мешкає в її маленькому світі. Google, схоже, не дає нічого про це *)
Farid

1
Здається, я не маю успіху з цим методом, коли я встановив лише топлефт і topRight кут у фоновій формі на закруглений.
Peterdk

@AnuMartin це відоме питання - issueetracker.google.com/isissue/37036728
Котов

132

В v21 бібліотеки підтримки тепер є рішення цього питання: воно називається RoundedBitmapDravable .

Це в основному як звичайний Dravable, за винятком того, що ви надаєте йому кутовий радіус для відсікання за допомогою:

setCornerRadius(float cornerRadius)

Отже, починаючи з Bitmap srcцілі ImageView, це виглядатиме приблизно так:

RoundedBitmapDrawable dr = RoundedBitmapDrawableFactory.create(res, src);
dr.setCornerRadius(cornerRadius);
imageView.setImageDrawable(dr);

3
Велике спасибі, ось наступний крок: stackoverflow.com/questions/24878740/…
David d C e Freitas

насправді є, android.support.v4.graphics.drawable.RoundedBitmapDrawableFactoryтак це v4також підтримує.
мертвий риб

2
@deadfish так це в v4бібліотеці підтримки, але не до REVISION 21бібліотеки підтримки
tyczj

3
Це рішення є простим і сучасним. Він вимагає найменшої кількості коду і має велику розширюваність. Можна працювати із зображеннями з локального файлу, кешованим малюнком або навіть з NetworkImageView Volley. Я дуже погоджуюсь, що це має бути прийнятою відповіддю сьогодні, як зазначив @Jonik.
katie

2
На жаль, не працює scaleType centerCrop(бібліотека підтримки v25.3.1)
rocknow

67

Я зробив користувальницьким ImageView:

public class RoundRectCornerImageView extends ImageView {

    private float radius = 18.0f;
    private Path path;
    private RectF rect;

    public RoundRectCornerImageView(Context context) {
        super(context);
        init();
    }

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

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

    private void init() {
        path = new Path();

    }

    @Override
    protected void onDraw(Canvas canvas) {
        rect = new RectF(0, 0, this.getWidth(), this.getHeight());
        path.addRoundRect(rect, radius, radius, Path.Direction.CW);
        canvas.clipPath(path);
        super.onDraw(canvas);
    }
}

Як користуватись:

<com.mypackage.RoundRectCornerImageView
     android:id="@+id/imageView"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@drawable/image"
     android:scaleType="fitXY" />

Вихід:

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

Сподіваюся, це допоможе вам.


це робить розмиття зображення
Amit Hooda

2
працює навіть з android: scaleType = "centerCrop", простий, не створює нових растрових зображень. Дякую!
ерназм

1
@Hiren Це рішення добре працює для ImageView з фоновим зображенням. Але він не працює для ImageViews, який має лише колір тла та зображення. Скажіть, будь ласка, чому це відбувається?
user2991413

Canvas.clipPath()може спричинити java.lang.UnsupportedOperationExceptionв деяких випадках. Дивіться stackoverflow.com/questions/13248904/…
Артем

1
Це рішення працює лише для набору зображень android:background, але не android:src.
CoolMind

64

Швидке рішення у форматі XML -

<android.support.v7.widget.CardView
            android:layout_width="40dp"
            android:layout_height="40dp"
            app:cardElevation="0dp"
            app:cardCornerRadius="4dp">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/rounded_user_image"
        android:scaleType="fitXY"/>

</android.support.v7.widget.CardView>

Ви можете встановити бажану ширину, висоту та радіус на CardView та scaleType на ImageView.

Використовуйте AndroidX <androidx.cardview.widget.CardView>


4
такий підхід спрацював у моєму випадку з androidx.cardview.widget.CardView
Іван

7
Не впевнені, чому це не має більшої кількості результатів? На мій погляд, найкраще рішення без бібліотек і тонни лаймового коду (хоча в моєму випадку я використовував масштабування центруCrop).
ThemBones

1
Ще мало відгуків, тому що це нова відповідь. Але я поставив свій +1, щоб скоро його перемістити! Дякую!
Micer

однак воно працює, але тут зображення розтягнеться через scaleType="fitXY"та не виглядає належним чином @ThemBones
WIZARD

@WIZARD, тому я згадав, що ви можете встановити бажаний масштаб типу в ImageView
Mittal,

57

Я виявив, що обидва методи були дуже корисними у розробці робочого рішення. Ось моя складна версія, яка не залежить від пікселів і дозволяє мати кілька квадратних кутів, а решта кути мають однаковий радіус (що є звичайним випадком використання). Завдяки обом рішенням, наведеним вище:

public static Bitmap getRoundedCornerBitmap(Context context, Bitmap input, int pixels , int w , int h , boolean squareTL, boolean squareTR, boolean squareBL, boolean squareBR  ) {

    Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888);
    Canvas canvas = new Canvas(output);
    final float densityMultiplier = context.getResources().getDisplayMetrics().density;

    final int color = 0xff424242;
    final Paint paint = new Paint();
    final Rect rect = new Rect(0, 0, w, h);
    final RectF rectF = new RectF(rect);

    //make sure that our rounded corner is scaled appropriately
    final float roundPx = pixels*densityMultiplier;

    paint.setAntiAlias(true);
    canvas.drawARGB(0, 0, 0, 0);
    paint.setColor(color);
    canvas.drawRoundRect(rectF, roundPx, roundPx, paint);


    //draw rectangles over the corners we want to be square
    if (squareTL ){
        canvas.drawRect(0, h/2, w/2, h, paint);
    }
    if (squareTR ){
        canvas.drawRect(w/2, h/2, w, h, paint);
    }
    if (squareBL ){
        canvas.drawRect(0, 0, w/2, h/2, paint);
    }
    if (squareBR ){
        canvas.drawRect(w/2, 0, w, h/2, paint);
    }


    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    canvas.drawBitmap(input, 0,0, paint);

    return output;
}

Крім того, я переоцінив ImageView, щоб помістити це, щоб я міг визначити це в xml. Ви можете додати трохи логіки, яку робить супер дзвінок тут, але я прокоментував це, оскільки це не корисно в моєму випадку.

    @Override
protected void onDraw(Canvas canvas) {
    //super.onDraw(canvas);
        Drawable drawable = getDrawable();

        Bitmap b =  ((BitmapDrawable)drawable).getBitmap() ;
        Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);

        int w = getWidth(), h = getHeight();


        Bitmap roundBitmap =  CropImageView.getRoundedCornerBitmap( getContext(), bitmap,10 , w, h , true, false,true, false);
        canvas.drawBitmap(roundBitmap, 0,0 , null);
}

Сподіваюся, це допомагає!


4
досить приголомшливо, особливо розширюючи ImageView
Хтось десь

2
Простий спосіб зберегти логіку ImageView # onDraw () - встановити округлу кутову растрову матрицю ImageView і залишити super.onDraw () для малювання растрової карти. Я створив клас RoundedCornerImageView , і його приклад використання тут . Зауважте, що я використовував getRoundedCornerBitmap (), не залежить від пікселів.
umbalaconmeogia

Дякуємо за RoundedCornerImageView. Я використовував його, але змінив його на незалежність від щільності пікселів.
PacificSky

Вихідний код для RoundedCornerImageView umba знаходиться тут: code.google.com/p/android-batsg/source/browse/trunk/…
хтось десь

@Caspar Harmer працює добре лише 1 редагування ... є чотири умови .. просто змінити їх так, як якщо б я встановив істинне, істинне, хибне, помилкове, він встановить нижній кут замість верхнього кута. Інший код працює нормально. і squareTR - це умови для squareBL і squareBR відповідно .. і vica навпаки.
TheFlash

48

Закруглене зображення Використовуючи ImageLoader тут

Створити DisplayImageOptions:

DisplayImageOptions options = new DisplayImageOptions.Builder()
    // this will make circle, pass the width of image 
    .displayer(new RoundedBitmapDisplayer(getResources().getDimensionPixelSize(R.dimen.image_dimen_menu))) 
    .cacheOnDisc(true)
    .build();

imageLoader.displayImage(url_for_image,ImageView,options);

Або ви можете користуватися Picassoбібліотекою від Square.

Picasso.with(mContext)
    .load(com.app.utility.Constants.BASE_URL+b.image)
    .placeholder(R.drawable.profile)
    .error(R.drawable.profile)
    .transform(new RoundedTransformation(50, 4))
    .resizeDimen(R.dimen.list_detail_image_size, R.dimen.list_detail_image_size)
    .centerCrop()
    .into(v.im_user);

Ви можете завантажити файл RoundedTransformation тут


1
Не відображається зображення
Amit Thaper

3
Бібліотека Пікассо хороша і дуже проста у виконанні, дуже дякую +1
Hitesh

3
Схоже, бібліотека Пікассо не перетворює зображення "заповнювача" та "помилки", тому якщо ваше зображення не завантажується (помилка) або спочатку завантажується час (заповнювач місця), воно не відображатиме зображення як округле зображення. github.com/square/picasso/isissue/337
Pelpotronic

Інші корисні перетворення пікассо надаються цією бібліотекою, яка також містить RoundedCornersTransformation: github.com/wasabeef/picasso-transformations
Массімо

Не працює з обрізанням зображень у Univ. Завантажувач зображень
Яр

26

Оскільки всі відповіді здалися мені занадто складними лише для круглих кутів, я подумав і прийшов до іншого рішення, яке, на мою думку, варто поділитися, лише з XML, якщо у вас є простір навколо зображення:

Створіть облямову форму з прозорим вмістом, як це:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners 
        android:radius="30dp" />
    <stroke 
        android:color="#ffffffff"
        android:width="10dp" />
</shape> 

Потім у RelativeLayout ви можете спочатку розмістити своє зображення, а потім у тому самому місці над формою з іншим ImageView. Форма покриття повинна бути більшою за розміром на величину ширини бордюру. Будьте обережні, приймайте більший радіус кута, оскільки визначається зовнішній радіус, але внутрішній радіус - це те, що покриває ваше зображення.

Сподіваюсь, це теж допоможе комусь.

Редагувати відповідно до запиту CQM щодо прикладу відносного макета:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:id="@+id/imageToShow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/imgCorners"
        android:layout_alignLeft="@+id/imgCorners"
        android:layout_alignRight="@+id/imgCorners"
        android:layout_alignTop="@+id/imgCorners"
        android:background="#ffffff"
        android:contentDescription="@string/desc"
        android:padding="5dp"
        android:scaleType="centerCrop" />

    <ImageView
        android:id="@+id/imgCorners"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:contentDescription="@string/desc"
        android:src="@drawable/corners_white" />

</RelativeLayout>

чи можете ви детальніше зупинитися на цьому з додатковим кодом, особливо те, що робиться за допомогою другого перегляду зображення і де застосовується "обмежена форма" xml (як src або як фон?) декілька питань тут. Я хочу, щоб це рішення сподобалось, оскільки воно дозволить мені контролювати всі чотири кути незалежно
CQM

1
Хоча це здається простою відповіддю, але, на жаль, додає запас навколо «маскованого» зображення, що є небажаним побічним ефектом.
Абдалрахман Шату

так, але те ж саме працює з ImageView на основі PNG-Dravable із закругленими кутами та прозорим фоном або 9-патч-Dravable, якщо у вас невизначений аспект.
Крістіан

Я роблю так само, і його працює; просто готові знати, чи це не створить проблем із орієнтацією та різним розміром телефону?
відкрито та безкоштовно

Якщо ви будете зберігати розміри відносно інших, це не повинно створювати проблем.
Крістіан

22

Починаючи з версії 1.2.0-alpha03цього на компоненти матеріалу бібліотеки є новий ShapeableImageView.

Ви можете використовувати щось на кшталт:

  <com.google.android.material.imageview.ShapeableImageView
      ...
      app:shapeAppearanceOverlay="@style/roundedImageView"
      app:srcCompat="@drawable/ic_image" />

з:

  <style name="roundedImageView" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">8dp</item>
  </style>

Або програмно:

float radius = getResources().getDimension(R.dimen.default_corner_radius);
imageView.setShapeAppearanceModel(imageView.getShapeAppearanceModel()
    .toBuilder()
    .setAllCorners(CornerFamily.ROUNDED,radius)
    .build());

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


Якщо зображення має фонове забарвлення, воно в даний час створює колір тла, щоб з'являтися під закругленими кутами. Це також ігнорує властивість scaleType на зображенні.
inokey

14

Моя реалізація ImageView із віджетом із закругленими кутами, який (вниз || вгору) розмір зображення до потрібних розмірів. Він використовує кодову форму CaspNZ.

public class ImageViewRounded extends ImageView {

    public ImageViewRounded(Context context) {
        super(context);
    }

    public ImageViewRounded(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

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

    @Override
    protected void onDraw(Canvas canvas) {
        BitmapDrawable drawable = (BitmapDrawable) getDrawable();

        if (drawable == null) {
            return;
        }

        if (getWidth() == 0 || getHeight() == 0) {
            return; 
        }

        Bitmap fullSizeBitmap = drawable.getBitmap();

        int scaledWidth = getMeasuredWidth();
        int scaledHeight = getMeasuredHeight();

        Bitmap mScaledBitmap;
        if (scaledWidth == fullSizeBitmap.getWidth() && scaledHeight == fullSizeBitmap.getHeight()) {
            mScaledBitmap = fullSizeBitmap;
        } else {
            mScaledBitmap = Bitmap.createScaledBitmap(fullSizeBitmap, scaledWidth, scaledHeight, true /* filter */);
        }

        Bitmap roundBitmap = ImageUtilities.getRoundedCornerBitmap(getContext(), mScaledBitmap, 5, scaledWidth, scaledHeight,
                false, false, false, false);
        canvas.drawBitmap(roundBitmap, 0, 0, null);

    }

}

12
Звідки беруться ImageUtilities?
JasonWyatt

1
@JasonWyatt дивіться повідомлення про сорродів нижче
Дам’ян

12

Нещодавно існує інший спосіб - використання API Generated Glide . Це займає деяку початкову роботу, але потім дає вам всю силу Glide з гнучкістю робити що-небудь, тому що ви пишете фактичний код, тому я думаю, що це хороше рішення в довгостроковій перспективі. Плюс, використання дуже просте і акуратне.

По-перше, налаштувати Glide версії 4+:

implementation 'com.github.bumptech.glide:glide:4.6.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.6.1'

Потім створіть клас модуля програми Glid, щоб запустити обробку приміток:

@GlideModule
public final class MyAppGlideModule extends AppGlideModule {}

Потім створіть розширення Glide, яке насправді виконує роботу. Ви можете налаштувати його на все, що завгодно:

@GlideExtension
public class MyGlideExtension {

    private MyGlideExtension() {}

    @NonNull
    @GlideOption
    public static RequestOptions roundedCorners(RequestOptions options, @NonNull Context context, int cornerRadius) {
        int px = Math.round(cornerRadius * (context.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
        return options.transforms(new RoundedCorners(px));
    }
}

Після додавання цих файлів побудуйте свій проект.

Потім використовуйте його у своєму коді так:

GlideApp.with(this)
        .load(imageUrl)
        .roundedCorners(getApplicationContext(), 5)
        .into(imageView);

Не забудьте додати пробіл між RequestOptionsі optionsв
парамах

Зроблено. Дякуємо за вклад.
Сер Кодесалот

ОкруженіКорнери не приходять, чи потрібно нам інше налаштовувати? Навіть після відновлення проекту
доктор aNdRO

Це працювало для мене, дякую. Мені було простіше уникати використання @GlideExtensionанотованого класу, і просто пішов з тим, .transform(new RoundedCorners(px))де pxце те саме ( int px = Math.round(cornerRadius * (context.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));).
Михайло Ософський

10

Існує класна бібліотека, яка дозволяє формувати зображення.

Ось приклад:

<com.github.siyamed.shapeimageview.mask.PorterShapeImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:siShape="@drawable/shape_rounded_rectangle"
    android:src="@drawable/neo"
    app:siSquare="true"/>

Визначення форми:

<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
    <corners
        android:topLeftRadius="18dp"
        android:topRightRadius="18dp"
        android:bottomLeftRadius="18dp"
        android:bottomRightRadius="18dp" />
    <solid android:color="@color/black" />
</shape>

Результат:

результат


1
Це чудово, і ви робите набагато більше, як ви можете додати межу та використовувати будь-яку фігуру
Адам Кіс,

8

Ось простий приклад перекриття imageView, ви також можете використовувати його в дизайнері макетів для попереднього перегляду.

public class RoundedImageView extends ImageView {

    public RoundedImageView(Context context) {
        super(context);
    }

    public RoundedImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public RoundedImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public RoundedImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public void setImageDrawable(Drawable drawable) {
        float radius = 0.1f;
        Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
        RoundedBitmapDrawable rid = RoundedBitmapDrawableFactory.create(getResources(), bitmap);
        rid.setCornerRadius(bitmap.getWidth() * radius);
        super.setImageDrawable(rid);
    }
}

Це для швидкого вирішення. Радіус використовується на всіх кутах і базується на відсотках ширини растрових зображень.

Я просто переосмислив setImageDrawableі використав метод підтримки v4 для округлення растрових зображень.

Використання:

<com.example.widgets.RoundedImageView
        android:layout_width="39dp"
        android:layout_height="39dp"
        android:src="@drawable/your_drawable" />

Попередній перегляд з imageView та спеціальним imageView:

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


Це працює у будь-якій ситуації, дякую. Ти врятував мені день.
Мехул Соланкі

7

Вам слід розширити ImageViewі намалювати власний округлий прямокутник.

Якщо ви хочете рамку навколо зображення, ви також можете накласти округлену рамку зверху на зображення в макеті.

[редагувати] Накладіть на кадр, щоб вибрати оригінальне зображення, використовуючи, FrameLayoutнаприклад,. Першим елементом FrameLayoutзаповіту буде зображення, яке ви хочете відтворити округлим. Потім додайте ще один ImageViewкадр. Друга ImageViewбуде відображатися поверх оригіналу, ImageViewі таким чином Android намалюватиме її вміст вище оригіналу ImageView.


Дякую. Але існує лише метод setDravable для ImageView, як я можу встановитиDravable з ImageView до вмісту мого зображення, а потім накласти округлий кадр поверх ImageView?
Майкл

Вибачте, мені було незрозуміло. Я мав на увазі накладення в макеті: таким чином (тобто) використовуйте FrameLayoutвкладене ImageViewв нього і додайте ще один ImageViewіз закругленою рамкою. Таким чином, перший ImageViewвідобразить обране вами зображення, а друге ImageFrame- округлу рамку.
MrSnowflake

Правильно - за допомогою FrameLayout ви можете накладати одне зображення / перегляд на інше. Ви також можете скористатися тегом FrameLayout на android: foreground.
Річард Ле Месюр'є

7

Ромен Гай - це місце, де воно знаходиться.

Мінімізована версія наступна.

Bitmap bitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.image)).getBitmap();

Bitmap bitmapRounded = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
Canvas canvas = new Canvas(bitmapRounded);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
canvas.drawRoundRect((new RectF(0.0f, 0.0f, bitmap.getWidth(), bitmap.getHeight())), 10, 10, paint);

imageView.setImageBitmap(bitmapRounded);

на жаль, навіть якщо це працює, але як і інші рішення тут, він створює нову растрову карту замість використання поточної.
андроїд розробник

не зовсім. bitmapRounded буде використовуватися знову і знову. якщо у вас був доступ до малюючого полотна, ви можете використовувати метод малювання безпосередньо, а не створювати нову растрову карту.
Олексій

як ти це робиш? припустимо, я не використовую будь-яких спеціальних зображуваних файлів і обробляю лише одну растрову карту та використовую setImageBitmap в кінці процесу. як би я досяг такого?
андроїд розробник

ознайомтеся з прикладом романського хлопця curious-creature.org/2012/12/11/… та зразок програми docs.google.com/file/d/0B3dxhm5xm1sia2NfM3VKTXNjUnc/edit
Алекс

обидва не змінюють растрову карту, а обертають її за допомогою користувацького малювання та спеціального перегляду зображень. це не те, про що я питав. Я запитав, як ви змінюєте саму растрову карту.
андроїд розробник

7

Цей чистий розчин у форматі XML був досить хорошим у моєму випадку. http://www.techrepublic.com/article/pro-tip-round-corners-on-an-android-imageview-with-this-hack/

EDIT

Ось відповідь у двох словах:

У папці / res / dravable створити файл frame.xml. У ньому ми визначаємо простий прямокутник із закругленими кутами та прозорим центром.

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
     <solid android:color="#00ffffff" />
     <padding android:left="6dp"
        android:top="6dp"
        android:right="6dp"
        android:bottom="6dp" />
     <corners android:radius="12dp" />
     <stroke android:width="6dp" android:color="#ffffffff" />
</shape>

У файл вашого макета ви додасте LinearLayout, який містить стандартний ImageView, а також вкладений FrameLayout. FrameLayout використовує прокладки та користувальницький малюнок, щоб створити ілюзію закруглених кутів.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:layout_gravity="center"
    android:gravity="center" 
    android:background="#ffffffff">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="6dp"
        android:src="@drawable/tr"/>

    <FrameLayout 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="6dp"
            android:src="@drawable/tr"/>

        <ImageView 
             android:src="@drawable/frame"
             android:layout_width="match_parent"
             android:layout_height="match_parent" />

    </FrameLayout>

</LinearLayout>

приємна ідея, я використовував її для показу куточків нерівних ImageView
Гал Ром,

6

Реквізити Джорджа Уолтерса II вище, я просто взяв його відповідь і трохи продовжив його, щоб по-різному підтримувати округлення окремих кутів. Це можна було б оптимізувати трохи далі (деякі цільові прямі перекриття), але не цілу партію.

Я знаю, що цей потік трохи старий, але це один із найкращих результатів для запитів у Google про те, як округлити кути ImageViews на Android.

/**
 * Use this method to scale a bitmap and give it specific rounded corners.
 * @param context Context object used to ascertain display density.
 * @param bitmap The original bitmap that will be scaled and have rounded corners applied to it.
 * @param upperLeft Corner radius for upper left.
 * @param upperRight Corner radius for upper right.
 * @param lowerRight Corner radius for lower right.
 * @param lowerLeft Corner radius for lower left.
 * @param endWidth Width to which to scale original bitmap.
 * @param endHeight Height to which to scale original bitmap.
 * @return Scaled bitmap with rounded corners.
 */
public static Bitmap getRoundedCornerBitmap(Context context, Bitmap bitmap, float upperLeft,
        float upperRight, float lowerRight, float lowerLeft, int endWidth,
        int endHeight) {
    float densityMultiplier = context.getResources().getDisplayMetrics().density;

    // scale incoming bitmap to appropriate px size given arguments and display dpi
    bitmap = Bitmap.createScaledBitmap(bitmap, 
            Math.round(endWidth * densityMultiplier),
            Math.round(endHeight * densityMultiplier), true);

    // create empty bitmap for drawing
    Bitmap output = Bitmap.createBitmap(
            Math.round(endWidth * densityMultiplier),
            Math.round(endHeight * densityMultiplier), Config.ARGB_8888);

    // get canvas for empty bitmap
    Canvas canvas = new Canvas(output);
    int width = canvas.getWidth();
    int height = canvas.getHeight();

    // scale the rounded corners appropriately given dpi
    upperLeft *= densityMultiplier;
    upperRight *= densityMultiplier;
    lowerRight *= densityMultiplier;
    lowerLeft *= densityMultiplier;

    Paint paint = new Paint();
    paint.setAntiAlias(true);
    paint.setColor(Color.WHITE);

    // fill the canvas with transparency
    canvas.drawARGB(0, 0, 0, 0);

    // draw the rounded corners around the image rect. clockwise, starting in upper left.
    canvas.drawCircle(upperLeft, upperLeft, upperLeft, paint);
    canvas.drawCircle(width - upperRight, upperRight, upperRight, paint);
    canvas.drawCircle(width - lowerRight, height - lowerRight, lowerRight, paint);
    canvas.drawCircle(lowerLeft, height - lowerLeft, lowerLeft, paint);

    // fill in all the gaps between circles. clockwise, starting at top.
    RectF rectT = new RectF(upperLeft, 0, width - upperRight, height / 2);
    RectF rectR = new RectF(width / 2, upperRight, width, height - lowerRight);
    RectF rectB = new RectF(lowerLeft, height / 2, width - lowerRight, height);
    RectF rectL = new RectF(0, upperLeft, width / 2, height - lowerLeft);

    canvas.drawRect(rectT, paint);
    canvas.drawRect(rectR, paint);
    canvas.drawRect(rectB, paint);
    canvas.drawRect(rectL, paint);

    // set up the rect for the image
    Rect imageRect = new Rect(0, 0, width, height);

    // set up paint object such that it only paints on Color.WHITE
    paint.setXfermode(new AvoidXfermode(Color.WHITE, 255, AvoidXfermode.Mode.TARGET));

    // draw resized bitmap onto imageRect in canvas, using paint as configured above
    canvas.drawBitmap(bitmap, imageRect, imageRect, paint);

    return output;
}

+1 для додавання в множник щільності та додавання підтримки для індивідуальних закруглення кутів. Я фактично використовував рішення вгорі, так як ваше рішення не зовсім спрацювало - але це було дуже корисно! Дивіться моє складене рішення нижче:
Caspar Harmer

6

Застосуйте фігуру imageViewяк нижче:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >
    <solid android:color="#faf5e6" />
    <stroke
        android:width="1dp"
        android:color="#808080" />
    <corners android:radius="15dp" />
    <padding
        android:bottom="5dp"
        android:left="5dp"
        android:right="5dp"
        android:top="5dp" />
</shape>

це може бути корисним вашому другові.


6

Чому б не зробити відсікання draw()?

Ось моє рішення:

  • Розширити відносний макет із відсіканням
  • Помістіть ImageView (або інші представлення) у макет:

Код:

public class RoundRelativeLayout extends RelativeLayout {

    private final float radius;

    public RoundRelativeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray attrArray = context.obtainStyledAttributes(attrs,
                R.styleable.RoundRelativeLayout);
        radius = attrArray.getDimension(
                R.styleable.RoundRelativeLayout_radius, 0);
    }

    private boolean isPathValid;
    private final Path path = new Path();

    private Path getRoundRectPath() {
        if (isPathValid) {
            return path;
        }

        path.reset();

        int width = getWidth();
        int height = getHeight();
        RectF bounds = new RectF(0, 0, width, height);

        path.addRoundRect(bounds, radius, radius, Direction.CCW);
        isPathValid = true;
        return path;
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        canvas.clipPath(getRoundRectPath());
        super.dispatchDraw(canvas);
    }

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int oldWidth = getMeasuredWidth();
        int oldHeight = getMeasuredHeight();
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int newWidth = getMeasuredWidth();
        int newHeight = getMeasuredHeight();
        if (newWidth != oldWidth || newHeight != oldHeight) {
            isPathValid = false;
        }
    }

}

1
Мені подобається такий підхід. Я використовував це для створення власного RoundImageView. Дякую за це
Паскаль

Це не працює з включеним прискореним прискоренням, правда? Я не побачив легкого вирішення ...
secureboot

Чи можете ви, будь ласка, показати, як це зробити, отримавши результат як мальованого, мати можливість додавати контур (штрих AKA) навколо вмісту, а також мати можливість зробити лише деякі кути, які повинні бути закруглені?
андроїд розробник

5

Далі створюється об'єкт макета прямокутника із закругленою формою, який малює округлий прямокутник навколо будь-яких дочірніх об'єктів, розміщених у ньому. Він також демонструє, як програмно створювати представлення та макети без використання файлів xml-макета.

package android.example;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MessageScreen extends Activity {
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  int mainBackgroundColor = Color.parseColor("#2E8B57");
  int labelTextColor = Color.parseColor("#FF4500");
  int messageBackgroundColor = Color.parseColor("#3300FF");
  int messageTextColor = Color.parseColor("#FFFF00");

  DisplayMetrics metrics = new DisplayMetrics();
  getWindowManager().getDefaultDisplay().getMetrics(metrics);
  float density = metrics.density;
  int minMarginSize = Math.round(density * 8);
  int paddingSize = minMarginSize * 2;
  int maxMarginSize = minMarginSize * 4;

  TextView label = new TextView(this);
  /*
   * The LayoutParams are instructions to the Layout that will contain the
   * View for laying out the View, so you need to use the LayoutParams of
   * the Layout that will contain the View.
   */
  LinearLayout.LayoutParams labelLayoutParams = new LinearLayout.LayoutParams(
    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
  label.setLayoutParams(labelLayoutParams);
  label.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
  label.setPadding(paddingSize, paddingSize, paddingSize, paddingSize);
  label.setText(R.string.title);
  label.setTextColor(labelTextColor);

  TextView message = new TextView(this);
  RoundedRectangle.LayoutParams messageLayoutParams = new RoundedRectangle.LayoutParams(
 LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
  /*
   * This is one of the calls must made to force a ViewGroup to call its
   * draw method instead of just calling the draw method of its children.
   * This tells the RoundedRectangle to put some extra space around the
   * View.
   */
  messageLayoutParams.setMargins(minMarginSize, paddingSize,
    minMarginSize, maxMarginSize);
  message.setLayoutParams(messageLayoutParams);
  message.setTextSize(TypedValue.COMPLEX_UNIT_SP, paddingSize);
  message.setText(R.string.message);
  message.setTextColor(messageTextColor);
  message.setBackgroundColor(messageBackgroundColor);

  RoundedRectangle messageContainer = new RoundedRectangle(this);
  LinearLayout.LayoutParams messageContainerLayoutParams = new LinearLayout.LayoutParams(
    LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
  messageContainerLayoutParams.setMargins(paddingSize, 0, paddingSize, 0);
  messageContainer.setLayoutParams(messageContainerLayoutParams);
  messageContainer.setOrientation(LinearLayout.VERTICAL);
  /*
   * This is one of the calls must made to force a ViewGroup to call its
   * draw method instead of just calling the draw method of its children.
   * This tells the RoundedRectangle to color the the exta space that was
   * put around the View as well as the View. This is exterior color of
   * the RoundedRectangle.
   */
  messageContainer.setBackgroundColor(mainBackgroundColor);
  /*
   * This is one of the calls must made to force a ViewGroup to call its
   * draw method instead of just calling the draw method of its children.
   * This is the interior color of the RoundedRectangle. It must be
   * different than the exterior color of the RoundedRectangle or the
   * RoundedRectangle will not call its draw method.
   */
  messageContainer.setInteriorColor(messageBackgroundColor);
  // Add the message to the RoundedRectangle.
  messageContainer.addView(message);

  //
  LinearLayout main = new LinearLayout(this);
  LinearLayout.LayoutParams mainLayoutParams = new LinearLayout.LayoutParams(
    LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
  main.setLayoutParams(mainLayoutParams);
  main.setOrientation(LinearLayout.VERTICAL);
  main.setBackgroundColor(mainBackgroundColor);
  main.addView(label);
  main.addView(messageContainer);

  setContentView(main);
 }
}

Клас для об’єкта макета RoundedRectangle визначений тут:

/**
 *  A LinearLayout that draws a rounded rectangle around the child View that was added to it.
 */
package android.example;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.widget.LinearLayout;

/**
 * A LinearLayout that has rounded corners instead of square corners.
 * 
 * @author Danny Remington
 * 
 * @see LinearLayout
 * 
 */
public class RoundedRectangle extends LinearLayout {
 private int mInteriorColor;

 public RoundedRectangle(Context p_context) {
  super(p_context);
 }

 public RoundedRectangle(Context p_context, AttributeSet attributeSet) {
  super(p_context, attributeSet);
 }

 // Listener for the onDraw event that occurs when the Layout is drawn.
 protected void onDraw(Canvas canvas) {
  Rect rect = new Rect(0, 0, getWidth(), getHeight());
  RectF rectF = new RectF(rect);
  DisplayMetrics metrics = new DisplayMetrics();
  Activity activity = (Activity) getContext();
  activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
  float density = metrics.density;
  int arcSize = Math.round(density * 10);

  Paint paint = new Paint();
  paint.setColor(mInteriorColor);

  canvas.drawRoundRect(rectF, arcSize, arcSize, paint);
 }

 /**
  * Set the background color to use inside the RoundedRectangle.
  * 
  * @param Primitive int - The color inside the rounded rectangle.
  */
 public void setInteriorColor(int interiorColor) {
  mInteriorColor = interiorColor;
 }

 /**
  * Get the background color used inside the RoundedRectangle.
  * 
  * @return Primitive int - The color inside the rounded rectangle.
  */
 public int getInteriorColor() {
  return mInteriorColor;
 }

}

5

Котлін

import android.graphics.BitmapFactory
import android.os.Bundle
import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory
import kotlinx.android.synthetic.main.activity_main.*

val bitmap = BitmapFactory.decodeResource(resources, R.drawable.myImage)
val rounded = RoundedBitmapDrawableFactory.create(resources, bitmap)
rounded.cornerRadius = 20f
profileImageView.setImageDrawable(rounded)

Щоб зробити ImageViewЦиркуляр, ми можемо змінити за cornerRadiusдопомогою:

rounded.isCircular = true

4

Дякую за першу відповідь. Тут є модифікована версія для перетворення прямокутного зображення в квадратне (і округлене), а колір заповнення передається як параметр.

public static Bitmap getRoundedBitmap(Bitmap bitmap, int pixels, int color) {

    Bitmap inpBitmap = bitmap;
    int width = 0;
    int height = 0;
    width = inpBitmap.getWidth();
    height = inpBitmap.getHeight();

    if (width <= height) {
        height = width;
    } else {
        width = height;
    }

    Bitmap output = Bitmap.createBitmap(width, height, Config.ARGB_8888);
    Canvas canvas = new Canvas(output);

    final Paint paint = new Paint();
    final Rect rect = new Rect(0, 0, width, height);
    final RectF rectF = new RectF(rect);
    final float roundPx = pixels;

    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(inpBitmap, rect, rect, paint);

    return output;
}

4

Якщо ви використовуєте Бібліотеку Glide, це буде корисно:

Glide.with(getApplicationContext())
     .load(image_url)
     .asBitmap()
     .centerCrop()
     .into(new BitmapImageViewTarget(imageView) {
        @Override
        protected void setResource(Bitmap resource) {
          RoundedBitmapDrawable circularBitmapDrawable =
                       RoundedBitmapDrawableFactory.create(getApplicationContext().getResources(), resource);
          circularBitmapDrawable.setCornerRadius(dpToPx(10));
          circularBitmapDrawable.setAntiAlias(true);
          imageView.setImageDrawable(circularBitmapDrawable);
        }
     });


public int dpToPx(int dp) {
  DisplayMetrics displayMetrics = getApplicationContext().getResources().getDisplayMetrics();
  return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
}

Якщо ви використовуєте Glide версії 4 та вище, використовуйте --- RequestOptions requestOptions = нові RequestOptions (); requestOptions = requestOptions.transforms (новий CenterCrop (), нові RoundedCorners (16)); Glide.with (itemView.getContext ()) .load (item.getImage ()) .apply (requestOptions) .into (mProgramThumbnail);
Б.шруті

3

якщо ваше зображення є в Інтернеті, найкращим способом є використання гліде та RoundedBitmapDrawableFactory(з API 21 - але доступне в бібліотеці підтримки):

 Glide.with(ctx).load(url).asBitmap().centerCrop().into(new BitmapImageViewTarget(imageView) {
    @Override
    protected void setResource(Bitmap res) {
        RoundedBitmapDrawable bitmapDrawable =
             RoundedBitmapDrawableFactory.create(ctx.getResources(), res);
        bitmapDrawable.setCircular(true);//comment this line and uncomment the next line if you dont want it fully cricular
        //circularBitmapDrawable.setCornerRadius(cornerRadius);
        imageView.setImageDrawable(bitmapDrawable);
    }
});

Це елегантний api, однак, .centerInside, здається, відсутній, отже, для визначення таких параметрів краще використовувати xml
carl

Це також корисно, коли зображення знаходиться в ресурсах і вам потрібно використовуватиcenterCrop
Артем

3

ви можете використовувати лише ImageViewу своєму макеті та використанні glide, за допомогою цього методу можна застосувати круглі кути.

спочатку у своєму градусі напишіть,

compile 'com.github.bumptech.glide:glide:3.7.0'

для зображення із закругленими кутами,

public void loadImageWithCorners(String url, ImageView view) {
    Glide.with(context)
            .load(url)
            .asBitmap()
            .centerCrop()
            .placeholder(R.color.gray)
            .error(R.color.gray)
            .diskCacheStrategy(DiskCacheStrategy.SOURCE)
            .into(new BitmapImageViewTarget(view) {
                @Override
                protected void setResource(Bitmap resource) {
                    RoundedBitmapDrawable circularBitmapDrawable =
                            RoundedBitmapDrawableFactory.create(context.getResources(), resource);
                    circularBitmapDrawable.setCornerRadius(32.0f); // radius for corners
                    view.setImageDrawable(circularBitmapDrawable);
                }
            });
}

метод виклику:

loadImageWithCorners("your url","your imageview");

Це додасть бібліотеку для завантаження зображень через HTTP-запит, що не стосується питання.
creativecreatorormaybenot

Яка бібліотека буде завантажена? Для завантаження зображення ви можете використовувати glide та його фрагмент виключно на основі методів та класів самого ковзання. Жодної іншої бібліотеки не потрібно додавати
Deep Patel

Glide - це бібліотека, в основному для завантаження зображень через HTTP, але ОП хотів знати, як округлити кути анкети ImageView.
творчий

2

Відповідь на запитання, яке перенаправлено тут: "Як створити круговий ImageView в Android?"

public static Bitmap getRoundBitmap(Bitmap bitmap) {

    int min = Math.min(bitmap.getWidth(), bitmap.getHeight());

    Bitmap bitmapRounded = Bitmap.createBitmap(min, min, bitmap.getConfig());

    Canvas canvas = new Canvas(bitmapRounded);
    Paint paint = new Paint();
    paint.setAntiAlias(true);
    paint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
    canvas.drawRoundRect((new RectF(0.0f, 0.0f, min, min)), min/2, min/2, paint);

    return bitmapRounded;
}

2

За допомогою бібліотеки ковзання та класу RoundedBitmapDravableFactory цього легко досягти. Можливо, вам доведеться створити кругове зображення заповнювача.

    Glide.with(context)
        .load(imgUrl)
        .asBitmap()
        .placeholder(R.drawable.placeholder)
        .error(R.drawable.placeholder)
        .into(new BitmapImageViewTarget(imgProfilePicture) {
            @Override
            protected void setResource(Bitmap resource) {
                RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(context.getResources(),
                        Bitmap.createScaledBitmap(resource, 50, 50, false));
                drawable.setCornerRadius(10); //drawable.setCircular(true);
                imgProfilePicture.setImageDrawable(drawable);
            }
        });

2

Для тих, хто використовує Glide та Kotlin, ви можете досягти цього, розширивши його RequestBuilder

fun <T> GlideRequest<T>.roundCorners(cornerRadius: Int) =
    apply(RequestOptions().transform(RoundedCorners(cornerRadius)))

і використовувати як;

 GlideApp.with(context)
            .load(url)
            .roundCorners(context.resources.getDimension(R.dimen.radius_in_dp).toInt())
            .into(imgView)

ОкруженіКорнери не приходять, чи потрібно нам інше налаштовувати?
Доктор aNdRO

Ви додали функцію розширення, roundCornersяк описано вище? @ Dr.aNdRO
dgngulcan

Надайте належний приклад! Ця відповідь бентежить!
Юнія Монтана
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.