Как сделать ImageView с закругленными углами? - PullRequest
510 голосов
/ 17 марта 2010

В Android ImageView по умолчанию является прямоугольником. Как сделать прямоугольник с закругленными углами (обрезать все 4 угла моего растрового изображения, чтобы они были прямоугольниками с закругленными углами) в ImageView?

Ответы [ 44 ]

529 голосов
/ 20 июля 2010

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

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

Надеюсь, это кому-нибудь поможет!

202 голосов
/ 22 февраля 2013

Хотя приведенный выше ответ работает, Romain Guy (основной разработчик для 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]
  • поддерживает alpha [против xfermode + метод porterduff]
  • поддерживает аппаратное ускорение [против метода clipPath]
  • только рисует один раз на холсте [против методов xfermode и clippath]

Я создал RoundedImageView на основе этого кода, который оборачивает эту логику в ImageView и добавляет надлежащую поддержку ScaleType и необязательную округлую границу.

140 голосов
/ 05 января 2017

Другой простой способ - использовать 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>

enter image description here

119 голосов
/ 20 октября 2014

В версии 21 библиотеки поддержки теперь есть решение: оно называется RoundedBitmapDrawable .

Это в основном так же, как обычный Drawable, за исключением того, что вы даете ему угловой радиус для отсечения с помощью:

setCornerRadius(float cornerRadius)

Итак, начиная с Bitmap src и цели ImageView, это будет выглядеть примерно так:

RoundedBitmapDrawable dr = RoundedBitmapDrawableFactory.create(res, src);
dr.setCornerRadius(cornerRadius);
imageView.setImageDrawable(dr);
97 голосов
/ 07 июня 2015

Обрезка до округлых форм добавлена ​​в класс View в API 21.

Просто сделайте это:

  • Создайте рисованную закругленную форму, примерно так:

Рез / рисуем / 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)

Вот как это будет выглядеть:

enter image description here

Примечание:

Этот метод работает для любой нарисованной фигуры (не только округленной). Он будет обрезать ImageView к любой форме фигуры, которую вы определили в своем Drawable XML.

Специальное примечание о ImageViews

setClipToOutline() работает только в том случае, если фон вида установлен на форму для рисования. Если эта фоновая фигура существует, View рассматривает контур фигуры как границы для целей отсечения и затенения.

Это означает, что если вы хотите использовать setClipToOutline() для округления углов в ImageView, ваше изображение должно быть настроено с использованием android:src вместо android:background (поскольку фон должен быть установлен в вашу округлую форму). Если вы ДОЛЖНЫ использовать фон, чтобы установить изображение вместо src, вы можете использовать этот обходной путь:

  • Создание макета и установка его фона для рисования
  • Оберните этот макет вокруг вашего ImageView (без заполнения)
  • ImageView (включая все остальное в макете) теперь будет отображаться с закругленной формой макета.
55 голосов
/ 20 октября 2016

Я сделал с помощью Custom 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" />

Выход:

enter image description here

Надеюсь, это поможет вам.

53 голосов
/ 10 марта 2011

Я обнаружил, что оба метода очень помогли найти рабочее решение. Вот моя составная версия, которая не зависит от пикселей и позволяет вам иметь некоторые квадратные углы, а остальные углы имеют одинаковый радиус (что является обычным вариантом использования). Благодаря обоим решениям выше:

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

Надеюсь, это поможет!

46 голосов
/ 27 мая 2014

Округленное изображение Использование 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 Библиотека с площади.

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 здесь здесь

25 голосов
/ 23 октября 2013

Поскольку все ответы казались мне слишком сложными только для углов, я подумал и пришел к другому решению, которым, на мой взгляд, стоит поделиться, только с 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>
19 голосов
/ 20 февраля 2019

Быстрое решение 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.

...