Je voudrais faire n'importe quelle image de ma ImageView
être circulaire avec une frontière.
J'ai cherché mais je n'ai trouvé aucune information utile (tout ce que j'ai essayé n'a pas fonctionné).
Comment puis-je atteindre cet objectif via xml: Créer une ImageView
avec certains src et le rendre circulaire avec une bordure?
Vous pouvez créer un cercle simple avec une bordure blanche et un contenu transparent avec une forme.
// 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>
Créez ensuite une liste de couches pouvant être dessinée et placez-la en tant qu'arrière-plan de votre vue image.
// 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>
et le mettre en arrière-plan pour votre imageview.
<ImageView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:background="@drawable/img"/>
Vous aurez quelque chose comme ça.
C'est la manière la plus simple que j'ai conçue. Essaye ça.
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>
Si vous travaillez sur les versions Android ci-dessus Lollipop
<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">
<ImageView
Android:layout_height="80dp"
Android:layout_width="match_parent"
Android:id="@+id/imageView1"
Android:src="@drawable/YOUR_IMAGE"
Android:scaleType="centerCrop"/>
</Android.support.v7.widget.CardView>
J'espère que cela pourrait vous aider.
1) Avec une bibliothèque tierce
<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_centerInParent="true"
Android:src="@drawable/your_picture"
app:civ_border_color="@color/colorAccent"
app:civ_border_width="3dp" />
Remarque: dans votre projet, ouvrez votre_app> Scripts Gradle> build.gradle (Module: app) et ajoutez l'instruction de mise en œuvre suivante aux dépendances {}
implementation 'de.hdodenhof:circleimageview:2.2.0'
Pour une description complète, veuillez vérifier: La source ici.
2) Sans bibliothèque tierce
package com.mypackage.custom;
import Android.content.Context;
import Android.content.res.TypedArray;
import Android.graphics.Bitmap;
import Android.graphics.BitmapShader;
import Android.graphics.Canvas;
import Android.graphics.Color;
import Android.graphics.ColorFilter;
import Android.graphics.Matrix;
import Android.graphics.Paint;
import Android.graphics.Shader;
import Android.graphics.drawable.BitmapDrawable;
import Android.graphics.drawable.Drawable;
import Android.support.v7.widget.AppCompatImageView;
import Android.util.AttributeSet;
import com.mypackage.R;
import static Android.widget.ImageView.ScaleType.CENTER_CROP;
import static Android.widget.ImageView.ScaleType.CENTER_INSIDE;
public class CircularImageView extends AppCompatImageView {
// Default Values
private static final float DEFAULT_BORDER_WIDTH = 4;
private static final float DEFAULT_SHADOW_RADIUS = 8.0f;
// Properties
private float borderWidth;
private int canvasSize;
private float shadowRadius;
private int shadowColor = Color.BLACK;
private ShadowGravity shadowGravity = ShadowGravity.BOTTOM;
private ColorFilter colorFilter;
// Object used to draw
private Bitmap image;
private Drawable drawable;
private Paint paint;
private Paint paintBorder;
private Paint paintBackground;
//region Constructor & Init Method
public CircularImageView(final Context context) {
this(context, null);
}
public CircularImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircularImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
// Init Paint
Paint = new Paint();
Paint.setAntiAlias(true);
paintBorder = new Paint();
paintBorder.setAntiAlias(true);
paintBackground = new Paint();
paintBackground.setAntiAlias(true);
// Load the styled attributes and set their properties
TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.CircularImageView, defStyleAttr, 0);
// Init Border
if (attributes.getBoolean(R.styleable.CircularImageView_civ_border, true)) {
float defaultBorderSize = DEFAULT_BORDER_WIDTH * getContext().getResources().getDisplayMetrics().density;
setBorderWidth(attributes.getDimension(R.styleable.CircularImageView_civ_border_width, defaultBorderSize));
setBorderColor(attributes.getColor(R.styleable.CircularImageView_civ_border_color, Color.WHITE));
}
setBackgroundColor(attributes.getColor(R.styleable.CircularImageView_civ_background_color, Color.WHITE));
// Init Shadow
if (attributes.getBoolean(R.styleable.CircularImageView_civ_shadow, false)) {
shadowRadius = DEFAULT_SHADOW_RADIUS;
drawShadow(attributes.getFloat(R.styleable.CircularImageView_civ_shadow_radius, shadowRadius),
attributes.getColor(R.styleable.CircularImageView_civ_shadow_color, shadowColor));
int shadowGravityIntValue = attributes.getInteger(R.styleable.CircularImageView_civ_shadow_gravity, ShadowGravity.BOTTOM.getValue());
shadowGravity = ShadowGravity.fromValue(shadowGravityIntValue);
}
attributes.recycle();
}
//endregion
//region Set Attr Method
public void setBorderWidth(float borderWidth) {
this.borderWidth = borderWidth;
requestLayout();
invalidate();
}
public void setBorderColor(int borderColor) {
if (paintBorder != null)
paintBorder.setColor(borderColor);
invalidate();
}
public void setBackgroundColor(int backgroundColor) {
if (paintBackground != null)
paintBackground.setColor(backgroundColor);
invalidate();
}
public void addShadow() {
if (shadowRadius == 0)
shadowRadius = DEFAULT_SHADOW_RADIUS;
drawShadow(shadowRadius, shadowColor);
invalidate();
}
public void setShadowRadius(float shadowRadius) {
drawShadow(shadowRadius, shadowColor);
invalidate();
}
public void setShadowColor(int shadowColor) {
drawShadow(shadowRadius, shadowColor);
invalidate();
}
public void setShadowGravity(ShadowGravity shadowGravity) {
this.shadowGravity = shadowGravity;
invalidate();
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
if (this.colorFilter == colorFilter)
return;
this.colorFilter = colorFilter;
drawable = null; // To force re-update shader
invalidate();
}
@Override
public ScaleType getScaleType() {
ScaleType currentScaleType = super.getScaleType();
return currentScaleType == null || currentScaleType != CENTER_INSIDE ? CENTER_CROP : currentScaleType;
}
@Override
public void setScaleType(ScaleType scaleType) {
if (scaleType != CENTER_CROP && scaleType != CENTER_INSIDE) {
throw new IllegalArgumentException(String.format("ScaleType %s not supported. " +
"Just ScaleType.CENTER_CROP & ScaleType.CENTER_INSIDE are available for this library.", scaleType));
} else {
super.setScaleType(scaleType);
}
}
//endregion
//region Draw Method
@Override
public void onDraw(Canvas canvas) {
// Load the bitmap
loadBitmap();
// Check if image isn't null
if (image == null)
return;
if (!isInEditMode()) {
canvasSize = Math.min(canvas.getWidth(), canvas.getHeight());
}
// circleCenter is the x or y of the view's center
// radius is the radius in pixels of the cirle to be drawn
// Paint contains the shader that will texture the shape
int circleCenter = (int) (canvasSize - (borderWidth * 2)) / 2;
float margeWithShadowRadius = shadowRadius * 2;
// Draw Border
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, circleCenter + borderWidth - margeWithShadowRadius, paintBorder);
// Draw Circle background
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, circleCenter - margeWithShadowRadius, paintBackground);
// Draw CircularImageView
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, circleCenter - margeWithShadowRadius, Paint);
}
private void loadBitmap() {
if (drawable == getDrawable())
return;
drawable = getDrawable();
image = drawableToBitmap(drawable);
updateShader();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
canvasSize = Math.min(w, h);
if (image != null)
updateShader();
}
private void drawShadow(float shadowRadius, int shadowColor) {
this.shadowRadius = shadowRadius;
this.shadowColor = shadowColor;
setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
float dx = 0.0f;
float dy = 0.0f;
switch (shadowGravity) {
case CENTER:
dx = 0.0f;
dy = 0.0f;
break;
case TOP:
dx = 0.0f;
dy = -shadowRadius / 2;
break;
case BOTTOM:
dx = 0.0f;
dy = shadowRadius / 2;
break;
case START:
dx = -shadowRadius / 2;
dy = 0.0f;
break;
case END:
dx = shadowRadius / 2;
dy = 0.0f;
break;
}
paintBorder.setShadowLayer(shadowRadius, dx, dy, shadowColor);
}
private void updateShader() {
if (image == null)
return;
// Create Shader
BitmapShader shader = new BitmapShader(image, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
// Center Image in Shader
float scale = 0;
float dx = 0;
float dy = 0;
switch (getScaleType()) {
case CENTER_CROP:
if (image.getWidth() * getHeight() > getWidth() * image.getHeight()) {
scale = getHeight() / (float) image.getHeight();
dx = (getWidth() - image.getWidth() * scale) * 0.5f;
} else {
scale = getWidth() / (float) image.getWidth();
dy = (getHeight() - image.getHeight() * scale) * 0.5f;
}
break;
case CENTER_INSIDE:
if (image.getWidth() * getHeight() < getWidth() * image.getHeight()) {
scale = getHeight() / (float) image.getHeight();
dx = (getWidth() - image.getWidth() * scale) * 0.5f;
} else {
scale = getWidth() / (float) image.getWidth();
dy = (getHeight() - image.getHeight() * scale) * 0.5f;
}
break;
}
Matrix matrix = new Matrix();
matrix.setScale(scale, scale);
matrix.postTranslate(dx, dy);
shader.setLocalMatrix(matrix);
// Set Shader in Paint
Paint.setShader(shader);
// Apply colorFilter
Paint.setColorFilter(colorFilter);
}
private Bitmap drawableToBitmap(Drawable drawable) {
if (drawable == null) {
return null;
} else if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
try {
// Create Bitmap object out of the drawable
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//endregion
//region Measure Method
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
setMeasuredDimension(width, height);
}
private int measureWidth(int measureSpec) {
int result;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// The parent has determined an exact size for the child.
result = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
// The child can be as large as it wants up to the specified size.
result = specSize;
} else {
// The parent has not imposed any constraint on the child.
result = canvasSize;
}
return result;
}
private int measureHeight(int measureSpecHeight) {
int result;
int specMode = MeasureSpec.getMode(measureSpecHeight);
int specSize = MeasureSpec.getSize(measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
// The child can be as large as it wants up to the specified size.
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = canvasSize;
}
return result + 2;
}
//endregion
public enum ShadowGravity {
CENTER,
TOP,
BOTTOM,
START,
END;
public int getValue() {
switch (this) {
case CENTER:
return 1;
case TOP:
return 2;
case BOTTOM:
return 3;
case START:
return 4;
case END:
return 5;
}
throw new IllegalArgumentException("Not value available for this ShadowGravity: " + this);
}
public static ShadowGravity fromValue(int value) {
switch (value) {
case 1:
return CENTER;
case 2:
return TOP;
case 3:
return BOTTOM;
case 4:
return START;
case 5:
return END;
}
throw new IllegalArgumentException("This value is not supported for ShadowGravity: " + value);
}
}
}
res/values / attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CircularImageView">
<attr name="civ_border" format="boolean" />
<attr name="civ_border_width" format="dimension" />
<attr name="civ_border_color" format="color" />
<attr name="civ_background_color" format="color" />
<attr name="civ_shadow" format="boolean" />
<attr name="civ_shadow_color" format="color" />
<attr name="civ_shadow_radius" format="float" />
<attr name="civ_shadow_gravity">
<flag name="center" value="1" />
<flag name="top" value="2" />
<flag name="bottom" value="3" />
<flag name="start" value="4" />
<flag name="end" value="5" />
</attr>
</declare-styleable>
</resources>
Disposition
<com.mypackage.CircularImageView
Android:id="@+id/iv_profile"
Android:layout_width="120dp"
Android:layout_height="120dp"
Android:layout_centerInParent="true"
Android:src="@drawable/your_picture"
app:civ_border="true"
app:civ_border_color="@color/colorAccent"
app:civ_border_width="3dp"/>
Les méthodes ci-dessus ne semblent pas fonctionner si vous utilisez l'attribut src
. Ce que j'ai fait est de placer deux vues d'image dans une disposition de cadre l'une au dessus de l'autre, comme ceci:
<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>
Mettez simplement un circular_crop.png dans votre dossier pouvant être dessiné qui a la forme de vos dimensions d'image (un carré dans mon cas) avec un fond blanc et un cercle transparent au centre. Vous pouvez utiliser cette image si vous voulez une image view carrée.
Il suffit de télécharger la photo ci-dessus.
Voici l'une des manières les plus simples de le faire, utilisez le code suivant:
Dépendances
dependencies {
...
compile 'de.hdodenhof:circleimageview:2.1.0' // use this or use the latest compile version. In case u get bug.
}
Code 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
Capture d'écran:
Avec l'aide de glide library et RoundedBitmapDrawableFactory class, c'est facile à réaliser. Vous devrez peut-être créer une image d'espace réservé circulaire.
Glide V4:
Glide.with(context).load(url).apply(RequestOptions.circleCropTransform()).into(imageView);
Glide V3:
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);
}
});
J'utilise shape = "ovale" au lieu de "l'anneau" ci-dessous. ça a marché pour moi. Pour conserver l'image dans les limites, j'utilise <padding>
et mets <adjustViewBounds>
à true dans mon <ImageView>
. J'ai essayé avec des images de taille comprise entre 50 x 50 px et 200x200 px.
Ça fera l'affaire:
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>
cercle.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 (la liste des couches)
<?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>
Votre mise en page
<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"/>
Vous pouvez simplement utiliser CardView sans aucune bibliothèque externe
<androidx.cardview.widget.CardView
Android:id="@+id/roundCardView"
Android:layout_width="40dp"
Android:layout_height="40dp"
Android:layout_centerHorizontal="true"
Android:elevation="0dp"
app:cardCornerRadius="20dp">
<ImageView
Android:layout_width="40dp"
Android:layout_height="40dp"
Android:src="@drawable/profile" />
</androidx.cardview.widget.CardView>
@Jyotman Singh, la réponse est très bonne (pour les arrière-plans solides), donc j'aimerais l'améliorer en partageant un vecteur dessinable qui peut être re-coloré pour vos besoins, également pratique car la forme vectorielle monobloc est bien évolutive.
C'est la forme d'un rectangle (@ drawable/shape_round_profile_pic):
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:viewportWidth="284"
Android:viewportHeight="284"
Android:width="284dp"
Android:height="284dp">
<path
Android:pathData="M0 142L0 0l142 0 142 0 0 142 0 142 -142 0 -142 0zm165 137.34231c26.06742 -4.1212 52.67405 -17.543 72.66855 -36.65787 11.82805 -11.30768 20.55487 -22.85153 27.7633 -36.72531C290.23789 158.21592 285.62874 101.14121 253.48951 58.078079 217.58149 9.9651706 154.68849 -10.125717 98.348685 8.5190299 48.695824 24.95084 12.527764 67.047123 3.437787 118.98655 1.4806194 130.16966 1.511302 152.96723 3.4990422 164.5 12.168375 214.79902 47.646316 256.70775 96 273.76783c21.72002 7.66322 44.26673 9.48476 69 5.57448z"
Android:fillColor="#ffffff" /> // you can change frame color
</vector>
L'utilisation est la même:
<FrameLayout
Android:layout_width="70dp"
Android:layout_height="70dp">
<ImageView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="@drawable/YOUR_PICTURE" />
<ImageView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="@drawable/shape_round_profile_pic"/>
</FrameLayout>
Utilisez cette bibliothèque (il y a une bonne documentation) et ajoutez votre image en arrière-plan.
En fait, vous pouvez utiliser ce que Google fournit via la bibliothèque de support RoundedBitmapDrawableFactory de classe ( here et here ), au lieu d'utiliser une bibliothèque tierce:
Gradle:
implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val originalDrawable = ContextCompat.getDrawable(this, R.drawable.avatar_1)!!
val bitmap = convertDrawableToBitmap(originalDrawable)
val drawable = RoundedBitmapDrawableFactory.create(resources, bitmap)
drawable.setAntiAlias(true)
drawable.cornerRadius = Math.max(bitmap.width, bitmap.height) / 2.0f
avatarImageView.setImageDrawable(drawable)
}
companion object {
@JvmStatic
fun convertDrawableToBitmap(drawable: Drawable): Bitmap {
if (drawable is BitmapDrawable)
return drawable.bitmap
// We ask for the bounds if they have been set as they would be most
// correct, then we check we are > 0
val bounds = drawable.bounds
val width = if (!bounds.isEmpty) bounds.width() else drawable.intrinsicWidth
val height = if (!bounds.isEmpty) bounds.height() else drawable.intrinsicHeight
// Now we check we are > 0
val bitmap = Bitmap.createBitmap(if (width <= 0) 1 else width, if (height <= 0) 1 else height,
Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
drawable.setBounds(0, 0, canvas.width, canvas.height)
drawable.draw(canvas)
return bitmap
}
}
}
res/layout/activity_main.xml
<FrameLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android" xmlns:app="http://schemas.Android.com/apk/res-auto"
xmlns:tools="http://schemas.Android.com/tools" Android:layout_width="match_parent"
Android:layout_height="match_parent" tools:context=".MainActivity">
<androidx.appcompat.widget.AppCompatImageView
Android:id="@+id/avatarImageView" Android:layout_width="100dp" Android:layout_height="100dp"
Android:layout_gravity="center"/>
</FrameLayout>
res/drawable/avatar_1.xml
<vector xmlns:Android="http://schemas.Android.com/apk/res/Android" Android:width="128dp" Android:height="128dp"
Android:viewportHeight="128.0" Android:viewportWidth="128.0">
<path
Android:fillColor="#FF8A80" Android:pathData="M0 0h128v128h-128z"/>
<path
Android:fillColor="#FFE0B2"
Android:pathData="M36.3 94.8c6.4 7.3 16.2 12.1 27.3 12.4 10.7,-.3 20.3,-4.7 26.7,-11.6l.2.1c-17,-13.3,-12.9,-23.4,-8.5,-28.6 1.3,-1.2 2.8,-2.5 4.4,-3.9l13.1,-11c1.5,-1.2 2.6,-3 2.9,-5.1.6,-4.4,-2.5,-8.4,-6.9,-9.1,-1.5,-.2,-3 0,-4.3.6,-.3,-1.3,-.4,-2.7,-1.6,-3.5,-1.4,-.9,-2.8,-1.7,-4.2,-2.5,-7.1,-3.9,-14.9,-6.6,-23,-7.9,-5.4,-.9,-11,-1.2,-16.1.7,-3.3 1.2,-6.1 3.2,-8.7 5.6,-1.3 1.2,-2.5 2.4,-3.7 3.7l-1.8 1.9c-.3.3,-.5.6,-.8.8,-.1.1,-.2 0,-.4.2.1.2.1.5.1.6,-1,-.3,-2.1,-.4,-3.2,-.2,-4.4.6,-7.5 4.7,-6.9 9.1.3 2.1 1.3 3.8 2.8 5.1l11 9.3c1.8 1.5 3.3 3.8 4.6 5.7 1.5 2.3 2.8 4.9 3.5 7.6 1.7 6.8,-.8 13.4,-5.4 18.4,-.5.6,-1.1 1,-1.4 1.7,-.2.6,-.4 1.3,-.6 2,-.4 1.5,-.5 3.1,-.3 4.6.4 3.1 1.8 6.1 4.1 8.2 3.3 3 8 4 12.4 4.5 5.2.6 10.5.7 15.7.2 4.5,-.4 9.1,-1.2 13,-3.4 5.6,-3.1 9.6,-8.9 10.5,-15.2m-14.4,-49.8c.9 0 1.6.7 1.6 1.6 0 .9,-.7 1.6,-1.6 1.6,-.9 0,-1.6,-.7,-1.6,-1.6,-.1,-.9.7,-1.6 1.6,-1.6zm-25.7 0c.9 0 1.6.7 1.6 1.6 0 .9,-.7 1.6,-1.6 1.6,-.9 0,-1.6,-.7,-1.6,-1.6,-.1,-.9.7,-1.6 1.6,-1.6z"/>
<path
Android:fillColor="#E0F7FA"
Android:pathData="M105.3 106.1c-.9,-1.3,-1.3,-1.9,-1.3,-1.9l-.2,-.3c-.6,-.9,-1.2,-1.7,-1.9,-2.4,-3.2,-3.5,-7.3,-5.4,-11.4,-5.7 0 0 .1 0 .1.1l-.2,-.1c-6.4 6.9,-16 11.3,-26.7 11.6,-11.2,-.3,-21.1,-5.1,-27.5,-12.6,-.1.2,-.2.4,-.2.5,-3.1.9,-6 2.7,-8.4 5.4l-.2.2s-.5.6,-1.5 1.7c-.9 1.1,-2.2 2.6,-3.7 4.5,-3.1 3.9,-7.2 9.5,-11.7 16.6,-.9 1.4,-1.7 2.8,-2.6 4.3h109.6c-3.4,-7.1,-6.5,-12.8,-8.9,-16.9,-1.5,-2.2,-2.6,-3.8,-3.3,-5z"/>
<path
Android:fillColor="#444" Android:pathData="M76.3,47.5 m-2.0, 0 a 2.0,2.0 0 1,1 4.0,0 a2.0,2.0 0 1,1 -4.0,0"/>
<path
Android:fillColor="#444" Android:pathData="M50.7,47.6 m-2.0, 0 a 2.0,2.0 0 1,1 4.0,0 a2.0,2.0 0 1,1 -4.0,0"/>
<path
Android:fillColor="#444"
Android:pathData="M48.1 27.4c4.5 5.9 15.5 12.1 42.4 8.4,-2.2,-6.9,-6.8,-12.6,-12.6,-16.4 17.2 1.5 14.1,-9.4 14.1,-9.4,-1.4 5.5,-11.1 4.4,-11.1 4.4h-18.8c-1.7,-.1,-3.4 0,-5.2.3,-12.8 1.8,-22.6 11.1,-25.7 22.9 10.6,-1.9 15.3,-7.6 16.9,-10.2z"/>
</vector>
Le résultat:
Et, supposons que vous vouliez ajouter une bordure par-dessus, vous pouvez utiliser ceci par exemple:
stroke_drawable.xml
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android" Android:shape="oval">
<stroke
Android:width="4dp" Android:color="@Android:color/black"/>
</shape>
Et ajoutez Android:foreground="@drawable/stroke_drawable"
à ImageView dans le fichier XML de présentation, et vous obtenez ceci:
Je ne sais pas comment ajouter une ombre (cela fonctionnera sur les anciennes versions d'Android), cependant. En utilisant FloatingActionButton (à partir du "com.google.Android.material: material" dependency ), je n’ai pas réussi à faire en sorte que le bitmap remplisse le FAB lui-même. L’utiliser à la place pourrait être encore meilleur si cela fonctionnait.
EDIT: si vous souhaitez ajouter une ombre d'élévation (disponible à partir de l'API 21), vous pouvez changer un peu ce que j'ai écrit:
Dans le fichier XML de présentation:
<androidx.appcompat.widget.AppCompatImageView Android:padding="4dp"
Android:id="@+id/avatarImageView" Android:layout_width="100dp" Android:layout_height="100dp" Android:elevation="8dp"
Android:layout_gravity="center" Android:background="@drawable/stroke_drawable" tools:srcCompat="@drawable/avatar_1"/>
CircularShadowViewOutlineProvider.kt
@TargetApi(Build.VERSION_CODES.Lollipop)
class CircularShadowViewOutlineProvider : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
val size = Math.max(view.width, view.height)
outline.setRoundRect(0, 0, size, size, size / 2f)
}
}
Dans du code:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop)
avatarImageView.outlineProvider = CircularShadowViewOutlineProvider()
Résultat:
utilisez simplement ce code simple: Ajoutez d’abord une dépendance:
implementation 'de.hdodenhof:circleimageview:2.2.0'
puis ajoutez dans XML layout le code suivant: -
<de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:id="@+id/Imgshaligram"
Android:layout_width="96dp"
Android:layout_height="96dp"
Android:src="@drawable/shaligram"
app:civ_border_color="#d1b1b1"
Android:foregroundGravity="center"/>
Essaye ça.
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);
}
}
et utiliser cette ImageView dans la disposition comme:
<com.app.Demo.RoundedImageView
Android:id="@+id/iv_profileImage"
Android:layout_width="70dp"
Android:layout_height="70dp"
Android:layout_centerHorizontal="true"
/>
J'ai une solution simple. Créez un nouvel actif d'image en cliquant avec le bouton droit de la souris sur le nom de votre paquet et en sélectionnant Nouveau-> Actif d'image. Entrez le nom (n'importe quel nom) et le chemin (emplacement de l'image dans votre système). Cliquez ensuite sur Suivant et sur Terminer. Si vous entrez le nom de l'image comme "img", une image ronde portant le nom "img_round" est créée automatiquement dans le dossier mipmap.
Ensuite, faites ceci:
<ImageView
Android:layout_width="100dp"
Android:layout_height="100dp"
Android:src="@mipmap/img_round"/>
Votre aperçu peut toujours montrer une image rectangulaire. Mais si vous exécutez l'application sur votre appareil, ce sera rond.
Cette classe est une image circulaire personnalisée avec ombre, trait, saturation et en utilisant cette image circulaire personnalisée, vous pouvez créer votre image en forme circulaire avec rayon. Les gars pour Shadow Circular ImageView Pas besoin Github cette classe est assez.
Ajout de CircularImageView à votre mise en page
CircularImageView c=new CircularImageView(this,screen width,screen height,Bitmap myimage);
yourLayout.addView(c);**
public class CircularImageView extends Android.support.v7.widget.AppCompatImageView
{
private final Context context;
private final int width, height;
private final Paint paint;
private final Paint paintBorder,imagePaint;
private final Bitmap bitmap2;
private final Paint paint3;
private Bitmap bitmap;
private BitmapShader shader;
private float radius = 4.0f;
float x = 0.0f;
float y = 8.0f;
private float stroke;
private float strokeWidth = 0.0f;
private Bitmap bitmap3;
private int corner_radius=50;
public CircularImageView(Context context, int width, int height, Bitmap bitmap) {
super(context);
this.context = context;
this.width = width;
this.height = height;
//here "bitmap" is the square shape(width* width) scaled bitmap ..
this.bitmap = bitmap;
Paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Paint.setAntiAlias(true);
Paint.setFilterBitmap(true);
Paint.setDither(true);
Paint3=new Paint();
Paint3.setStyle(Paint.Style.STROKE);
Paint3.setColor(Color.WHITE);
Paint3.setAntiAlias(true);
paintBorder = new Paint();
imagePaint= new Paint();
paintBorder.setColor(Color.WHITE);
paintBorder.setAntiAlias(true);
this.setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
this.bitmap2 = Bitmap.createScaledBitmap(bitmap, (bitmap.getWidth() - 40), (bitmap.getHeight() - 40), true);
imagePaint.setAntiAlias(true);
invalidate();
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Shader b;
if (bitmap3 != null)
b = new BitmapShader(bitmap3, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
else
b = new BitmapShader(bitmap2, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
imagePaint.setShader(b);
canvas.drawBitmap(maskedBitmap(), 20, 20, null);
}
private Bitmap maskedBitmap()
{
Bitmap l1 = Bitmap.createBitmap(width,width, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(l1);
paintBorder.setShadowLayer(radius, x, y, Color.parseColor("#454645"));
Paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
final RectF rect = new RectF();
rect.set(20, 20, bitmap2.getWidth(), bitmap2.getHeight());
canvas.drawRoundRect(rect, corner_radius, corner_radius, paintBorder);
canvas.drawRoundRect(rect, corner_radius, corner_radius, imagePaint);
if (strokeWidth!=0.0f)
{
Paint3.setStrokeWidth(strokeWidth);
canvas.drawRoundRect(rect, corner_radius, corner_radius, Paint3);
}
Paint.setXfermode(null);
return l1;
}
// use seekbar here, here you have to pass "0 -- 250" here corner radius will change
public void setCornerRadius(int corner_radius)
{
this.corner_radius = corner_radius;
invalidate();
}
-------->use seekbar here, here you have to pass "0 -- 10.0f" here shadow radius will change
public void setShadow(float radius)
{
this.radius = radius;
invalidate();
}
// use seekbar here, here you have to pass "0 -- 10.0f" here stroke size will change
public void setStroke(float stroke)
{
this.strokeWidth = stroke;
invalidate();
}
private Bitmap updateSat(Bitmap src, float settingSat)
{
int w = src.getWidth();
int h = src.getHeight();
Bitmap bitmapResult =
Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvasResult = new Canvas(bitmapResult);
Paint paint = new Paint();
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.setSaturation(settingSat);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);
Paint.setColorFilter(filter);
canvasResult.drawBitmap(src, 0, 0, Paint);
return bitmapResult;
}
// use seekbar here, here you have to pass "0 -- 2.0f" here saturation will change
public void setSaturation(float sat)
{
System.out.println("qqqqqqqqqq "+sat);
bitmap3=updateSat(bitmap2, sat);
invalidate();
}
}
// Seekbar to change radius
radius_seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
text_radius.setText(""+progress);
circularImageView.setCornerRadius(progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
// Seekbar to change shadow
shadow_seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
float f= 4+progress/10.0f;
text_shadow.setText(""+progress);
circularImageView.setShadow(f);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
// Seekbar to change saturation
saturation_seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
int progressSat = saturation_seekbar.getProgress();
float sat = (float) ((progressSat*4 / 100.0f)-1.0f);
circularImageView.setSaturation(sat);
text_saturation.setText(""+progressSat);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
// Seekbar to change stroke
stroke_seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
if (progress==0)
{
float f=(progress*10.0f/100.0f);
circularImageView.setStroke(f);
}
else
{
float f=(progress*10.0f/100.0f);
circularImageView.setStroke(f);
}
text_stroke.setText(""+progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
//radius seekbar in xml file
<SeekBar
Android:layout_width="match_parent"
Android:layout_gravity="center"
Android:progress="50"
Android:max="250"
Android:id="@+id/radius_seekbar"
Android:layout_height="wrap_content" />
//saturation seekbar in xml file
<SeekBar
Android:layout_width="match_parent"
Android:layout_gravity="center"
Android:progress="50"
Android:max="100"
Android:id="@+id/saturation_seekbar"
Android:layout_height="wrap_content" />
//shadow seekbar in xml file
<SeekBar
Android:layout_width="match_parent"
Android:layout_gravity="center"
Android:progress="0"
Android:max="100"
Android:id="@+id/shadow_seekbar"
Android:layout_height="wrap_content" />
//stroke seekbar in xml file
<SeekBar
Android:layout_width="match_parent"
Android:layout_gravity="center"
Android:progress="0"
Android:max="100"
Android:id="@+id/stroke _seekbar"
Android:layout_height="wrap_content" />
Utilisez simplement ces lignes de code et vous avez terminé:
<de.hdodenhof.circleimageview.CircleImageView
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:clickable="true"
app:civ_border_width="3dp"
app:civ_border_color="#FFFFFFFF"
Android:id="@+id/profile"
Android:layout_width="200dp"
Android:layout_height="200dp"
Android:layout_below="@+id/header_cover_image"
Android:layout_centerHorizontal="true"
Android:layout_marginTop="-130dp"
Android:elevation="5dp"
Android:padding="20dp"
Android:scaleType="centerCrop"
Android:src="@drawable/profilemain" />
N'oubliez pas d'importer:
import de.hdodenhof.circleimageview.CircleImageView;
Ajoutez cette bibliothèque dans build.gradle:
compile 'de.hdodenhof:circleimageview:2.1.0'
Créez une CustomImageview qui suit simplement sa méthode onDraw()
:
@Override
protected void onDraw(Canvas canvas) {
float radius = this.getHeight()/2;
Path path = new Path();
RectF rect = new RectF(0, 0, this.getWidth(), this.getHeight());
path.addRoundRect(rect, radius, radius, Path.Direction.CW);
canvas.clipPath(path);
super.onDraw(canvas);
}