2013-07-15 4 views
55

Я создал CircularImageView с этим вопросом: Create circular image view in androidКак добавить тень и границу на круге imageView 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) Текущий результат на картинке:

Current result

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

Objectif результат:

Objectif result


Редактировать 10/15/2015:

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

compile 'com.mikhaellopez:circularimageview:2.0.1' 
+16

Я не знаю, какое приложение вы делаете, но выглядит потрясающе – Jameo

+0

@ lopez.mikhael Ваш код работает, и это действительно хорошо! Но можно ли использовать wrap_content по ширине и высоте? Это сбой, когда я пытался. –

+0

@ DanielNazareth Вы правы, сейчас невозможно использовать wrap_content по ширине и высоте. У меня не было времени изменить его. Беда исходит из того, что я сделал, используя размеры изображения, чтобы нарисовать круг. Используя wrap_content, я теряю эту информацию. Проблема будет исправлена, я предупрежу вас. –

ответ

69

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

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

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); 
    } 
} 

Я надеюсь, что это помогает!

.

EDIT

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

https://github.com/Pkmmte/CircularImageView

+0

Есть ли способ добавить тень к RoundedImageView https://github.com/vinc3m1/RoundedImageView? – toobsco42

+0

Отличное решение - работает сон. Однако, похоже, он не сохраняет соотношение сторон прямоугольного изображения. –

+0

Можете ли вы, пожалуйста, помочь мне в тени для разных фигур, таких как полигон, звезды и т. Д.? – Dig

1

просто использовать метод DrawCircle() с большей шириной и высотой перед нанесением фактического изображения. Увеличьте ширину и высоту в этом новом вызове метода по вашему желанию, и установить некоторые другие цвета из вы хотите на краске

+0

Я сделал первый круг с цветом моей границы. Затем я создал второй меньший круг, который будет содержать мое изображение, и он работает. Однако мой второй, меньший круг не сосредоточен на моем первом. Как я могу это сделать? –

+0

напишите центр и радиус этих обоих кругов, их центральные точки должны быть одинаковыми –

+0

У вас есть образец кода вашего первого решения? –

2
  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);

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

Возможно, лучшее решение here.

+0

Отлично, работа на границе.Ему не хватает теневого эффекта, у вас будет идея? –

2

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

Checkout этот ответ, который создает пользовательский прямоугольник (но точно так же с овальным \ Circle): How to create Google + cards UI in a list view?

6

добавить границу, сделав 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); 

добавить границы IC reated в круге форме 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 с ImageView внутри него, с помощью отступов и фон рисует с 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

+0

Это хорошее решение, спасибо за это, я попробую. –

Смежные вопросы