Как добавить тень и границу на круговом образе viewView?
Я создал CircularImageView с этим вопросом: Создание кругового изображения в андроиде
Загрузить проект 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) Текущий результат на картинке:
![Current result]()
Как изменить этот код на наличие тени и круговой границы вокруг моего изображения?
Результат Objectif:
![Objectif result]()
Редактировать 10/15/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 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
чтобы добавить границу, сделав изображение в виде круга, я сделал простую вещь,
Я использовал этот класс, чтобы сделать изображение в виде круга
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>
затем используя макеты, я добавил relativeLayout с представлением изображения внутри него, используя прописку и фоновый рисунок с помощью wrapcontent. Я установил свой относительный макет, как этот
<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>
теперь он выглядит так, я не знаю, чтобы добавить тень, извините за это тоже
![enter image description here]()
Ответ 3
-
Добавить
canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 2, paint);
до
canvas.drawBitmap(roundBitmap, 0, 0, null);
-
+ Изменить
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, чтобы создать столько компонентов для компонента, сколько захотите.
Ознакомьтесь с этим ответом, который создает настраиваемый Rectangle (но точно такой же, как и в Oval\Circle): Как создать пользовательский интерфейс Google + в виде списка?
Ответ 5
просто используйте метод drawCircle() с большей шириной и высотой перед рисованием фактического изображения. Увеличьте ширину и высоту в этом новом вызове метода в соответствии с вашим желанием и установите другой цвет, который вы хотите покрасить
Ответ 6
Я нашел библиотеку, которая делает именно то, что вы пожелаете, отлично работала для меня.
Проверьте это.
https://android-arsenal.com/details/1/932