programing

모서리가 둥근 이미지 보기를 만드는 방법은 무엇입니까?

newsource 2023. 8. 8. 21:39

모서리가 둥근 이미지 보기를 만드는 방법은 무엇입니까?

Android에서 ImageView는 기본적으로 직사각형입니다.이미지 보기에서 비트맵을 둥근 사각형(원형 직사각형으로 만들려면 비트맵의 네 모서리를 모두 잘라내십시오)으로 만들려면 어떻게 해야 합니까?


부터는 2021년식을 .ShapeableImageView

응답이 꽤 늦었지만, 이것을 찾는 다른 사람들을 위해 다음 코드를 수행하여 이미지의 모서리를 수동으로 반올림할 수 있습니다.

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

이것은 제 코드는 아니지만, 저는 그것을 사용했고 그것은 훌륭하게 작동합니다.이미지 내에서 도우미로 사용했습니다.헬퍼 클래스는 주어진 이미지에 필요한 깃털의 양을 전달하기 위해 약간 확장되었습니다.

최종 코드는 다음과 같습니다.

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

또 다른 쉬운 방법은 모서리 반지름이 있는 CardView와 내부에 ImageView를 사용하는 것입니다.

  <androidx.cardview.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"
                />
        </androidx.cardview.widget.CardView>

enter image description here

둥근 모양으로의 클리핑이 API 21의 클래스에 추가되었습니다.

이렇게 하면 됩니다.

  • 다음과 같은 둥근 모양 그리기 가능한 모양을 만듭니다.

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

참고:

이 방법은 모든 그리기 가능한 모양(원형만 있는 것이 아님)에 적용됩니다.그리기 가능한 xml에서 정의한 모양 윤곽선에 이미지 보기를 클리핑합니다.

이미지 보기에 대한 특별 참고 사항

setClipToOutline()보기의 배경이 그리기 가능한 모양으로 설정된 경우에만 작동합니다.이 배경 도형이 존재하는 경우 보기는 도형의 윤곽선을 잘라내기 및 음영 처리를 위한 테두리로 처리합니다.

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

  • 레이아웃을 작성하고 배경을 도형 그리기 가능으로 설정
  • 해당 레이아웃을 이미지 보기 주위로 래핑(패딩 없음)
  • 이제 이미지 보기(레이아웃에 있는 다른 항목 포함)가 둥근 레이아웃 모양으로 표시됩니다.

위의 답변이 효과가 있지만, 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);

다른 방법에 비해 이점은 다음과 같습니다.

  • 비트맵의 별도 복사본을 만들지 않습니다. 비트맵은 큰 이미지와 함께 많은 메모리를 사용합니다 [여기에 있는 대부분의 다른 답변].
  • 안티앨리어싱 지원 [vs clipPath 메서드]
  • 알파 지원 [vs xfermode+porterduff 방식]
  • 하드웨어 가속 지원 [vs clipPath 메서드]
  • 캔버스에 한 번만 그릴 수 있습니다 [vs xfermode 및 clippath 방법].

나는 이 코드를 기반으로 이 논리를 ImageView로 감싸고 적절한 값을 추가하는 Round ImageView를 만들었습니다.ScaleType지원 및 선택적인 둥근 테두리.

재료 구성요소 라이브러리 버전부터 새로운 버전이 출시되었습니다.

다음과 같은 것을 사용할 수 있습니다.

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

의 의범내에.themes.xml:

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

enter image description here


제트 팩 컴포지트를 사용하여 다음을 적용할 수 있습니다. Modifier사용:

Image(
    painter = painterResource(R.drawable.xxxx),
    contentDescription = "xxxx",
    contentScale = ContentScale.Crop,            
    modifier = Modifier
        .size(64.dp)
        .clip(RoundedCornerShape(8.dp))             
)

지원 라이브러리의 v21에는 이제 RoundedBitmapDrawable이라는 솔루션이 있습니다.

기본적으로 일반 드로잉 가능한 것과 같습니다. 단, 클리핑을 위한 모서리 반지름은 다음과 같습니다.

setCornerRadius(float cornerRadius)

그서일단은으로 합니다.Bitmap src 목표물 적표.ImageView다음과 같이 보일 것입니다.

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

빠른 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 및 Scale에서 원하는 너비, 높이 및 반지름을 설정할 수 있습니다.이미지 보기를 입력합니다.

X와 Android X » 사용하기<androidx.cardview.widget.CardView>

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

또는 사용할 수 있습니다.PicassoSquare에서 온 도서관.

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

여기에서 RoundTransformation 파일을 다운로드할 수 있습니다.

모든 답변이 너무 복잡하여 둥근 모서리에만 적용할 수 없을 것 같았기 때문에 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>

이 작업은 다음과 같이 수행할 수 있습니다.ShapeableImageView용사를 ShapeAppearanceOverlay:

<com.google.android.material.imageview.ShapeableImageView
    android:id="@+id/avatar"
    android:layout_width="64dp"
    android:layout_height="64dp"
    android:padding="4dp"
    app:shapeAppearance="@style/ShapeAppearanceOverlay.Avatar"/>

style 디타스일어ShapeAppearanceOverlay.Avatar는 에니합다상에 합니다.res/values/styles.xml:

<style name="ShapeAppearanceOverlay.Avatar" parent="ShapeAppearance.MaterialComponents.SmallComponent">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">50%</item>
</style>

동일한 이은동됩니것면다하등.layout_height그리고.layout_width세트, 그렇지 않으면 알약이 될 것이고 원은 없습니다.

둥근 모서리가 있는 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의 Generated API를 사용하는 다른 방법이 있습니다.초기 작업이 필요하지만 실제 코드를 작성하기 때문에 무엇이든 할 수 있는 유연성을 갖춘 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);

이미지 보기를 만들 수 있는 멋진 라이브러리가 있습니다.

다음은 예입니다.

<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

재료 구성 요소 라이브러리를 사용해 보십시오.ShapeableImageView.
: 와같것은이::

Java:

imageView=new ShapeableImageView(context);
imageView.setShapeAppearanceModel(
        imageView.getShapeAppearanceModel()
                 .toBuilder()
                 .setAllCornerSizes(20)
                 .build());

코틀린:

val imageView = ShapeableImageView(context)
imageView.setShapeAppearanceModel(
        imageView.getShapeAppearanceModel()
                 .toBuilder()
                 .setAllCornerSizes(20f)
                 .build())

enter image description here

다음은 imageView를 재정의하는 간단한 예입니다. 그런 다음 레이아웃 디자이너에서 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

코틀린

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아래와 같이:

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

그것은 당신의 친구에게 도움이 될 것입니다.

당신은 야합다니를 확장해야 .ImageView둥근 직사각형을 그리세요.

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

[edit]를 사용하여 프레임을 겹쳐 원래 이미지를 엽니다.FrameLayout예들면번. 첫째요의 .FrameLayout반올림하여 표시할 이미지가 됩니다.그런 다음 다른 항목을 추가합니다.ImageView틀에 박혀서두번째ImageView원본 위에 표시됩니다.ImageView따라서 Android는 원본 위에 내용을 그릴 것입니다.ImageView.

위의 George Walters II에 대한 지지로, 저는 그의 답변을 받아들였고 개별 모서리를 다르게 반올림하는 것을 지원하기 위해 약간 확장했습니다.이것은 약간 더 최적화될 수 있지만(일부 대상 정류가 겹칩니다), 전체적으로는 그렇지 않습니다.

이 스레드가 약간 오래된 것은 알지만 안드로이드에서 ImageView의 모서리를 반올림하는 방법에 대한 구글의 쿼리에 대한 최고 결과 중 하나입니다.

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

로메인 가이가 그 자리에 있습니다.

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

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

클리핑을 수행하는 것이 어떻습니까?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;
        }
    }

}

이 순수한 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>

레이아웃 파일에서 표준 이미지 보기와 중첩된 프레임 레이아웃을 포함하는 선형 레이아웃을 추가합니다.프레임 레이아웃은 패딩과 커스텀 드로잉 가능을 사용하여 둥근 모서리의 느낌을 줍니다.

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

답변에 제공된 어떤 방법도 저에게 효과가 없었습니다.안드로이드 버전이 5.0 이상이면 다음과 같은 방식으로 작동한다는 것을 알게 되었습니다.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

    ViewOutlineProvider provider = new ViewOutlineProvider() {
        @Override
        public void getOutline(View view, Outline outline) {
            int curveRadius = 24;
            outline.setRoundRect(0, 0, view.getWidth(), (view.getHeight()+curveRadius), curveRadius);
        }
    };
    imageview.setOutlineProvider(provider);
    imageview.setClipToOutline(true);
}

정의할 xml 셰이프가 없으며 위의 코드는 정상적인 메서드가 작동하지 않는 상단에만 모서리를 만듭니다.4개의 모서리를 둥글게 처리해야 하는 경우 다음을 제거합니다.

"+ curveRadius"  

setRoundRect의 하단에 대한 매개변수에서.필요에 맞는 윤곽선을 지정하여 도형을 다른 도형으로 확장할 수 있습니다.다음 링크를 확인하십시오.

Android 개발자 설명서.


Android의 다른 방법과 마찬가지로 일반적으로 DP에서 크기를 "변환"해야 합니다.위의 예에서 반지름을 24로 한다고 가정합니다.

                            int curveRadius = 24;

예를 들어, 나중에 반경이 "24"로 설정된 그리기 가능한 영역에 테두리를 추가할 수 있으며 일치시킬 수 있습니다.이런 이유로,

    float desiredRadius = 24;
    float radiusConverted = TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP,
            desiredRadius,
            itemView.getContext().getResources().getDisplayMetrics());

그리고 나서.

                            int curveRadius = radiusConverted;

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

}

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

먼저 답변해 주셔서 감사합니다.직사각형 이미지를 사각형(원형) 이미지로 변환하고 채우기 색상을 매개 변수로 전달하는 수정 버전입니다.

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

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

여기에 리디렉션된 질문에 대한 대답: "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;
}

언급URL : https://stackoverflow.com/questions/2459916/how-to-make-an-imageview-with-rounded-corners