Android

How to add a shadow and a border on circular imageView android?

Как добавить тень и границу в circular ImageView Android?

Я создал CircularImageView с этим вопросом: Создать круговой вид изображения в Android

Скачать проект можно на GitHub

1) Это класс CircularImageView :

public class CircularImageView extends ImageView {
public CircularImageView(Context context) {
super(context);
}

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

public CircularImageView(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);

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

public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) {
Bitmap sbmp;
if(bmp.getWidth() != radius || bmp.getHeight() != radius)
sbmp = Bitmap.createScaledBitmap(bmp, radius, radius, false);
else
sbmp = bmp;

Bitmap output = Bitmap.createBitmap(sbmp.getWidth(), sbmp.getHeight(), Bitmap.Config.ARGB_8888);
final Rect rect = new Rect(0, 0, sbmp.getWidth(), sbmp.getHeight());

Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
paint.setColor(Color.parseColor("#BAB399"));

Canvas c = new Canvas(output);
c.drawARGB(0, 0, 0, 0);
c.drawCircle(sbmp.getWidth() / 2+0.7f, sbmp.getHeight() / 2+0.7f, sbmp.getWidth() / 2+0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
c.drawBitmap(sbmp, rect, rect, paint);

return output;
}
}

2) Я использую в своем макете вот так :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#cccccc"
android:gravity="center"
android:orientation="vertical"
android:padding="10dp" >

<com.mikhaellopez.circularimageview.CircularImageView
android:id="@+id/imageViewCircular"
android:layout_width="@dimen/image_view_size"
android:layout_height="@dimen/image_view_size"
android:layout_gravity="center"
android:background="@drawable/border"
android:src="@drawable/image" />

</LinearLayout>

3) Текущий результат на картинке :

Текущий результат

Как мне изменить этот код, чтобы вокруг моего ImageView были тень и круговая граница?

Результат Objectif :

Результат Objectif


Редактировать 15.10.2015 :

Вы можете использовать или загрузить мою библиотеку на GitHub CircularImageView со всеми исправлениями, используя зависимость gradle :

compile 'com.mikhaellopez:circularimageview:2.0.1'
Переведено автоматически
Ответ 1

Я изменил CircularImageView, найденный здесь, чтобы добиться того, чего вы хотите.

Чтобы создать тень вокруг границы, я просто использовал эти две строки:

this.setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
paintBorder.setShadowLayer(4.0f, 0.0f, 2.0f, Color.BLACK);

Вам нужно setLayerType из-за аппаратного ускорения в HoneyComb и выше. Без этого не получалось, когда я пробовал.

Вот полный код:

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.widget.ImageView;

public class CircularImageView extends ImageView
{
private int borderWidth = 4;
private int viewWidth;
private int viewHeight;
private Bitmap image;
private Paint paint;
private Paint paintBorder;
private BitmapShader shader;

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

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

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

private void setup()
{
// init paint
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.BLACK);
}

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)
{
// load the bitmap
loadBitmap();

// init shader
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;

// 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
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)
{
// We were told how big to be
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)
{
// We were told how big to be
result = specSize;
}
else
{
// Measure the text (beware: ascent is a negative number)
result = viewHeight;
}

return (result + 2);
}
}

Надеюсь, это поможет!

.

Редактировать

Я разветвил CircularImageView и добавил поддержку наложений селекторов. Я также значительно улучшил производительность рисования...

https://github.com/Pkmmte/CircularImageView

Ответ 2

Чтобы добавить границу, сделав ImageView в виде круга, я сделал простую вещь, я использовал этот класс, чтобы сделать свое изображение в виде круга

package com.fidenz.fexceller.fexceller;

/**
* Created by Chathu Hettiarachchi on 5/18/2015.
*/

import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;

public class RoundedImg extends Drawable {
private final Bitmap mBitmap;
private final Paint mPaint;
private final RectF mRectF;
private final int mBitmapWidth;
private final int mBitmapHeight;

public RoundedImg(Bitmap bitmap) {
mBitmap = bitmap;
mRectF = new RectF();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
final BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint.setShader(shader);

mBitmapWidth = mBitmap.getWidth();
mBitmapHeight = mBitmap.getHeight();
}

@Override
public void draw(Canvas canvas) {
canvas.drawOval(mRectF, mPaint);
}

@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mRectF.set(bounds);
}

@Override
public void setAlpha(int alpha) {
if (mPaint.getAlpha() != alpha) {
mPaint.setAlpha(alpha);
invalidateSelf();
}
}

@Override
public void setColorFilter(ColorFilter cf) {
mPaint.setColorFilter(cf);
}

@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}

@Override
public int getIntrinsicWidth() {
return mBitmapWidth;
}

@Override
public int getIntrinsicHeight() {
return mBitmapHeight;
}

public void setAntiAlias(boolean aa) {
mPaint.setAntiAlias(aa);
invalidateSelf();
}

@Override
public void setFilterBitmap(boolean filter) {
mPaint.setFilterBitmap(filter);
invalidateSelf();
}

@Override
public void setDither(boolean dither) {
mPaint.setDither(dither);
invalidateSelf();
}

public Bitmap getBitmap() {
return mBitmap;
}

}

и, используя это наonCreate, я вызвал изображение для его настройки,

profilePic = (ImageView)findViewById(R.id.img_home_profile_pic);

Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.no_image);
roundedImage = new RoundedImg(bm);
profilePic.setImageDrawable(roundedImage);

чтобы добавить границу, я создал XML в форме круга, подобный этому,

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" >
<gradient android:startColor="@color/ring_color" android:endColor="@color/ring_color"
android:angle="270"/>
</shape>

затем, используя layouts, я добавил внутри него RelativeLayout with ImageView, используя padding и background drawable с помощью wrap_content я установил свой RelativeLayout следующим образом

<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/lay_rel_img"
android:layout_gravity="center"
android:padding="5dp"
android:background="@drawable/circle">

<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_gravity="center"
android:id="@+id/img_home_profile_pic"
android:src="@drawable/no_image"
android:layout_centerHorizontal="true"/>

</RelativeLayout>

теперь это отображается так, я не знаю, как добавить тень, извините и за это

введите описание изображения здесь

Ответ 3

  1. Добавить canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 2, paint); перед canvas.drawBitmap(roundBitmap, 0, 0, null);

  2. Изменить c.drawCircle(sbmp.getWidth() / 2, sbmp.getHeight() / 2, sbmp.getWidth() / 2, paint); на c.drawCircle(sbmp.getWidth() / 2, sbmp.getHeight() / 2, sbmp.getWidth() / 2 - "the border with you prefer", paint);

Надеюсь, это поможет.

Возможно, здесь есть решение получше.

Ответ 4

Создайте пользовательский объект рисования и используйте его для определения атрибута фона вашего ImageView. Вы можете использовать LayeredDrawable, чтобы создать столько различных компонентов для компонента, сколько захотите.

Проверьте этот ответ, который создает пользовательский прямоугольник (но точно такой же с овалом \ кругом): Как создать пользовательский интерфейс Google + Cards в виде списка?

java android