Wie erstelle ich eine ImageView mit abgerundeten Ecken?

573

In Android ist eine ImageView standardmäßig ein Rechteck. Wie kann ich in der ImageView ein abgerundetes Rechteck erstellen (alle 4 Ecken meiner Bitmap abschneiden, um abgerundete Rechtecke zu erhalten)?

Michael
quelle
Dies könnte hilfreich sein stackoverflow.com/questions/26850780/…
Mangesh
Unter älteren, komplizierteren Antworten ist das versteckt, was meiner Meinung nach jetzt die akzeptierte Antwort sein sollte: RoundedBitmapDrawable , hinzugefügt in
Version
Sie können es am einfachsten tun, indem Sie einfach die CardView mit einer ImageView im Inneren verwenden - sehen Sie sich das Beispiel hier an stackoverflow.com/a/41479670/4516797
Taras Vovkovych
Diese Bibliothek ist sehr nützlich.
Grrigore
Überprüfen Sie dies jetzt müssen wir ShapeableImageViewkreisförmige oder abgerundete imageView stackoverflow.com/a/61086632/7666442
Nilesh Rathod

Antworten:

544

Dies ist eine ziemlich späte Antwort, aber für alle anderen, die danach suchen, können Sie den folgenden Code ausführen, um die Ecken Ihrer Bilder manuell abzurunden.

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

Dies ist nicht mein Code, aber ich habe ihn verwendet und er funktioniert wunderbar. Ich habe es als Helfer in einer ImageHelper-Klasse verwendet und es nur ein wenig erweitert, um die Menge an Federn zu übergeben, die ich für ein bestimmtes Bild benötige.

Der endgültige Code sieht folgendermaßen aus:

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

Hoffe das hilft jemandem!

George Walters II
quelle
4
Es funktioniert nicht für alle Geräte. Muss ich irgendwo etwas ändern?
Spring Breaker
7
Für ein 200 * 200-Bild dauert dies fast 0,03 Sekunden. Ich denke, das ist nicht die beste Lösung.
Jacky
2
Es rundet nur die oberen linken und oberen rechten Ecken ab. Warum ?
Prateek
1
@ vinc3m1 Lösung hier github.com/makeramen/RoundedImageView funktioniert wirklich gut! siehe auch seine Antwort ( stackoverflow.com/a/15032283/2048266 )
Nommer
16
Funktioniert nicht gut, wenn versucht wird, den Skalentyp von imageview festzulegen. Nur fitXY funktioniert. CenterCrop und andere zeigen unvorhersehbare Ergebnisse. Hat hier jemand die gleichen Probleme?
Shivansh
211

Während die obige Antwort funktioniert, zeigt Romain Guy (ein zentraler Android-Entwickler) in seinem Blog eine bessere Methode, die weniger Speicher benötigt, indem ein Shader verwendet wird, der keine Kopie der Bitmap erstellt. Der allgemeine Kern der Funktionalität ist hier:

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

Dies hat gegenüber anderen Methoden folgende Vorteile:

  • erstellt keine separate Kopie der Bitmap, die bei großen Bildern viel Speicherplatz beansprucht [im Vergleich zu den meisten anderen Antworten hier]
  • unterstützt Antialisasing [vs clipPath Methode]
  • unterstützt Alpha [vs Xfermode + Porterduff-Methode]
  • unterstützt Hardwarebeschleunigung [vs clipPath Methode]
  • Zeichnet nur einmal auf die Zeichenfläche [vs xfermode- und clippath-Methoden]

Ich habe eine RoundedImageView basierend auf diesem Code erstellt, die diese Logik in eine ImageView einschließt und die richtige ScaleTypeUnterstützung und einen optionalen abgerundeten Rand hinzufügt .

vinc3m1
quelle
/ example / res / layout / rounded_item.xml Warum geben Sie in Ihrem Warum einen Bild-Quellcode an, wenn alle Ihre Quellen fest codiert sind? Schöne Demo, einfach übertrieben.
Jemand irgendwo
Ihre Probe hat ein ernstes Problem mit zu wenig Speicher, genau wie die Originalprobe von Romain Guy. Ich weiß immer noch nicht, was es verursacht, aber genau wie sein Code ist dies eine wirklich schwer zu findende Sache. Wenn Sie aufgrund von OOM keinen Absturz der App sehen können, können Sie die App mehrmals drehen, bis sie auftritt (abhängig von Ihrem Gerät, ROM usw.). Ich habe in der Vergangenheit hier darüber berichtet: stackoverflow.com/questions/14109187/…
Android-Entwickler
1
Niemand anderes meldet das Problem mit zu wenig Speicher, daher muss es etwas sein, das Sie außerhalb des Codes tun, das falsch ist. Das Beispiel enthält eine begrenzte Anzahl von Bitmaps korrekt im Adapter, ohne sie jedes Mal neu zu erstellen, wenn eine Ansicht gezeichnet wird. Das hier gezeigte Beispiel ist ein Ausschnitt aus der draw () -Methode in Drawable, die den Verweis auf die ursprüngliche Bitmap verwendet, die sie enthält und ordnungsgemäß funktioniert. Die ursprüngliche Bitmap soll nicht geändert, sondern nur mit abgerundeten Ecken gerendert werden. Die mittlere Ernte funktioniert auch im Beispiel einwandfrei.
vinc3m1
1
Wenn Sie Screenshots oder Geräte bereitstellen können, auf denen dies nicht funktioniert, oder sogar eine Fix- und Pull-Anforderung anbieten können, ist dies am produktivsten. Ich habe das mehrfache Drehen auf meinen Geräten getestet und der Speicher bleibt gleich.
vinc3m1
11
Beachten Sie, dass dies nicht funktioniert, wenn die Bildgröße über 2048 Pixel liegt. Der Shader unterstützt keine Textur, die größer als diese ist.
Gábor
209

Eine andere einfache Möglichkeit ist die Verwendung einer CardView mit dem Eckenradius und einer ImageView im Inneren:

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

Geben Sie hier die Bildbeschreibung ein

Taras Vovkovych
quelle
5
Scheint eine gute Lösung zu sein. Es werden jedoch keine Bilder auf Pre-Lollipops abgeschnitten.
Nikolai
1
Was ist, wenn wir nur den Radius in der oberen linken und oberen rechten Ecke und nicht in allen Ecken wollen?
Pratik Singhal
3
Sehr einfache und intelligente Möglichkeit, Kurvenränder in jeder Ansicht anzuwenden.
AMI CHARADAVA
1
Gute Lösung, aber Elevation wird nur in API Level 21 und höher unterstützt
Saad Bilal
1
Um die Kartenhöhe zu deaktivieren, benutze die App: cardElevation = "0dp" (nicht android: height)
Johnny Five
149

Das Abschneiden auf abgerundete Formen wurde der ViewKlasse in API 21 hinzugefügt .

Mach das einfach:

  • Erstellen Sie eine abgerundete Form, die wie folgt gezeichnet werden kann:

res / drawable / round_outline.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="10dp" />
    ...
</shape>
  • Legen Sie das Zeichen als Hintergrund für Ihre ImageView fest: android:background="@drawable/round_outline"
  • Gemäß dieser Dokumentation müssen Sie nur noch hinzufügenandroid:clipToOutline="true"

Leider gibt es einen Fehler und dieses XML-Attribut wird nicht erkannt. Zum Glück können wir das Clipping noch in Java einrichten:

  • In Ihrer Aktivität oder Ihrem Fragment: ImageView.setClipToOutline(true)

So wird es aussehen:

Geben Sie hier die Bildbeschreibung ein

Hinweis:

Diese Methode funktioniert für jede zeichnbare Form (nicht nur abgerundet). Die ImageView wird an die Formkontur angepasst, die Sie in Ihrer Drawable-XML definiert haben.

Besonderer Hinweis zu ImageViews

setClipToOutline()Funktioniert nur, wenn der Hintergrund der Ansicht auf eine Form eingestellt ist, die gezeichnet werden kann. Wenn diese Hintergrundform vorhanden ist, behandelt View den Umriss der Form als Rahmen für Beschneidungs- und Schattenzwecke.

Dies bedeutet, wenn Sie setClipToOutline()die Ecken in einer ImageView abrunden möchten, muss Ihr Bild android:srcanstelle von festgelegt werden android:background(da der Hintergrund auf Ihre abgerundete Form eingestellt werden muss). Wenn Sie den Hintergrund verwenden müssen, um Ihr Bild anstelle von src festzulegen, können Sie diese Problemumgehung verwenden:

  • Erstellen Sie ein Layout und stellen Sie den Hintergrund auf Ihre Form ein
  • Wickeln Sie dieses Layout um Ihre ImageView (ohne Polsterung).
  • Die ImageView (einschließlich aller anderen Elemente im Layout) wird jetzt mit abgerundeter Layoutform angezeigt.
hungrighost
quelle
10
Fehler: (x) Keine Ressourcen-ID für das Attribut 'clipToOutline' im Paket 'android' gefunden
Anu Martin
7
Stattdessen android:clipToOutlinemuss man verwenden android:outlineProvider="background".
WindRider
2
Ein weiterer Grund, warum ich Google so "liebe", ist, dass dieser Fehler fast in meinem Alter ist und sich immer noch in seiner kleinen Welt befindet. Google scheint kein Cr * ap darüber zu geben))
Farid
1
Ich scheine mit dieser Methode keinen Erfolg zu haben, wenn ich nur die linke und die obere rechte Ecke in der Hintergrundform auf abgerundet setze.
Peterdk
@AnuMartin Dies ist ein bekanntes Problem - issuetracker.google.com/issues/37036728
Vadim Kotov
132

In Version 21 der Support-Bibliothek gibt es jetzt eine Lösung dafür: RoundedBitmapDrawable .

Es ist im Grunde wie ein normales Drawable, außer dass Sie ihm einen Eckradius für das Abschneiden geben mit:

setCornerRadius(float cornerRadius)

Ausgehend von Bitmap srceinem Ziel ImageViewwürde es also ungefähr so ​​aussehen:

RoundedBitmapDrawable dr = RoundedBitmapDrawableFactory.create(res, src);
dr.setCornerRadius(cornerRadius);
imageView.setImageDrawable(dr);
tyczj
quelle
3
Vielen
David d C e Freitas
eigentlich gibt es android.support.v4.graphics.drawable.RoundedBitmapDrawableFactoryso v4auch unterstützungen.
Deadfish
2
@deadfish ja, es ist in der v4Support-Bibliothek, aber erst REVISION 21in der Support-Bibliothek
Tyczj
3
Diese Lösung ist einfach und aktuell. Es erfordert die geringste Menge an Code und ist sehr erweiterbar. Kann mit Bildern aus lokalen Dateien, zwischengespeicherten Zeichen oder sogar mit Volleys NetworkImageView arbeiten. Ich stimme sehr zu, dass dies heutzutage die akzeptierte Antwort sein sollte, wie @Jonik betonte.
Katie
2
Funktioniert leider nicht mit scaleType centerCrop(Support Library v25.3.1)
Rocknow
67

Ich habe von Custom ImageView gemacht:

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

Wie benutzt man:

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

Ausgabe:

Geben Sie hier die Bildbeschreibung ein

Hoffe das würde dir helfen.

Hiren Patel
quelle
Dies macht Bild verschwimmen
Amit Hooda
2
funktioniert auch mit android: scaleType = "centerCrop", einfach, erstellt keine neue Bitmap. Vielen Dank!
ernazm
1
@Hiren Diese Lösung funktioniert gut für ImageView mit einem Hintergrundbild. Es funktioniert jedoch nicht für ImageViews, die nur Hintergrundfarbe und kein Bild haben. Können Sie mir bitte sagen, warum das passiert?
user2991413
Canvas.clipPath()kann java.lang.UnsupportedOperationExceptionin einigen Fällen verursachen. Siehe stackoverflow.com/questions/13248904/…
Artyom
1
Diese Lösung funktioniert nur für Bildsätze mit android:background, aber nicht android:src.
CoolMind
64

Eine schnelle XML-Lösung -

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

Sie können die gewünschte Breite, Höhe und den gewünschten Radius in CardView und scaleType in ImageView festlegen.

Verwenden Sie mit AndroidX <androidx.cardview.widget.CardView>

Chirag Mittal
quelle
4
Dieser Ansatz funktionierte in meinem Fall mit androidx.cardview.widget.CardView
Ivan
7
Nicht sicher, warum dies nicht mehr Upvotes hat? Meiner Meinung nach die beste Lösung ohne Bibliotheken und jede Menge beschissenen Code (obwohl ich in meinem Fall die CenterCrop-Skalierung verwendet habe).
ThemBones
1
Noch nicht viele positive Stimmen, weil es eine neue Antwort ist. Aber ich habe meine +1 gesetzt, um sie bald nach oben zu bringen! Vielen Dank!
Micer
Es funktioniert jedoch, aber hier wird sich das Bild aufgrund von scaleType="fitXY"@ThemBones
WIZARD
@ WIZARD Deshalb habe ich erwähnt, dass Sie Ihren gewünschten Skalentyp auf ImageView
Chirag Mittal
57

Ich fand, dass beide Methoden sehr hilfreich waren, um eine funktionierende Lösung zu finden. Hier ist meine zusammengesetzte Version, die pixelunabhängig ist und es Ihnen ermöglicht, einige quadratische Ecken zu haben, wobei der Rest der Ecken den gleichen Radius hat (was der übliche Anwendungsfall ist). Dank an beide oben genannten Lösungen:

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

Außerdem habe ich ImageView überschrieben, um dies einzufügen, damit ich es in XML definieren kann. Vielleicht möchten Sie einen Teil der Logik hinzufügen, die der Superaufruf hier ausführt, aber ich habe ihn kommentiert, da er in meinem Fall nicht hilfreich ist.

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

Hoffe das hilft!

Caspar Harmer
quelle
4
ziemlich genial, besonders das Erweitern der ImageView
Someone Somewhere
2
Eine einfache Möglichkeit, die Logik der ImageView # onDraw () beizubehalten, besteht darin, die Bitmap mit abgerundeten Ecken auf die Zeichenfläche der ImageView zu setzen und die Bitmap mit super.onDraw () zu zeichnen. Ich habe eine Klasse RoundedCornerImageView erstellt. Das Anwendungsbeispiel finden Sie hier . Bitte beachten Sie, dass die von mir verwendete getRoundedCornerBitmap () nicht pixelunabhängig ist.
Umbalaconmeogia
Vielen Dank für die RoundedCornerImageView. Ich habe es verwendet, aber so modifiziert, dass es unabhängig von der Pixeldichte ist.
PacificSky
Der Quellcode für Umbas RoundedCornerImageView ist hier: code.google.com/p/android-batsg/source/browse/trunk/…
Jemand irgendwo
@Caspar Harmer funktioniert gut, nur 1 Bearbeitung ... es gibt vier Bedingungen. Ändern Sie sie einfach so, als ob ich wahr, wahr, falsch, falsch setzen würde. Es wird die untere Ecke anstelle der oberen Ecke gesetzt. Andernfalls funktioniert der Code einwandfrei. Also squareTL und squareTR sind Bedingungen für squareBL bzw. squareBR..und umgekehrt.
TheFlash
48

Abgerundetes Bild ImageLoader Hier verwenden

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

Oder Sie können die PicassoBibliothek von Square aus verwenden.

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

Sie können hier RoundedTransformation Datei herunterladen hier

Shailesh
quelle
1
Bild nicht
angezeigt
3
Die Picasso Library One ist gut und sehr einfach zu implementieren, vielen Dank +1
Hitesh
3
Die Picasso-Bibliothek scheint das Bild "Platzhalter" und "Fehler" jedoch nicht zu transformieren. Wenn Ihr Bild also nicht geladen werden kann (Fehler) oder das Laden zunächst eine Weile dauert (Platzhalter), wird das Bild nicht als abgerundetes Bild angezeigt. github.com/square/picasso/issues/337
Pelpotronic
Weitere nützliche Picasso-Transformationen bietet diese Bibliothek, die auch eine RoundedCornersTransformation enthält: github.com/wasabeef/picasso-transformations
Massimo
Funktioniert nicht mit dem Zuschneiden von Bildern in Univ. Image Loader.
Yar
26

Da mir alle Antworten nur für runde Ecken zu kompliziert erschienen, dachte ich und kam zu einer anderen Lösung, die ich für sinnvoll halte, nur mit XML, falls Sie etwas Platz um das Bild haben:

Erstellen Sie eine Rahmenform mit transparentem Inhalt wie folgt:

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

In einem RelativeLayout können Sie dann zuerst Ihr Bild und dann mit einer anderen ImageView an derselben Stelle über der Form platzieren. Die Deckform sollte um den Umfang der Randbreite größer sein. Achten Sie darauf, einen größeren Eckenradius zu verwenden, da der äußere Radius definiert ist, aber der innere Radius bedeckt Ihr Bild.

Hoffe es hilft auch jemandem.

Bearbeiten Sie das entsprechende Layoutbeispiel gemäß CQM-Anforderung:

<?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>
Christian
quelle
Können Sie dies mit mehr Code näher erläutern, insbesondere was mit der zweiten Bildansicht gemacht wird und wo die XML-Datei "Rahmenform" angewendet wird (als src oder als Hintergrund?), hier einige Fragen. Ich möchte diese Lösung mögen, da ich damit alle vier Ecken unabhängig voneinander
steuern kann
1
Obwohl dies eine einfache Antwort zu sein scheint, fügt es leider einen Rand um die "maskierte" Bildansicht hinzu, was ein unerwünschter Nebeneffekt ist.
Abdalrahman Shatou
Ja, aber das gleiche funktioniert mit einer ImageView, die auf einem PNG-Drawable mit abgerundeten Ecken und transparentem Hintergrund basiert, oder einem 9-Patch-Drawable, wenn Sie einen undefinierten Aspekt haben.
Christian
Ich mache das gleiche und es funktioniert; Sie möchten nur wissen, ob dies keine Probleme mit der Ausrichtung und der unterschiedlichen Telefongröße verursacht.
geöffnet und frei
Wenn Sie die Abmessungen relativ zueinander halten, sollte dies kein Problem darstellen.
Christian
22

Ab der Version 1.2.0-alpha03der Material Components Library gibt es die neueShapeableImageView .

Sie können etwas verwenden wie:

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

mit:

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

Oder programmatisch:

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

Geben Sie hier die Bildbeschreibung ein

Gabriele Mariotti
quelle
Wenn das Bild eine Hintergrundfarbe hat, wird derzeit die Hintergrundfarbe erzeugt, die unter den abgerundeten Ecken angezeigt wird. Dadurch wird auch die Eigenschaft scaleType für das Bild ignoriert.
Inokey
14

Meine Implementierung von ImageView mit einem Widget mit abgerundeten Ecken, das das Bild (nach unten || nach oben) auf die erforderlichen Abmessungen anpasst. Es verwendet die Codeform 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);

    }

}
Damjan
quelle
12
Woher kommt ImageUtilities?
Jason Wyatt
1
@ JasonWyatt siehe Sorrodos Beitrag unten
Damjan
12

Seit kurzem gibt es einen anderen Weg - die Verwendung der generierten API von Glide . Es erfordert einige anfängliche Arbeiten, bietet Ihnen dann aber die ganze Kraft von Glide mit der Flexibilität, alles zu tun, da Sie den eigentlichen Code schreiben, sodass ich denke, dass dies auf lange Sicht eine gute Lösung ist. Außerdem ist die Verwendung sehr einfach und ordentlich.

Richten Sie zunächst Glide Version 4+ ein:

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

Erstellen Sie dann die App-Modulklasse von Glid, um die Annotationsverarbeitung auszulösen:

@GlideModule
public final class MyAppGlideModule extends AppGlideModule {}

Erstellen Sie dann die Glide-Erweiterung, die die Arbeit tatsächlich erledigt. Sie können es anpassen, um zu tun, was Sie wollen:

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

Erstellen Sie nach dem Hinzufügen dieser Dateien Ihr Projekt.

Verwenden Sie es dann wie folgt in Ihrem Code:

GlideApp.with(this)
        .load(imageUrl)
        .roundedCorners(getApplicationContext(), 5)
        .into(imageView);
Sir Codesalot
quelle
Vergessen Sie nicht, ein Leerzeichen zwischen RequestOptionsund optionsin params einzufügen
StevenTB
Erledigt. Danke für die Eingabe.
Sir Codesalot
.roundedCorners kommen nicht müssen wir noch etwas einrichten? Auch nach dem Wiederaufbau des Projekts
Dr. aNdRO
Das hat bei mir funktioniert, danke. Ich fand es einfacher, die Verwendung der mit @GlideExtensionAnmerkungen versehenen Klasse zu vermeiden, und ging einfach dahin, .transform(new RoundedCorners(px))wo pxes dasselbe ist ( int px = Math.round(cornerRadius * (context.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));).
Michael Osofsky
10

Es gibt eine coole Bibliothek , mit der Sie Bildansichten gestalten können.

Hier ist ein Beispiel:

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

Formdefinition:

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

Ergebnis:

Ergebnis

grrigore
quelle
1
Das ist großartig und macht viel mehr, als wenn Sie einen Rand hinzufügen und eine beliebige Form verwenden können
Adam Kis
8

Hier ist ein einfaches Beispiel, das imageView überschreibt. Sie können es dann auch im Layout-Designer zur Vorschau verwenden.

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

Dies ist für eine schnelle Lösung. Der Radius wird an allen Ecken verwendet und basiert auf dem Prozentsatz der Bitmap-Breite.

Ich habe gerade setImageDrawabledie Support v4-Methode für abgerundete Bitmap-Zeichen überschrieben und verwendet.

Verwendungszweck:

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

Vorschau mit imageView und benutzerdefiniertem imageView:

Geben Sie hier die Bildbeschreibung ein

toter Fisch
quelle
Das funktioniert in jeder Situation, danke. Du hast meinen Tag gerettet.
Mehul Solanki
7

Sie sollten ImageViewIhr eigenes abgerundetes Rechteck erweitern und zeichnen.

Wenn Sie einen Rahmen um das Bild haben möchten, können Sie den abgerundeten Rahmen auch über die Bildansicht im Layout legen.

[Bearbeiten] Überlagern Sie den Rahmen, um das Originalbild zu öffnen, indem Sie FrameLayoutbeispielsweise ein verwenden. Das erste Element von FrameLayoutwird das Bild sein, das Sie diplomatisch gerundet haben möchten. Fügen Sie dann einen weiteren ImageViewmit dem Rahmen hinzu. Die zweite ImageViewwird über dem Original angezeigt ImageViewund Android zeichnet den Inhalt über das Original ImageView.

MrSnowflake
quelle
Vielen Dank. Es gibt jedoch nur die setDrawable-Methode für ImageView. Wie kann ich Drawable der ImageView auf den Inhalt meines Bildes setzen und dann einen abgerundeten Rahmen über die ImageView legen?
Michael
Es tut mir leid, ich war unklar. Ich meinte, das Layout zu überlagern: Verwenden Sie also (dh) ein FrameLayoutPut- ImageViewIn und fügen Sie ein weiteres ImageViewmit dem abgerundeten Rahmen hinzu. Auf diese Weise zeigt das erste ImageViewdas ausgewählte Bild und das zweite ImageFrameden abgerundeten Rahmen an.
MrSnowflake
Richtig - mit FrameLayout können Sie ein Bild / eine Ansicht mit einem anderen überlagern. Sie können auch das android: foreground-Tag von FrameLayout verwenden.
Richard Le Mesurier
7

Romain Guy ist da, wo es ist.

Minimierte Version wie folgt.

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);
Alex
quelle
Obwohl es funktioniert, erstellt es leider genau wie die anderen Lösungen hier eine neue Bitmap, anstatt die aktuelle zu verwenden.
Android-Entwickler
nicht wirklich. bitmapRounded würde immer wieder verwendet. Wenn Sie Zugriff auf die Zeichenfläche hatten, können Sie die Zeichenmethode direkt verwenden, anstatt eine neue Bitmap zu generieren.
Alex
Wie machst du das? Angenommen, ich verwende kein spezielles Drawable und behandle nur eine einzelne Bitmap und verwende am Ende des Prozesses setImageBitmap. Wie würde ich so etwas erreichen?
Android-Entwickler
Beide ändern die Bitmap nicht, sondern umschließen sie mit einer benutzerdefinierten Zeichen- und einer benutzerdefinierten Bildansicht. Das ist nicht das, worüber ich gefragt habe. Ich fragte, wie Sie die Bitmap selbst ändern.
Android-Entwickler
7

Diese reine XML-Lösung war in meinem Fall gut genug. http://www.techrepublic.com/article/pro-tip-round-corners-on-an-android-imageview-with-this-hack/

BEARBEITEN

Hier ist die Antwort auf den Punkt gebracht:

Erstellen Sie im Ordner / res / drawable eine Datei frame.xml. Darin definieren wir ein einfaches Rechteck mit abgerundeten Ecken und einer transparenten Mitte.

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

In Ihrer Layoutdatei fügen Sie ein LinearLayout hinzu, das eine Standard-ImageView sowie ein verschachteltes FrameLayout enthält. Das FrameLayout verwendet Polsterung und benutzerdefiniertes Zeichnen, um die Illusion abgerundeter Ecken zu erzeugen.

<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>
j7nn7k
quelle
nette Idee, ich habe es benutzt, um eine ungleichmäßige ImageView-Ecke zu zeigen
Gal Rom
6

Requisiten an George Walters II oben, ich habe nur seine Antwort genommen und sie ein wenig erweitert, um das Abrunden einzelner Ecken unterschiedlich zu unterstützen. Dies könnte etwas weiter optimiert werden (einige der Zielbereiche überlappen sich), aber nicht viel.

Ich weiß, dass dieser Thread etwas alt ist, aber er ist eines der besten Ergebnisse bei Abfragen bei Google, wie man Ecken von ImageViews auf Android abrundet.

/**
 * 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;
}
Sorrodos
quelle
+1 zum Hinzufügen des Dichtemultiplikators und Hinzufügen von Unterstützung für einzeln abgerundete Ecken. Ich habe die Lösung oben verwendet, da Ihre Lösung nicht ganz funktioniert hat - aber sie war sehr hilfreich! Siehe meine zusammengesetzte Lösung unten:
Caspar Harmer
6

Wenden Sie eine Form imageViewwie folgt an:

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

es kann für deinen Freund hilfreich sein.

Jigar
quelle
6

Warum nicht einschneiden draw()?

Hier ist meine Lösung:

  • Erweitern Sie RelativeLayout mit Clipping
  • Fügen Sie ImageView (oder andere Ansichten) in das Layout ein:

Code:

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

}
Fischherbst
quelle
1
Ich mag diesen Ansatz. Ich habe es verwendet, um meine eigene RoundImageView zu erstellen. Danke dafür.
Pascal
Dies funktioniert nicht bei eingeschalteter Hardward-Beschleunigung, richtig? Ich habe keine einfache
Problemumgehung gesehen
Können Sie bitte zeigen, wie es geht, indem Sie das Ergebnis als Zeichenmaterial haben, die Möglichkeit haben, einen Umriss (AKA-Strich) um den Inhalt hinzuzufügen und auch nur einige der Ecken abzurunden?
Android-Entwickler
5

Im Folgenden wird ein Layoutobjekt für abgerundete Rechtecke erstellt, das ein abgerundetes Rechteck um alle darin platzierten untergeordneten Objekte zeichnet. Außerdem wird gezeigt, wie Ansichten und Layouts programmgesteuert erstellt werden, ohne die XML-Layoutdateien zu verwenden.

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

Die Klasse für das RoundedRectangle-Layoutobjekt ist wie folgt definiert:

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

}
Danny Remington - OMS
quelle
5

Kotlin

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)

Um ImageViewCircular zu machen , können wir ändern cornerRadiusmit:

rounded.isCircular = true
Vahid
quelle
4

Vielen Dank für die erste Antwort. Hier ist die modifizierte Version, um ein rechteckiges Bild in ein quadratisches (und abgerundetes) Bild umzuwandeln, und die Füllfarbe wird als Parameter übergeben.

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;
}
mkm
quelle
4

Wenn Sie die Glide Library verwenden, ist dies hilfreich:

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));
}
Anirudh
quelle
Wenn Sie Glide Version 4 und höher verwenden, verwenden Sie --- RequestOptions requestOptions = new RequestOptions (); requestOptions = requestOptions.transforms (neues CenterCrop (), neue RoundedCorners (16)); Glide.with (itemView.getContext ()) .load (item.getImage ()) .apply (requestOptions) .into (mProgramThumbnail);
B. Shruti
3

Wenn sich Ihr Bild im Internet befindet, verwenden Sie am besten glide und RoundedBitmapDrawableFactory(ab API 21 - aber in der Support-Bibliothek verfügbar) wie folgt :

 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);
    }
});
Amir Ziarati
quelle
Dies ist eine elegante API, jedoch scheint .centerInside zu fehlen, daher ist es vielleicht besser, XML zu verwenden, um solche Parameter zu definieren
Carl
Dies ist auch nützlich, wenn sich das Bild in Ressourcen befindet und Sie es verwenden müssencenterCrop
Artyom
3

Sie können nur ImageViewin Ihrem Layout verwenden und glidemit dieser Methode können Sie runde Ecken anwenden.

schreibe zuerst in dein gradle,

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

für Bild mit abgerundeten Ecken,

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

Aufrufmethode:

loadImageWithCorners("your url","your imageview");
Deep Patel
quelle
Dadurch wird eine Bibliothek zum Laden von Bildern über eine HTTP-Anforderung hinzugefügt, die für die Frage nicht relevant ist.
CreativeCreatorormaybenot
Welche Bibliothek wird geladen? Zum Laden von Bildern können Sie Glide und das Snippet verwenden, das ausschließlich auf Methoden und Klassen von Glide selbst basiert. Es muss keine weitere Bibliothek hinzugefügt werden
Deep Patel
Glide ist eine Bibliothek, die hauptsächlich zum Laden von Bildern über HTTP dient, aber OP wollte wissen, wie man die Ecken eines Bildes abrundet ImageView.
CreativeCreatorormaybenot
2

Antwort auf die hier umgeleitete Frage: "Wie erstelle ich eine kreisförmige ImageView in 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;
}
Andrey
quelle
2

Mit Hilfe von glide Bibliothek und RoundedBitmapDrawableFactory Klasse ist es leicht zu erreichen. Möglicherweise müssen Sie ein kreisförmiges Platzhalterbild erstellen.

    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);
            }
        });
Chitrang
quelle
2

Für diejenigen, die Glide und Kotlin verwenden, können Sie dies durch Erweitern erreichen RequestBuilder

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

und verwenden als;

 GlideApp.with(context)
            .load(url)
            .roundCorners(context.resources.getDimension(R.dimen.radius_in_dp).toInt())
            .into(imgView)
dgngulcan
quelle
.roundedCorners kommen nicht müssen wir noch etwas einrichten?
Dr. aNdRO
Haben Sie die Erweiterungsfunktion roundCornerswie oben hinzugefügt ? @ Dr.aNdRO
dgngulcan
Bitte geben Sie das richtige Beispiel an! Diese Antwort ist verwirrend!
Junia Montana