2014-02-28 94 views
100

我想使我的ImageView中的任何图像具有边框的圆形。通过xml循环的ImageView

我搜索,但无法找到任何有用的信息(我尝试过的任何东西都不起作用)。

如何通过xml实现此目标: 使用特定的src创建ImageView并使其具有边框的圆形?

+0

如何在java代码中更改ImageView的src? – chenzhongpu

+0

好简单的解决方案在这里http://stackoverflow.com/a/28096369/2162226 - 全部用Java,所以你可以在运行时动态地将这种格式应用于图像 – gnB

回答

141

你可以用白色边框和透明的形状做一个简单的圆形。

// res/drawable/circle.xml 

<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:innerRadius="0dp" 
    android:shape="ring" 
    android:thicknessRatio="1.9" 
    android:useLevel="false" > 
    <solid android:color="@android:color/transparent" /> 

    <stroke 
     android:width="10dp" 
     android:color="@android:color/white" /> 
</shape> 

然后创建一个可绘制的图层列表,并将其作为背景添加到您的图像视图中。

// res/drawable/img.xml 

<?xml version="1.0" encoding="utf-8"?> 
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" > 

    <item android:drawable="@drawable/ic_launcher"/> 
    <item android:drawable="@drawable/circle"/> 

</layer-list> 

并把它作为背景到你的imageview。

<ImageView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:background="@drawable/img"/> 

你会有这样的事情。

enter image description here

+5

然后我将该形状设置为我的imageview背景?我试过了,但没有奏效。我的图像仍然是长方形的:( – user3050910

+0

你有一个矩形图像,你想围绕它像一个圆形? –

+1

是的,使用XML,因为使用java代码是非常昂贵的移动。图像,而不是图像本身是一个圆圈,我认为是为了边框,我想让图像在这个圆圈内圆角倒圆 – user3050910

4

我使用形状= “椭圆形”,而不是下面的 “环”。它为我工作。为了保持图像的范围,我使用<padding>并在我的<ImageView>中将<adjustViewBounds>设置为true。我已经尝试过尺寸在50 x 50 px到200x200 px之间的图像。

+5

更改你能举一个你如何做的例子吗? –

21

如果您使用src属性,上述方法似乎不起作用。我所做的是把两个影像观点的帧结构里面一个在另一个上是这样的:

<FrameLayout android:id="@+id/frame" 
      android:layout_width="40dp" 
      android:layout_height="40dp"> 

    <ImageView android:id="@+id/pic" 
       android:layout_width="40dp" 
       android:layout_height="40dp" 
       android:src="@drawable/my_picture" /> 

    <ImageView android:id="@+id/circle_crop" 
       android:layout_width="40dp" 
       android:layout_height="40dp" 
       android:src="@drawable/circle_crop" /> 

</FrameLayout> 

简单地讲了circular_crop.png在绘制文件夹位于图像尺寸的形状(方形我案例),中间有一个白色的背景和一个透明的圆圈。如果你想要一个正方形的图像视图,你可以使用这个图像。

Round image

只需下载上面的图片。

+2

最佳解决方案!最棒的表演。改变位图是内存问题 – itzhar

+3

这只适用于白色背景? – Kishore

+0

这个样本图像是白色的,所以是的。但是你可以用任何颜色创建你自己的图像,或者下载这个图像并改变它的颜色。 –

2

这将这样的伎俩:

rectangle.xml

<?xml version="1.0" encoding="UTF-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shape="rectangle"> 
    <solid android:color="@android:color/transparent" /> 
    <padding android:bottom="-14dp" android:left="-14dp" android:right="-14dp" android:top="-14dp" /> 

</shape> 

circle.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:innerRadius="0dp" 
    android:shape="oval" 

    android:useLevel="false" > 
    <solid android:color="@android:color/transparent" /> 

    <stroke 
     android:width="15dp" 
     android:color="@color/verification_contact_background" /> 

</shape> 

profile_image.xml(该layerlist)

<?xml version="1.0" encoding="utf-8"?> 
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" > 

    <item android:drawable="@drawable/rectangle" /> 
    <item android:drawable="@drawable/circle"/> 

</layer-list> 

您的布局

<ImageView 
     android:id="@+id/profile_image" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:background="@drawable/default_org" 
     android:src="@drawable/profile_image"/> 
+0

什么是default_org? –

+0

这可以是任何占位符图像 – Nidhi

+0

在这种情况下,矩形尺寸图像的边缘将跨过圆的边界。我如何精确定位每个图像,每个维度和形式,在圆内? –

134

这是

我设计的最简单的方法

。尝试这个。

dependencies: compile 'com.android.support:appcompat-v7:23.1.1' 
       compile 'com.android.support:design:23.1.1' 
       compile 'com.android.support:cardview-v7:23.1.1' 

<android.support.v7.widget.CardView 
    android:layout_width="80dp" 
    android:layout_height="80dp" 
    android:elevation="12dp" 
    android:id="@+id/view2" 
    app:cardCornerRadius="40dp" 
    android:layout_centerHorizontal="true" 
    android:innerRadius="0dp" 
    android:shape="ring" 
    android:thicknessRatio="1.9"> 
    <ImageView 
     android:layout_height="80dp" 
     android:layout_width="match_parent" 
     android:id="@+id/imageView1" 
     android:src="@drawable/YOUR_IMAGE" 
     android:layout_alignParentTop="true" 
     android:layout_centerHorizontal="true"> 
    </ImageView> 
</android.support.v7.widget.CardView> 
+3

这里不错的创意。 –

+1

谢谢你。内存使用简单,容易。到目前为止,我尝试过的库在使用RecyclerView项目中的自定义视图时都会给出OOMException。 – COBB

+1

最好的解决方案,只有在设计期间不要预览它。 –

51

我希望这可能对您有所帮助。

enter image description here

<de.hdodenhof.circleimageview.CircleImageView 
     xmlns:app="http://schemas.android.com/apk/res-auto" 
     android:id="@+id/profile_image" 
     android:layout_width="120dp" 
     android:layout_height="120dp" 
     android:layout_centerHorizontal="true" 
     android:layout_centerVertical="true" 
     android:src="@drawable/your_picture" 
     app:border_color="@color/white" 
     app:border_width="3dp" /> 

注意:在你的项目中,打开your_app>摇篮脚本>的build.gradle(模块:应用程序),并添加下面的执行语句的依赖关系{}

 compile 'de.hdodenhof:circleimageview:2.2.0' 

如需查看完整描述,请查看:The Source here.

+6

我不知道为什么人们讨厌第三方 –

+1

如何将灰色部分更改为白色? –

+2

自发布以来发生了更新。 border_colour和border_width已被重命名。检查github页面的更多信息:https://github.com/hdodenhof/CircleImageView – rharvey

4

glide库和RoundedBitmapDrawableFactory类很容易实现。您可能需要创建循环的占位符图像。

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.setCircular(true); 
       imgProfilePicture.setImageDrawable(drawable); 
      } 
     }); 
+0

不知道你正在使用的这个例子是什么版本的下滑,但与V4.0.0,你可以简单地使用他们的RequestOptions代替RoundedBitmapDrawable的: '滑翔(context).load(imgUrl).apply(new RequestOptions()。centerCrop()) .into(imageView)' –

+0

新的RequestOptions()。circleCrop()).into(imageView)? – Androidz

11

下面是做到这一点,使用下面的代码最简单的方法之一:

依赖

dependencies { 
    ... 
    compile 'de.hdodenhof:circleimageview:2.1.0'  // use this or use the latest compile version. In case u get bug. 
} 

XML代码

<de.hdodenhof.circleimageview.CircleImageView 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:id="@+id/profile_image" 
    android:layout_width="96dp"    // here u can adjust the width 
    android:layout_height="96dp"   // here u can adjust the height 
    android:src="@drawable/profile"   // here u can change the image 
    app:civ_border_width="2dp"    // here u can adjust the border of the circle. 
    app:civ_border_color="#FF000000"/>  // here u can adjust the border color 

截图:

Screenshot

来源:Circular ImageView GitHub Repository

enter image description here

+1

不支持缩放类型。:( – Khan

0

使用下面的代码,你可以修改它:

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.Bitmap.Config; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.PorterDuff.Mode; 
import android.graphics.PorterDuffXfermode; 
import android.graphics.Rect; 
import android.graphics.drawable.BitmapDrawable; 
import android.graphics.drawable.Drawable; 
import android.util.AttributeSet; 
import android.widget.ImageView; 

public class RoundedImageView extends ImageView { 

    public RoundedImageView(Context context) { 
     super(context); 
    } 

    public RoundedImageView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public RoundedImageView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 

     Drawable drawable = getDrawable(); 

     if (drawable == null) { 
      return; 
     } 

     if (getWidth() == 0 || getHeight() == 0) { 
      return; 
     } 
     Bitmap b = ((BitmapDrawable) drawable).getBitmap(); 
     Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true); 

     int w = getWidth(); 
     @SuppressWarnings("unused") 
     int h = getHeight(); 

     Bitmap roundBitmap = getCroppedBitmap(bitmap, w); 
     canvas.drawBitmap(roundBitmap, 0, 0, null); 

    } 

    public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) { 
     Bitmap sbmp; 

     if (bmp.getWidth() != radius || bmp.getHeight() != radius) { 
      float smallest = Math.min(bmp.getWidth(), bmp.getHeight()); 
      float factor = smallest/radius; 
      sbmp = Bitmap.createScaledBitmap(bmp, 
        (int) (bmp.getWidth()/factor), 
        (int) (bmp.getHeight()/factor), false); 
     } else { 
      sbmp = bmp; 
     } 

     Bitmap output = Bitmap.createBitmap(radius, radius, Config.ARGB_8888); 
     Canvas canvas = new Canvas(output); 

     final String color = "#BAB399"; 
     final Paint paint = new Paint(); 
     final Rect rect = new Rect(0, 0, radius, radius); 

     paint.setAntiAlias(true); 
     paint.setFilterBitmap(true); 
     paint.setDither(true); 
     canvas.drawARGB(0, 0, 0, 0); 
     paint.setColor(Color.parseColor(color)); 
     canvas.drawCircle(radius/2 + 0.7f, radius/2 + 0.7f, 
       radius/2 + 0.1f, paint); 
     paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); 
     canvas.drawBitmap(sbmp, rect, rect, paint); 

     return output; 
    } 

} 
0

试试这个。

public class RoundedImageView extends android.support.v7.widget.AppCompatImageView { 

    private int borderWidth = 4; 
    private int viewWidth; 
    private int viewHeight; 
    private Bitmap image; 
    private Paint paint; 
    private Paint paintBorder; 
    private BitmapShader shader; 

    public RoundedImageView(Context context) 
    { 
     super(context); 
     setup(); 
    } 

    public RoundedImageView(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 
     setup(); 
    } 

    public RoundedImageView(Context context, AttributeSet attrs, int defStyle) 
    { 
     super(context, attrs, defStyle); 
     setup(); 
    } 

    private void setup() 
    { 
     paint = new Paint(); 
     paint.setAntiAlias(true); 

     paintBorder = new Paint(); 
     setBorderColor(Color.WHITE); 
     paintBorder.setAntiAlias(true); 
     this.setLayerType(LAYER_TYPE_SOFTWARE, paintBorder); 

     paintBorder.setShadowLayer(4.0f, 0.0f, 2.0f, Color.WHITE); 
    } 

    public void setBorderWidth(int borderWidth) 
    { 
     this.borderWidth = borderWidth; 
     this.invalidate(); 
    } 

    public void setBorderColor(int borderColor) 
    { 
     if (paintBorder != null) 
      paintBorder.setColor(borderColor); 

     this.invalidate(); 
    } 

    private void loadBitmap() 
    { 
     BitmapDrawable bitmapDrawable = (BitmapDrawable) this.getDrawable(); 

     if (bitmapDrawable != null) 
      image = bitmapDrawable.getBitmap(); 
    } 

    @SuppressLint("DrawAllocation") 
    @Override 
    public void onDraw(Canvas canvas) 
    { 
     loadBitmap(); 

     if (image != null) 
     { 
      shader = new BitmapShader(Bitmap.createScaledBitmap(image, canvas.getWidth(), canvas.getHeight(), false), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); 
      paint.setShader(shader); 
      int circleCenter = viewWidth/2; 
      canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, circleCenter + borderWidth - 4.0f, paintBorder); 
      canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, circleCenter - 4.0f, paint); 
     } 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
    { 
     int width = measureWidth(widthMeasureSpec); 
     int height = measureHeight(heightMeasureSpec, widthMeasureSpec); 

     viewWidth = width - (borderWidth * 2); 
     viewHeight = height - (borderWidth * 2); 

     setMeasuredDimension(width, height); 
    } 

    private int measureWidth(int measureSpec) 
    { 
     int result = 0; 
     int specMode = MeasureSpec.getMode(measureSpec); 
     int specSize = MeasureSpec.getSize(measureSpec); 

     if (specMode == MeasureSpec.EXACTLY) 
     { 
      result = specSize; 
     } 
     else 
     { 
      // Measure the text 
      result = viewWidth; 
     } 

     return result; 
    } 

    private int measureHeight(int measureSpecHeight, int measureSpecWidth) 
    { 
     int result = 0; 
     int specMode = MeasureSpec.getMode(measureSpecHeight); 
     int specSize = MeasureSpec.getSize(measureSpecHeight); 

     if (specMode == MeasureSpec.EXACTLY) 
     { 
      result = specSize; 
     } 
     else 
     { 
      result = viewHeight; 
     } 

     return (result + 2); 
    } 
} 

,并在这样的布局使用的ImageView:

<com.app.Demo.RoundedImageView 
    android:id="@+id/iv_profileImage" 
    android:layout_width="70dp" 
    android:layout_height="70dp" 
    android:layout_centerHorizontal="true" 
    /> 
0

如奥尔罕Obut的答案,但与变化被描述:

<ImageView 
    android:layout_width="0dp" 
    android:layout_height="match_parent" 
    android:src="@drawable/img" 
    android:layout_weight="75" /> 

避免图像的延伸。 而img.xml:

<?xml version="1.0" encoding="utf-8"?><layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
<item android:drawable="@drawable/profile" /> 
<item android:drawable="@drawable/circle" /></layer-list> 

(没有改变),和circle.xml:

<shape xmlns:android="http://schemas.android.com/apk/res/android" 
android:innerRadiusRatio="2" 
android:shape="ring" 
android:thickness="300dp" 
android:useLevel="false"> 
<solid android:color="@android:color/white"/> 
<stroke 
    android:width="2dp" 
    android:color="@android:color/black"/> 
</shape> 

这里的环的最大得到的厚度 - 1000dp
和radiusRatio是图像宽度的一半(最大的戒指宽度,是吗?) - 2
如果需要,笔画是需要的边框。
我用方形PNG图像(profile.png),顺便说一句。具有相同的宽度和高度。 这对任意ImageView尺寸都是正确的。 enter image description here