Bagaimana cara membuat ImageView dengan sudut bulat?

573

Di Android, ImageView adalah persegi panjang secara default. Bagaimana saya bisa membuatnya menjadi persegi panjang bulat (memotong semua 4 sudut Bitmap saya menjadi persegi panjang bulat) di ImageView?

michael
sumber
Ini mungkin membantu stackoverflow.com/questions/26850780/…
Mangesh
Tersembunyi di bawah yang lebih tua, jawaban yang lebih rumit adalah apa yang saya pikir seharusnya menjadi jawaban yang diterima sekarang: RoundedBitmapDrawable , ditambahkan di v4 Dukungan Library revisi 21.
Jonik
Anda dapat melakukannya dengan cara termudah hanya menggunakan CardView dengan bagian dalam ImageView - lihat contoh di sini stackoverflow.com/a/41479670/4516797
Taras Vovkovych
Ini perpustakaan sangat berguna.
Grrigore
Periksa ini sekarang kita harus ShapeableImageViewmembuat imageView stackoverflow.com/a/61086632/7666442
Nilesh Rathod

Jawaban:

545

Ini agak terlambat dalam respons, tetapi untuk orang lain yang mencari ini, Anda dapat melakukan kode berikut untuk secara manual mengitari sudut-sudut gambar Anda.

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

Ini bukan kode saya, tapi saya sudah menggunakannya dan ini bekerja dengan sangat baik. Saya menggunakannya sebagai penolong dalam kelas ImageHelper dan memperpanjangnya hanya sedikit untuk memberikan jumlah bulu yang saya butuhkan untuk gambar yang diberikan.

Kode akhir terlihat seperti ini:

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

Semoga ini bisa membantu seseorang!

George Walters II
sumber
4
Ini tidak berfungsi untuk semua perangkat. Apakah saya perlu mengubahnya di mana saja?
Spring Breaker
7
Butuh hampir 0,03 detik untuk melakukan itu untuk gambar 200 * 200, jadi saya pikir itu bukan solusi terbaik.
Jacky
2
Ini hanya putaran sudut kiri atas dan kanan atas. Mengapa
Prateek
1
@ solusi vinc3m1 di sini github.com/makeramen/RoundedImageView bekerja dengan sangat baik! juga lihat jawabannya ( stackoverflow.com/a/15032283/2048266 )
nommer
16
Tidak berfungsi dengan baik ketika mencoba mengatur skalet imageview, hanya fitXY yang berfungsi, centerCrop dan lainnya menunjukkan hasil yang tidak dapat diprediksi, ada orang di sini yang memiliki masalah yang sama?
Shivansh
211

Sementara jawaban di atas berfungsi, Romain Guy (pengembang Android inti) menunjukkan metode yang lebih baik di blognya yang menggunakan lebih sedikit memori dengan menggunakan shader yang tidak membuat salinan bitmap. Inti umum dari fungsionalitas ada di sini:

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

Keuntungan dari ini dibandingkan metode lain adalah:

  • tidak membuat salinan bitmap terpisah, yang menggunakan banyak memori dengan gambar besar [vs sebagian besar jawaban lain di sini]
  • mendukung antialisasing [vs metode clipPath]
  • mendukung alpha [vs xfermode + metode porterduff]
  • mendukung akselerasi perangkat keras [vs metode clipPath]
  • hanya menarik sekali ke kanvas [vs metode xfermode dan clippath]

Saya telah membuat RoundedImageView berdasarkan kode ini yang membungkus logika ini menjadi ImageView dan menambahkan ScaleTypedukungan yang tepat dan batas bulat opsional.

vinc3m1
sumber
di Anda / example / res / layout / rounded_item.xml mengapa Anda menentukan gambar src ketika semua sumber Anda hardcoded? Demo yang bagus, hanya cara yang berlebihan.
Seseorang di suatu tempat
sampel Anda memiliki masalah kehabisan memori yang serius, sama seperti sampel asli Romain Guy. Saya masih tidak tahu apa penyebabnya, tetapi seperti kodenya, ini adalah hal yang sangat sulit ditemukan. Jika Anda tidak dapat melihat kerusakan dari aplikasi karena OOM, Anda dapat memutar aplikasi beberapa kali hingga terjadi (tergantung pada perangkat, ROM, dll ...). Saya telah melaporkannya di masa lalu di sini: stackoverflow.com/questions/14109187/…
pengembang android
1
Tidak ada orang lain yang melaporkan masalah kehabisan memori, jadi itu pasti sesuatu yang Anda lakukan di luar kode yang salah. Contoh ini dengan benar memegang set bitmap terbatas dalam adaptor tanpa membuatnya kembali setiap kali dilihat. Contoh yang ditampilkan di sini adalah potongan dari metode draw () di Drawable, yang menggunakan referensi ke bitmap asli yang dipegangnya dan berfungsi dengan benar. Ini tidak dimaksudkan untuk mengubah bitmap asli, tetapi hanya membuatnya dengan sudut bulat. Tanaman tengah bekerja dengan baik dalam contoh juga.
vinc3m1
1
Jika Anda dapat memberikan tangkapan layar atau perangkat yang tidak berfungsi, atau bahkan menawarkan permintaan memperbaiki dan menarik, itu akan menjadi sangat produktif. Saya telah menguji rotasi berulang kali pada perangkat saya dan memori tetap sama.
vinc3m1
11
Perhatikan bahwa itu tidak akan berfungsi jika ukuran gambar di atas 2048 piksel. Shader tidak mendukung tekstur yang lebih besar dari itu.
Gábor
209

Cara mudah lainnya adalah dengan menggunakan CardView dengan radius sudut dan ImageView di dalam:

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

masukkan deskripsi gambar di sini

Taras Vovkovych
sumber
5
Sepertinya solusi yang baik. Tapi itu tidak klip gambar di pra-Lollipop.
Nikolai
1
Bagaimana jika, kita hanya ingin jari-jari di sudut kiri atas dan kanan atas dan tidak semua sudut?
Pratik Singhal
3
Cara yang sangat sederhana dan cerdas untuk menerapkan batas kurva dalam tampilan apa pun.
AMI CHARADAVA
1
Solusi yang bagus tetapi peningkatan hanya didukung di api level 21 ke atas
Saad Bilal
1
Untuk menonaktifkan elevasi kartu, gunakan aplikasi: cardElevation = "0dp" (bukan android: elevasi)
Johnny Five
150

Kliping ke bentuk bulat ditambahkan ke Viewkelas di API 21.

Lakukan ini:

  • Buat bentuk bulat yang dapat digambar, kira-kira seperti ini:

res / drawable / round_outline.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="10dp" />
    ...
</shape>
  • Setel drawable sebagai latar belakang ImageView Anda: android:background="@drawable/round_outline"
  • Menurut dokumentasi ini , maka yang perlu Anda lakukan hanyalah menambahkanandroid:clipToOutline="true"

Sayangnya, ada bug dan atribut XML itu tidak dikenali. Untungnya, kita masih dapat mengatur kliping di Jawa:

  • Dalam aktivitas atau fragmen Anda: ImageView.setClipToOutline(true)

Ini akan terlihat seperti apa:

masukkan deskripsi gambar di sini

catatan:

Metode ini berfungsi untuk semua bentuk yang dapat digambar (tidak hanya membulat). Ini akan klip ImageView ke bentuk bentuk apa pun yang Anda tetapkan dalam Drawable xml Anda.

Catatan khusus tentang ImageViews

setClipToOutline()hanya berfungsi ketika latar belakang Tampilan diatur ke bentuk yang dapat digambar. Jika bentuk latar belakang ini ada, Lihat memperlakukan garis bentuk sebagai batas untuk kliping dan tujuan membayangi.

Ini berarti, jika Anda ingin menggunakan setClipToOutline()untuk membulatkan sudut pada ImageView, gambar Anda harus ditetapkan menggunakan android:srcbukan android:background(karena latar belakang harus diatur ke bentuk bulat Anda). Jika Anda HARUS menggunakan latar belakang untuk mengatur gambar Anda alih-alih src, Anda dapat menggunakan solusi ini:

  • Buat tata letak dan atur latar belakangnya agar bentuk Anda dapat digambar
  • Bungkus tata letak itu di sekitar ImageView Anda (tanpa bantalan)
  • ImageView (termasuk yang lainnya di tata letak) sekarang akan ditampilkan dengan bentuk tata letak bulat.
paling lapar
sumber
10
Kesalahan: (x) Tidak ditemukan pengenal sumber daya untuk atribut 'clipToOutline' dalam paket 'android'
Anu Martin
7
Sebagai gantinya android:clipToOutline, seseorang harus menggunakan android:outlineProvider="background".
WindRider
2
Alasan lain saya "sangat mencintai" Google adalah bahwa bug ini hampir seusia saya dan masih berada di dunia kecilnya. Google tampaknya tidak memberikan cr * ap tentang hal itu))
Farid
1
Saya tampaknya tidak berhasil dengan metode ini ketika saya hanya mengatur sudut topleft dan topRight dalam bentuk latar belakang untuk dibulatkan.
Peterdk
@AnuMartin ini adalah masalah yang diketahui - issuetracker.google.com/issues/37036728
Vadim Kotov
132

Di v21 dari pustaka dukungan sekarang ada solusi untuk ini: itu disebut RoundedBitmapDrawable .

Ini pada dasarnya sama seperti Drawable normal kecuali Anda memberinya radius sudut untuk kliping dengan:

setCornerRadius(float cornerRadius)

Jadi, dimulai dengan Bitmap srcdan target ImageView, akan terlihat seperti ini:

RoundedBitmapDrawable dr = RoundedBitmapDrawableFactory.create(res, src);
dr.setCornerRadius(cornerRadius);
imageView.setImageDrawable(dr);
tyczj
sumber
3
Terima kasih banyak, inilah langkah selanjutnya: stackoverflow.com/questions/24878740/…
David d C e Freitas
sebenarnya ada android.support.v4.graphics.drawable.RoundedBitmapDrawableFactorybegitu v4juga mendukung hal itu.
deadfish
2
@deadfish ya di v4perpustakaan dukungan tetapi tidak sampai REVISION 21perpustakaan pendukung
tyczj
3
Ini adalah solusi yang sederhana dan terkini. Ini membutuhkan jumlah kode paling sedikit dan memiliki ekstensibilitas yang besar. Dapat bekerja dengan gambar dari file lokal, cache yang dapat ditarik, atau bahkan dengan NetworkImageView Volley. Saya sangat setuju bahwa ini harus menjadi jawaban yang diterima saat ini, seperti yang ditunjukkan @Jonik.
katie
2
Sayangnya tidak bekerja dengan scaleType centerCrop(perpustakaan dukungan v25.3.1)
rocknow
67

Saya telah melakukannya oleh 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);
    }
}

Cara Penggunaan:

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

Keluaran:

masukkan deskripsi gambar di sini

Semoga ini bisa membantu Anda.

Hiren Patel
sumber
ini membuat gambar kabur
Amit Hooda
2
bekerja bahkan dengan android: scaleType = "centerCrop", sederhana, tidak membuat bitmap baru. Terima kasih!
ernazm
1
@ Husen Solusi ini berfungsi baik untuk ImageView dengan gambar latar belakang. Tapi itu tidak berfungsi untuk ImageViews yang hanya memiliki warna latar belakang dan tidak ada gambar. Bisakah Anda memberi tahu saya mengapa ini terjadi?
user2991413
Canvas.clipPath()java.lang.UnsupportedOperationExceptiondalam beberapa kasus dapat menyebabkan . Lihat stackoverflow.com/questions/13248904/…
Artyom
1
Solusi ini hanya berfungsi untuk set gambar android:background, tetapi tidak android:src.
CoolMind
65

Solusi xml cepat -

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

Anda dapat mengatur lebar, tinggi, dan radius yang Anda inginkan pada CardView dan scaleType di ImageView.

Dengan AndroidX, gunakan <androidx.cardview.widget.CardView>

Chirag Mittal
sumber
4
pendekatan ini berhasil dalam kasus saya dengan androidx.cardview.widget.CardView
Ivan
7
Tidak yakin mengapa ini tidak memiliki lebih banyak upvotes? Menurut pendapat saya solusi terbaik tanpa perpustakaan dan banyak kode menyebalkan (meskipun saya menggunakan skala centerCrop dalam kasus saya).
ThemBones
1
Belum banyak upvotes, karena itu jawaban baru. Tapi saya menaruh +1 saya untuk segera menaikkannya! Terima kasih!
Micer
Namun, ini berfungsi tetapi di sini gambar akan meregang karena scaleType="fitXY"dan tidak terlihat tepat @ThemBones
WIZARD
@ WIZARD itu sebabnya saya sebutkan bahwa Anda dapat mengatur scaleType yang Anda inginkan di ImageView
Chirag Mittal
57

Saya menemukan bahwa kedua metode sangat membantu dalam menghasilkan solusi yang berfungsi. Ini adalah versi komposit saya, yaitu pixel-independent dan memungkinkan Anda untuk memiliki beberapa sudut persegi dengan sisa sudut lainnya memiliki jari-jari yang sama (yang merupakan kasus penggunaan biasa). Dengan terima kasih kepada kedua solusi di atas:

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

Juga, saya mengesampingkan ImageView untuk memasukkan ini sehingga saya bisa mendefinisikannya dalam xml. Anda mungkin ingin menambahkan beberapa logika yang dibuat oleh panggilan super di sini, tapi saya sudah berkomentar karena itu tidak membantu dalam kasus saya.

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

Semoga ini membantu!

Caspar Harmer
sumber
4
cukup mengagumkan, terutama memperluas ImageView
Seseorang Di Suatu Tempat
2
Cara sederhana untuk menjaga logika ImageView # onDraw () adalah dengan mengatur bitmap sudut bundar ke drawable dari ImageView, dan meninggalkan super.onDraw () untuk menggambar bitmap. Saya telah membuat kelas RoundedCornerImageView , dan contoh penggunaannya ada di sini . Harap perhatikan bahwa getRoundedCornerBitmap () yang saya gunakan bukan piksel independen.
umbalaconmeogia
Terima kasih atas RoundedCornerImageView. Saya menggunakannya tetapi memodifikasinya menjadi pixel-density independent.
PacificSky
Kode sumber ke RoundedCornerImageView umba ada di sini: code.google.com/p/android-batsg/source/browse/trunk/…
Seseorang di Suatu Tempat
@Caspar Harmer bekerja dengan baik hanya 1 sunting ... ada empat kondisi .. hanya mengubahnya seolah-olah saya menetapkan benar, benar, salah, salah itu akan menetapkan sudut bawah bukan sudut atas .. kode lain berfungsi dengan baik. Jadi squareTL dan squareTR adalah kondisi masing-masing untuk squareBL dan squareBR..dan vica-versa.
TheFlash
48

Gambar bulat Menggunakan ImageLoader di sini

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

Atau Anda dapat menggunakan PicassoLibrary dari Square.

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

Anda dapat mengunduh file RoundedTransformation di sini di sini

Shailesh
sumber
1
Tidak menampilkan gambar
Amit Thaper
3
Pustaka Picasso bagus, dan sangat mudah diimplementasikan, terima kasih banyak +1
Hitesh
3
Pustaka Picasso tampaknya tidak mengubah gambar "placeholder" dan "error", jadi jika gambar Anda gagal dimuat (kesalahan) atau butuh waktu untuk memuat pada awalnya (placeholder) itu tidak akan menampilkan gambar sebagai gambar bulat. github.com/square/picasso/issues/337
Pelpotronic
Transformasi picasso berguna lainnya disediakan oleh perpustakaan ini, yang juga berisi RoundedCornersTransformation: github.com/wasabeef/picasso-transformations
Massimo
Tidak bekerja dengan memotong gambar di Univ. Pemuat Gambar.
Yar
26

Karena semua jawaban tampak terlalu rumit bagi saya hanya untuk sudut-sudut, saya pikir dan datang ke solusi lain yang saya pikir layak untuk dibagikan, hanya dengan XML jika Anda memiliki ruang di sekitar gambar:

Buat bentuk berbatasan dengan konten transparan seperti ini:

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

Kemudian dalam RelativeLayout Anda pertama-tama dapat menempatkan gambar Anda dan kemudian di lokasi yang sama di atas bentuk dengan ImageView lain. Bentuk penutup harus lebih besar ukurannya dengan jumlah lebar perbatasan. Berhati-hatilah untuk mengambil jari-jari sudut yang lebih besar karena jari-jari luar didefinisikan tetapi jari-jari dalam adalah yang menutupi gambar Anda.

Semoga ini bisa membantu seseorang juga.

Edit sesuai permintaan CQM contoh tata letak relatif:

<?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>
Kristen
sumber
dapatkah Anda menjelaskan lebih lanjut tentang ini dengan lebih banyak kode, terutama apa yang sedang dilakukan dengan tampilan gambar kedua dan di mana "bentuk berbatasan" xml sedang diterapkan (sebagai src atau sebagai latar belakang?) beberapa pertanyaan di sini. Saya ingin menyukai solusi ini karena ini akan memungkinkan saya mengontrol keempat sudut secara mandiri
CQM
1
Meskipun tampaknya menjadi jawaban yang sederhana, sayangnya menambahkan margin di sekitar tampilan gambar "bertopeng" yang merupakan efek samping yang tidak diinginkan.
Abdalrahman Shatou
ya, tetapi yang sama berfungsi dengan ImageView berdasarkan pada PNG-Drawable dengan sudut bulat dan latar belakang transparan atau 9-Patch-Drawable jika Anda memiliki aspek yang tidak ditentukan.
Christian
Saya melakukan hal yang sama, dan ini bekerja; hanya ingin tahu apakah itu tidak akan menimbulkan masalah dengan orientasi dan ukuran ponsel yang berbeda?
buka dan gratis
Jika Anda menjaga dimensi relatif satu sama lain, ini seharusnya tidak membuat masalah.
Christian
22

Dimulai dengan versi 1.2.0-alpha03dari para Bahan Komponen Perpustakaan ada yang baru ShapeableImageView.

Anda dapat menggunakan sesuatu seperti:

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

dengan:

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

Atau secara terprogram:

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

masukkan deskripsi gambar di sini

Gabriele Mariotti
sumber
Jika gambar memiliki warna latar belakang, saat ini menghasilkan warna latar belakang untuk muncul di bawah sudut yang membulat. Ini juga mengabaikan properti scaleType pada gambar.
inokey
14

Implementasi saya dari ImageView dengan widget sudut bulat, yang (turun ||) ukuran gambar untuk dimensi yang diperlukan. Ini menggunakan bentuk kode 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
sumber
12
Dari mana ImageUtilities berasal?
JasonWyatt
1
@JasonWyatt lihat posting sorrodos di bawah ini
Damjan
12

Sampai saat ini, ada cara lain - menggunakan API Generated Glide . Butuh beberapa pekerjaan awal tetapi kemudian memberi Anda semua kekuatan Glide dengan fleksibilitas untuk melakukan apa pun karena Anda menggeliat kode yang sebenarnya jadi saya pikir itu adalah solusi yang baik untuk jangka panjang. Plus, penggunaannya sangat sederhana dan rapi.

Pertama, siapkan Glide versi 4+:

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

Kemudian buat kelas modul aplikasi Glid untuk memicu pemrosesan anotasi:

@GlideModule
public final class MyAppGlideModule extends AppGlideModule {}

Kemudian buat ekstensi Glide yang sebenarnya berfungsi. Anda dapat menyesuaikannya untuk melakukan apa pun yang Anda inginkan:

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

Setelah menambahkan file-file ini, bangun proyek Anda.

Kemudian gunakan dalam kode Anda seperti ini:

GlideApp.with(this)
        .load(imageUrl)
        .roundedCorners(getApplicationContext(), 5)
        .into(imageView);
Tuan Codesalot
sumber
Jangan lupa menambahkan spasi di antara RequestOptionsdan optionsdalam params
StevenTB
Selesai Terima kasih atas masukannya.
Sir Codesalot
.roundedCorners tidak datang, apakah kita perlu mengatur yang lain? Bahkan setelah proyek pembangunan kembali
Dr. aNdRO
Ini berhasil untuk saya, terima kasih. Saya merasa lebih mudah untuk menghindari menggunakan @GlideExtensionkelas beranotasi dan hanya pergi dengan .transform(new RoundedCorners(px))mana pxyang sama ( int px = Math.round(cornerRadius * (context.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));).
Michael Osofsky
10

Ada perpustakaan keren yang memungkinkan Anda untuk membentuk tampilan gambar.

Berikut ini sebuah contoh:

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

Definisi bentuk:

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

Hasil:

hasil

Grrigore
sumber
1
Ini hebat, dan melakukan lebih banyak lagi, seperti Anda dapat menambahkan perbatasan dan menggunakan bentuk apa pun
Adam Kis
8

Berikut ini adalah contoh sederhana meng-override imageView, Anda kemudian dapat menggunakannya di desainer tata letak untuk melihat pratinjau.

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

Ini untuk solusi cepat. Radius digunakan di semua sudut dan didasarkan pada persentase lebar bitmap.

Saya baru saja mengganti setImageDrawabledan menggunakan metode dukungan v4 untuk bitmap bulat yang dapat digambar.

Pemakaian:

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

Pratinjau dengan imageView dan custom imageView:

masukkan deskripsi gambar di sini

ikan mati
sumber
Ini berfungsi dalam semua situasi, terima kasih. Kamu menyelamatkan hariku.
Mehul Solanki
7

Anda harus memperluas ImageViewdan menggambar persegi panjang bulat Anda sendiri.

Jika Anda ingin bingkai di sekitar gambar Anda juga bisa menempatkan bingkai bulat di atas tampilan gambar di tata letak.

[Sunting] Menempatkan bingkai ke atas untuk op gambar asli, dengan menggunakan FrameLayoutmisalnya. Elemen pertama FrameLayoutadalah gambar yang ingin Anda putar bulat. Kemudian tambahkan yang lain ImageViewdengan bingkai. Yang kedua ImageViewakan ditampilkan di atas yang asli ImageViewdan dengan demikian Android akan menggambar isinya di atas orignal ImageView.

MrSnowflake
sumber
Terima kasih. Tetapi hanya ada metode setDrawable untuk ImageView, bagaimana saya bisa mengatur ImageView dari isi gambar saya dan kemudian menempatkan bingkai bulat di atas ImageView?
michael
Maaf, saya tidak jelas. Maksud saya melapiskan dalam tata letak: dengan demikian (yaitu) menggunakan FrameLayoutmenempatkan ImageViewdi dalamnya dan menambahkan yang lain ImageViewdengan bingkai bulat. Dengan begitu yang pertama ImageViewakan menampilkan gambar yang Anda pilih dan yang kedua ImageFrameakan menampilkan bingkai bulat.
MrSnowflake
Benar - dengan FrameLayout Anda dapat melapisi satu gambar / tampilan dengan yang lain. Anda juga dapat menggunakan tag android: foreground dari FrameLayout.
Richard Le Mesurier
7

Romain Guy adalah tempatnya.

Versi yang diperkecil sebagai berikut.

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
sumber
Sayangnya, meskipun berfungsi, tetapi sama seperti solusi lainnya di sini, ia menciptakan bitmap baru alih-alih menggunakan yang sekarang.
pengembang android
tidak juga. bitmapRounded akan digunakan berulang kali. jika Anda memiliki akses ke kanvas yang dapat digambar, Anda dapat menggunakan metode menggambar secara langsung alih-alih menghasilkan bitmap baru.
Alex
bagaimana kamu melakukannya? misalkan saya tidak menggunakan drawable khusus dan hanya menangani bitmap tunggal dan menggunakan setImageBitmap di akhir proses. bagaimana saya mencapai hal seperti itu?
pengembang android
lihat contoh romain guy penasaran-creature.org/2012/12/11/… dan contoh dokumen
Alex
keduanya tidak mengubah bitmap, tetapi membungkusnya menggunakan drawable kustom dan custom imageview. ini bukan yang saya tanyakan. saya bertanya bagaimana Anda mengubah bitmap itu sendiri.
Pengembang Android
7

Solusi xml murni ini cukup baik dalam kasus saya. http://www.techrepublic.com/article/pro-tip-round-corners-on-an-android-imageview-with-this-hack/

EDIT

Singkatnya, inilah jawabannya:

Di folder / res / drawable, buat file frame.xml. Di dalamnya, kita mendefinisikan sebuah persegi panjang sederhana dengan sudut bulat dan pusat transparan .

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

Di file tata letak Anda, Anda menambahkan LinearLayout yang berisi ImageView standar, serta FrameLayout bersarang. FrameLayout menggunakan padding dan custom drawable untuk memberikan ilusi sudut yang membulat.

<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
sumber
ide bagus, saya menggunakannya untuk menunjukkan sudut
Gal Rom
6

Alat peraga untuk George Walters II di atas, saya hanya mengambil jawabannya dan sedikit memperluasnya untuk mendukung pembulatan sudut individu secara berbeda. Ini dapat dioptimalkan sedikit lebih jauh (beberapa rect target tumpang tindih), tetapi tidak banyak.

Saya tahu utas ini agak lama, tetapi ini adalah salah satu hasil teratas untuk kueri di Google untuk cara membulatkan sudut-sudut ImageViews di Android.

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

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

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

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

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

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

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

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

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

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

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

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

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

    return output;
}
sorrodos
sumber
+1 untuk menambahkan pengali kepadatan dan menambahkan dukungan untuk sudut pembulatan individual. Saya benar-benar menggunakan solusi di atas, karena solusi Anda tidak cukup berfungsi - tetapi itu sangat membantu! Lihat solusi komposit saya di bawah ini:
Caspar Harmer
6

Terapkan bentuk ke Anda imageViewseperti di bawah ini:

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

mungkin bermanfaat bagi Anda teman.

jigar
sumber
6

Mengapa tidak melakukan kliping draw()?

Inilah solusi saya:

  • Perpanjang RelativeLayout dengan kliping
  • Masukkan ImageView (atau tampilan lain) ke dalam tata letak:

Kode:

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

}
kolom ikan
sumber
1
Saya suka pendekatan ini. Saya menggunakannya untuk membuat RoundImageView saya sendiri. Terima kasih untuk ini.
Pascal
Ini tidak bekerja dengan akselerasi keras dihidupkan, benar? Saya tidak melihat solusi yang mudah ...
secureboot
Bisakah Anda menunjukkan bagaimana melakukannya, dengan memiliki hasil sebagai drawable, memiliki kemampuan untuk menambahkan garis besar (stroke AKA) di sekitar konten, dan juga memiliki kemampuan untuk membuat hanya beberapa sudut untuk dibulatkan?
pengembang android
5

Berikut ini membuat objek tata letak persegi panjang bulat yang menarik persegi panjang bulat di sekitar objek anak yang ditempatkan di dalamnya. Itu juga menunjukkan cara membuat tampilan dan tata letak secara terprogram tanpa menggunakan tata letak file 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);
 }
}

Kelas untuk objek tata letak RoundedRectangle adalah seperti yang didefinisikan di sini:

/**
 *  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
sumber
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)

Untuk membuat ImageViewCircular, kami dapat mengubah cornerRadiusdengan:

rounded.isCircular = true
Vahid
sumber
4

Terima kasih banyak atas jawaban pertama. Berikut adalah versi yang dimodifikasi untuk mengubah gambar persegi panjang menjadi gambar persegi (dan bulat) dan mengisi warna yang dilewatkan sebagai parameter.

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

Jika Anda menggunakan Glide Library, ini akan sangat membantu:

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
sumber
Jika menggunakan Glide versi 4 dan penggunaan di atas --- RequestOptions requestOptions = new RequestOptions (); requestOptions = requestOptions.transforms (CenterCrop baru (), RoundedCorners baru (16)); Glide.with (itemView.getContext ()) .load (item.getImage ()) .apply (requestOptions) .into (mProgramThumbnail);
B.shruti
3

jika gambar Anda ada di internet, cara terbaik adalah menggunakan glide dan RoundedBitmapDrawableFactory(dari API 21 - tetapi tersedia di perpustakaan dukungan) seperti:

 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
sumber
Ini adalah api yang elegan, bagaimanapun, .centerInside tampaknya hilang, oleh karena itu mungkin lebih baik menggunakan xml untuk mendefinisikan parameter tersebut
carl
Ini juga berguna ketika gambar dalam sumber daya dan Anda perlu menggunakancenterCrop
Artyom
3

Anda hanya dapat menggunakan ImageViewtata letak dan menggunakan glide, Anda dapat menerapkan sudut bulat menggunakan metode ini.

pertama di tulis gradle Anda,

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

untuk gambar dengan sudut bulat,

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

metode panggilan:

loadImageWithCorners("your url","your imageview");
Deep Patel
sumber
Ini akan menambahkan perpustakaan untuk memuat gambar melalui permintaan HTTP, yang tidak relevan dengan pertanyaan.
creativecreatorormaybenot
Perpustakaan mana yang akan dimuat? Untuk memuat gambar, Anda dapat menggunakan glide dan snippet itu murni berdasarkan metode dan kelas glide itu sendiri. Tidak ada perpustakaan lain yang perlu ditambahkan
Deep Patel
Glide adalah pustaka terutama untuk memuat gambar melalui HTTP, tetapi OP ingin tahu cara membulatkan sudut sebuah ImageView.
creativecreatorormaybenot
2

Jawab untuk pertanyaan yang dialihkan ke sini: "Bagaimana cara membuat ImageView melingkar di 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
sumber
2

Dengan bantuan luncur perpustakaan dan kelas RoundedBitmapDrawableFactory mudah untuk dicapai. Anda mungkin perlu membuat gambar placeholder melingkar.

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

Untuk yang menggunakan Glide dan Kotlin, Anda dapat mencapainya dengan memperluas RequestBuilder

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

dan gunakan sebagai;

 GlideApp.with(context)
            .load(url)
            .roundCorners(context.resources.getDimension(R.dimen.radius_in_dp).toInt())
            .into(imgView)
dgngulcan
sumber
.roundedCorners tidak datang, apakah kita perlu mengatur yang lain?
Dr. aNdRO
apakah Anda menambahkan fungsi ekstensi roundCornersseperti di atas? @ Dr.aNdRO
dgngulcan
Berikan contoh yang tepat! Jawaban ini membingungkan!
Junia Montana