ImageView в цикле через xml
Я хотел бы сделать любое изображение из моего ImageView
быть круговым с границей.
Я искал, но не смог найти никакой полезной информации (все, что я пробовал, не сработало).
Как я могу достичь этого через xml:
Создайте ImageView
с определенным src и сделать его круговым с границей?
16 ответов:
вы можете сделать простой круг с белой каймой и прозрачным содержимым с формой.
// 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>
затем сделайте layerlist drawable и поместите его в качестве фона для вашего imageview.
// 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"/>
У вас будет что-то вроде этого.
Это самый простой способ, который я разработал. Попробовать это.
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>
Если вы работаете на Android версии выше леденец
<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>
Я надеюсь, это может помочь вам.
1) со сторонней библиотекой
<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" />
Примечание: в вашем проекте откройте your_app > Gradle Scripts > build.gradle (Module: app) и добавьте следующий оператор реализации к зависимостям{}
implementation 'de.hdodenhof:circleimageview:2.2.0'
для полного описания, пожалуйста, проверьте:здесь Источник.
2) без сторонних Библиотека
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>
планировка
<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"/>
ниже приводится один из самых простых способов сделать это, используйте следующий код:
зависимости
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
скриншоты:
Я использую shape = " овал "вместо" кольцо " ниже. Это сработало для меня. Чтобы сохранить изображение в пределах границ, я использую
<padding>
и set<adjustViewBounds>
true в моем<ImageView>
. Я пробовал с изображениями размером от 50 x 50 px до 200x200 px .
С помощью скольжения библиотеки и RoundedBitmapDrawableFactory класс это легко достичь. Возможно, вам потребуется создать круговое изображение заполнителя.
Скольжение 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); } });
это будет делать трюк:
прямоугольник.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>
круг.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 (The 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"/>
этот класс является пользовательским круговым Imageview с тенью, штрихом, насыщенностью и с помощью этого пользовательского кругового ImageView вы можете сделать свое изображение в круглой форме с радиусом. Ребята для круговой тени ImageView нет необходимости Github этого класса достаточно.
добавление CircularImageView в макет
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" />
@Jyotman Singh, ответ очень хорош (для сплошных фонов), поэтому я хотел бы улучшить его, поделившись векторным рисунком, который можно перекрасить для ваших нужд, также это удобно, поскольку векторная цельная форма хорошо масштабируется.
это прямоугольник-круг формы (@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>
использование:
<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>
на самом деле, вы можете использовать то, что Google предоставляет через библиотеку поддержки RoundedBitmapDrawableFactory class (здесь и здесь), вместо того, чтобы использовать стороннюю библиотеку :
Gradle:
implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
MainActivity.КТ
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>
результат:
и, предположим, вы хотите добавить границы сверху, вы можете использовать это для пример:
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>
и добавить
android:foreground="@drawable/stroke_drawable"
к ImageView в xml-файле макета, и вы получите это:Я не уверен, как добавить тень (которая будет работать на старых версиях Android), хотя. Используя FloatingActionButton (от " com.гуглить.андроид.материал:материал" зависимость), Я не смог сделать растровое изображение заполняет саму ФАБ. Использование его вместо этого может быть еще лучше, если это сработает.
EDIT: если вы хотите добавить тень высоты (доступно из API 21), Вы можете немного изменить то, что я написал:
внутри XML-файла макета:
<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.КТ
@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) } }
In код:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) avatarImageView.outlineProvider = CircularShadowViewOutlineProvider()
результат:
просто используйте этот простой код: Сначала добавьте зависимость:
implementation 'de.hdodenhof:circleimageview:2.2.0'
затем добавить в xml-файле разметки следующий код:-
<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"/>
использовать ниже код, вы можете изменить его :
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; } }
попробуйте это.
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" />
как было описано в ответе Орхана обута, но с изменениями:
<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>
(без изменений), и круг.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 (профиль.ПНГ ), кстати. С такой же шириной и высота. Это верно для произвольных размеров ImageView.
просто используйте эти строки кода, и вы сделали:
<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" />
не забудьте импортировать :
import de.hdodenhof.circleimageview.CircleImageView;
добавить эту библиотеку в строй.Gradle в :
compile 'de.hdodenhof:circleimageview:2.1.0'