문제

Android에서 ImageView는 기본적으로 직사각형입니다.ImageView에서 어떻게 둥근 직사각형으로 만들 수 있습니까(비트맵의 네 모퉁이를 모두 잘라 둥근 직사각형이 되도록)?

도움이 되었습니까?

해결책

답변이 꽤 늦었지만, 이를 찾는 다른 사람을 위해 다음 코드를 사용하여 이미지 모서리를 수동으로 둥글게 만들 수 있습니다.

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

이것이 누군가에게 도움이 되기를 바랍니다!

다른 팁

위의 답변이 작동하는 동안 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 방법과 비교]
  • 지원하다 알파 [vs xfermode+porterduff 방법]
  • 지원하다 하드웨어 가속 [clipPath 방법과 비교]
  • 오직 캔버스에 한 번 그립니다. [xfermode 및 클립 경로 방법과 비교]

나는 둥근이미지보기 이 논리를 ImageView로 래핑하고 적절한 추가 기능을 추가하는 이 코드를 기반으로 합니다. ScaleType 지원 및 선택적 둥근 테두리.

또 다른 쉬운 방법은 모서리 반경이 있는 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

이제 지원 라이브러리 v21에는 이에 대한 솔루션이 있습니다.~라고 불린다 둥근비트맵드로어블.

다음을 사용하여 클리핑을 위한 모서리 반경을 지정한다는 점을 제외하면 기본적으로 일반 Drawable과 같습니다.

setCornerRadius(float cornerRadius)

그래서 시작해서 Bitmap src 그리고 목표 ImageView, 다음과 같이 보일 것입니다 :

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

둥근 모양으로 자르기가 추가되었습니다. View API 21의 클래스입니다.

이렇게 하세요:

  • 다음과 같이 둥근 모양의 드로어블을 만듭니다.

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

메모:

이 방법은 다음과 같은 경우에 효과적입니다. 어느 그릴 수 있는 모양(둥근 모양이 아님).Drawable xml에 정의한 모양 윤곽선에 맞게 ImageView를 자릅니다.

ImageView에 대한 특별 참고 사항

setClipToOutline() View의 배경이 Shape Drawable로 설정된 경우에만 작동합니다.이 배경 모양이 존재하는 경우 View는 모양의 윤곽선을 클리핑 및 그림자 적용을 위한 테두리로 처리합니다.

즉, 사용하려는 경우 setClipToOutline() ImageView의 모서리를 둥글게 하려면 다음을 사용하여 이미지를 설정해야 합니다. android:src 대신에 android:background (배경은 둥근 모양으로 설정해야 하므로)src 대신 배경을 사용하여 이미지를 설정해야 하는 경우 다음 해결 방법을 사용할 수 있습니다.

  • 레이아웃을 만들고 배경을 모양 그리기 가능으로 설정합니다.
  • ImageView 주위에 해당 레이아웃을 배치합니다(패딩 없음).
  • 이제 ImageView(레이아웃의 다른 항목 포함)가 둥근 레이아웃 모양으로 표시됩니다.

나는 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

이것이 당신에게 도움이 되기를 바랍니다.

나는 두 가지 방법 모두 작업 솔루션을 찾는 데 매우 도움이 된다는 것을 알았습니다.여기에 내 합성 버전이 있습니다. 이는 픽셀 독립적이며 일부 정사각형 모서리와 동일한 반경을 갖는 나머지 모서리를 가질 수 있습니다(일반적인 사용 사례임).위의 두 가지 솔루션 덕분에:

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

또한 이를 XML에 정의할 수 있도록 ImageView를 재정의했습니다.여기에 슈퍼 호출이 만드는 논리 중 일부를 추가하고 싶을 수도 있지만 제 경우에는 도움이 되지 않기 때문에 이에 대해 언급했습니다.

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

도움이 되었기를 바랍니다!

둥근 이미지 사용 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 파일을 다운로드할 수 있습니다.여기

빠른 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에서는 원하는 너비, 높이, 반경을, ImageView에서는 scaleType을 설정할 수 있습니다.

모든 답변이 둥근 모서리에 비해 너무 복잡해 보였기 때문에 이미지 주위에 공간이 있는 경우 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>

둥근 모서리 위젯을 사용하여 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);

    }

}

최근에는 다른 방법이 있습니다. Glide에서 생성된 API.약간의 초기 작업이 필요하지만 실제 코드를 작성하기 때문에 무엇이든 할 수 있는 유연성과 함께 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);

이있다 멋진 도서관 이를 통해 이미지 뷰를 형성할 수 있습니다.

예는 다음과 같습니다.

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

결과:

result

연장해야 해 ImageView 그리고 자신만의 둥근 직사각형을 그려보세요.

이미지 주위에 프레임을 원하는 경우 레이아웃의 이미지 보기 위에 둥근 프레임을 겹쳐 놓을 수도 있습니다.

[편집] 원본 이미지에 프레임을 겹쳐서 사용하세요. FrameLayout 예를 들어.첫 번째 요소는 FrameLayout 둥근 모양으로 표시하려는 이미지가 됩니다.그런 다음 다른 것을 추가하세요 ImageView 프레임과 함께.두번째 ImageView 원본 위에 표시됩니다. ImageView 따라서 Android는 원본 위에 콘텐츠를 그립니다. ImageView.

위의 George Walters II에 대한 제안으로 저는 그의 답변을 받아들여 개별 모서리를 다르게 둥글게 하는 것을 지원하도록 약간 확장했습니다.이는 좀 더 최적화할 수 있지만(일부 대상 직사각형이 겹침) 전체적으로는 그렇지 않습니다.

이 스레드는 약간 오래되었지만 Android에서 ImageView의 모서리를 둥글게 만드는 방법에 대한 Google 쿼리의 상위 결과 중 하나입니다.

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

draw()에서 클리핑을 수행하지 않는 이유는 무엇입니까?

내 해결책은 다음과 같습니다.

  • 클리핑으로 RelativeLayout 확장
  • 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;
    }
}
}

Romain Guy가 바로 그 곳입니다.

다음과 같이 축소된 버전입니다.

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

내 경우에는 이 순수 XML 솔루션만으로도 충분했습니다. http://www.techrepublic.com/article/pro-tip-round-corners-on-an-android-imageview-with-this-hack/

편집하다

간단히 말해서 대답은 다음과 같습니다.

/res/drawable 폴더에 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>

레이아웃 파일에 표준 ImageView와 중첩된 FrameLayout이 포함된 LinearLayout을 추가합니다.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를 재정의하는 간단한 예입니다. 그런 다음 레이아웃 디자이너에서 이를 사용하여 미리 볼 수도 있습니다.

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로 미리보기:

enter image description here

다음은 배치된 모든 하위 개체 주위에 둥근 사각형을 그리는 둥근 사각형 레이아웃 개체를 만듭니다.또한 레이아웃 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;
 }

}

모양을 적용하세요. 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>

그것은 당신 친구에게 도움이 될 수 있습니다.

첫 번째 답변에 감사드립니다.다음은 직사각형 이미지를 정사각형 이미지(및 둥근 이미지)로 변환하고 채우기 색상이 매개변수로 전달되는 수정된 버전입니다.

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

코틀린

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

당신은 사용할 수 있습니다 ImageView 레이아웃 및 사용 glide, 이 방법을 사용하여 둥근 모서리를 적용할 수 있습니다.

먼저 gradle에서 작성하고,

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

여기로 리디렉션되는 질문에 대한 답변:"Android에서 원형 ImageView를 만드는 방법은 무엇입니까?"

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

의 도움으로 활주 도서관과 둥근비트맵DrawableFactory 수업은 달성하기 쉽습니다.원형 자리 표시자 이미지를 만들어야 할 수도 있습니다.

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

이미지가 인터넷에 있는 경우 가장 좋은 방법은 글라이드를 사용하는 것입니다. 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);
    }
});

Glide Library를 사용하는 경우 다음이 도움이 될 것입니다.

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와 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)

답변이 꽤 많아요!

나는 몇몇 사람들이 제안한 이 예를 따랐습니다. http://www.techrepublic.com/article/pro-tip-round-corners-on-an-android-imageview-with-this-hack/

그러나 나에게 필요한 것은 투명한 이미지 뒤에 색칠된 원이었습니다.같은 일에 관심이 있는 사람을 위해...

1) FrameLayout을 너비와 높이로 설정합니다. 제 경우에는 이미지 크기(50dp)입니다.
2) 이미지가 있는 ImageView 위에 src = "@drawable/..."이 있는 ImageView를 배치합니다.ID를 부여하세요. 제 경우에는 iconShape라고 불렀습니다.
3) drawable mask.xml은 #ffffffff의 단색을 가져야합니다. 4) 코드에서 원 색상을 동적으로 변경하려면

ImageView iv2 = (ImageView) v.findViewById(R.id.iconShape);
Drawable shape = getResources().getDrawable(R.drawable.mask);
shape.setColorFilter(Color.BLUE, Mode.MULTIPLY);
iv2.setImageDrawable(shape);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top