在Android中自定义ImageView

时间:2015-06-30 15:55:25

标签: android image imageview

我需要帮助创建ImageView。我需要制作一个圆形边缘的图像(带有圆边的正方形)。我不知道更确切的词。有没有人可能有它的代码,或指向教程的链接?提前谢谢。

ImageView示例:
enter image description here

5 个答案:

答案 0 :(得分:0)

不是舍入昂贵的图像视图,而是应该对图像本身进行舍入,然后使用RoundedBitmapDrawable

将圆角图像放在图像视图中

示例:

RoundedBitmapDrawable dr = RoundedBitmapDrawable.createRoundedBitmapDrawable(res, src);
dr.setCornerRadius(cornerRadius);

imageview.setImageDrawable(dr);

答案 1 :(得分:0)

您可以使用以下课程。这是一个圆形方形边框的图像视图。

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

/**
 * A customized squared image view class.
 *
 * Extra functions:
 * {@link #removeBorder(boolean)}
 * {@link #setBorderWidth(int)}
 * {@link #setBorderColor(int)}
 * {@link @setBitmap}
 * <p/>
 * The rest of the things is exactly the same as {@link android.widget.ImageView}
 * <p/>
 * Created by amintavassolian on 15-02-12.
 */

public class SquareImageView extends ImageView {

    private static final float DEFAULT_BOARDER_STROKE = 5;

    private int borderColor;
    private int borderWidth;

    private Bitmap bitmap;

    private boolean removeBorder = false;

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

    @Override
    protected void onDraw(Canvas canvas) {

        Bitmap imageBitmap = getBitmapResource();
        Bitmap temporaryBitmap;
        if (imageBitmap != null) {
            temporaryBitmap = imageBitmap.copy(Bitmap.Config.ARGB_8888, true);
        } else {
            return;
        }

        int w = getWidth();

        Bitmap roundBitmap = getRoundedCroppedBitmap(cropBitmap(temporaryBitmap), w);
        canvas.drawBitmap(roundBitmap, 0, 0, null);
    }

    private Bitmap getBitmapResource() {
        if (bitmap == null) {
            Drawable drawable = getDrawable();
            if (drawable == null) {
                return null;
            }

            if (getWidth() == 0 || getHeight() == 0) {
                return null;
            }

            return ((BitmapDrawable) drawable).getBitmap();
        } else {
            return bitmap;
        }
    }

    private Bitmap cropBitmap(Bitmap sourceBmp) {
        Bitmap outputBmp;

        if (sourceBmp.getWidth() > sourceBmp.getHeight()) {
            outputBmp = Bitmap.createBitmap(sourceBmp, 0, 0, sourceBmp.getHeight(), sourceBmp.getHeight());
        } else if (sourceBmp.getWidth() < sourceBmp.getHeight()) {
            outputBmp = Bitmap.createBitmap(sourceBmp, 0, 0, sourceBmp.getWidth(), sourceBmp.getWidth());
        } else {
            outputBmp = sourceBmp;
        }

        return outputBmp;
    }

    private Bitmap getRoundedCroppedBitmap(Bitmap bitmap, int radius) {
        Bitmap finalBitmap;
        if (bitmap.getWidth() != radius || bitmap.getHeight() != radius) {
            // Set the filter to false, because we don't need very smooth one! It's cheaper!
            finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius, false);
        } else {
            finalBitmap = bitmap;
        }

        Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(), finalBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, finalBitmap.getWidth(), finalBitmap.getHeight());

        paint.setAntiAlias(true);
        paint.setFilterBitmap(true);
        paint.setDither(true);

        canvas.drawARGB(0, 0, 0, 0);

        // It doesn't matter which color!
        paint.setColor(Color.WHITE);
        canvas.drawRoundRect(new RectF(0, 0, finalBitmap.getWidth(), finalBitmap.getHeight()), 15, 15, paint);

        // The second drawing should only be visible of if overlapping with the first
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(finalBitmap, rect, rect, paint);

        // Draw the border, if exist
        if (!removeBorder) {
            canvas.drawRoundRect(new RectF(0, 0, finalBitmap.getWidth(), finalBitmap.getHeight()), 15, 15, getBorderPaint());
        }



        return output;
    }

    private Paint getBorderPaint() {
        Paint borderPaint = new Paint();
        if (borderColor != 0) {
            borderPaint.setColor(borderColor);
        } else {
            borderPaint.setColor(Color.WHITE);
        }
        if (borderWidth != 0) {
            borderPaint.setStrokeWidth(borderWidth);
        } else {
            borderPaint.setStrokeWidth(DEFAULT_BOARDER_STROKE);
        }

        borderPaint.setStyle(Paint.Style.STROKE);
        borderPaint.setAntiAlias(true);

        return borderPaint;
    }

    /**
     * A method to set the bitmap for the image view
     *
     * @param bmp The target bitmap
     */
    public void setBitmap(Bitmap bmp) {
        this.bitmap = bmp;
    }

    /**
     * A method to se the color of the border of the image view
     *
     * @param colorResource The resource id of the favourite color
     */
    public void setBorderColor(int colorResource) {
        this.borderColor = colorResource;
    }

    /**
     * A method to set the thickness of the border of the image view
     *
     * @param width The width of the border stroke in pixels
     */
    public void setBorderWidth(int width) {
        this.borderWidth = width;
    }

    /**
     * A method to set whether show the image view with border or not
     *
     * @param removeBorder true to remove the border of the iamge view, otherwise it will have a border
     */
    public void removeBorder(boolean removeBorder) {
        this.removeBorder = removeBorder;
    }

}

您可以简单地将它放在xml布局中,并通过android:src属性设置图像或调用setBitmap()函数。您也可以通过调用代码中的以下函数来自定义iamgeview的这个边框:

setBorderColor(int colorResource)
setBorderWidth(int width)
removeBorder(boolean removeBorder)

以下是xml布局的示例:

<yourpackagename.SquareImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/sample_image" />

<强>更新 正如@pskink建议你也可以使用RoundedBitmap。我不熟悉那门课。但是,上面这个类仍然提供了一些额外的功能。

干杯 甲

答案 2 :(得分:0)

的Metalink, 这就是我舍入图像边缘的方法,在图像的XML中添加以下代码。

<ImageView
    android:bottomRightRadius="20dip"
    android:bottomLeftRadius="20dip"  
    android:topRightRadius="20dip"
    android:topLeftRadius="20dip"

/&GT;

根据图像尺寸的大小,相应地将下降值增加或减少到10/30。

由于

答案 3 :(得分:0)

如果您不希望边框影响图像,请使用此类。不幸的是,onDraw()并没有找到在画布上绘制透明区域的任何方法。因此,在这里创建了一个新的位图,并将其绘制在真实的画布上。

如果要使边框消失,该视图将很有用。如果将borderWidth设置为0,则边框将消失并且图像的圆角与边框完全一样。即看起来边框是完全由图像边缘绘制的。

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
import android.graphics.RectF
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatImageView


class RoundedImageViewWithBorder @JvmOverloads constructor(
        context: Context,
        attrs: AttributeSet? = null,
        defStyleAttr: Int = 0) : AppCompatImageView(context, attrs, defStyleAttr) {

    var borderColor: Int = 0
        set(value) {
            invalidate()
            field = value
        }
    var borderWidth: Int = 0
        set(value) {
            invalidate()
            field = value
        }
    var cornerRadius: Float = 0f
        set(value) {
            invalidate()
            field = value
        }

    private var bitmapForDraw: Bitmap? = null
    private var canvasForDraw: Canvas? = null
    private val transparentPaint = Paint().apply {
        isAntiAlias = true
        color = Color.TRANSPARENT
        style = Paint.Style.STROKE
        xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC)
    }

    private val borderPaint = Paint().apply {
        isAntiAlias = true
        style = Paint.Style.STROKE
    }

    private val transparentAreaRect = RectF()
    private val borderRect = RectF()

    init {
        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundedImageViewWithBorder)

        try {
            borderWidth = typedArray.getDimensionPixelSize(R.styleable.RoundedImageViewWithBorder_border_width, 0)
            borderColor = typedArray.getColor(R.styleable.RoundedImageViewWithBorder_border_color, 0)
            cornerRadius = typedArray.getDimensionPixelSize(R.styleable.RoundedImageViewWithBorder_corner_radius, 0).toFloat()

        } finally {
            typedArray.recycle()
        }
    }

    @SuppressLint("CanvasSize", "DrawAllocation")
    override fun onDraw(canvas: Canvas) {

        if (canvasForDraw?.height != canvas.height || canvasForDraw?.width != canvas.width) {
            val newBitmap = Bitmap.createBitmap(canvas.width, canvas.height, Bitmap.Config.ARGB_8888)
            bitmapForDraw = newBitmap
            canvasForDraw = Canvas(newBitmap)
        }

        // Draw existing content
        super.onDraw(canvasForDraw)

        if (borderWidth > 0) {
            canvasForDraw?.let { drawWithBorder(it) }
        } else {
            canvasForDraw?.let { drawWithoutBorder(it) }
        }

        // Draw everything on real canvas
        bitmapForDraw?.let { canvas.drawBitmap(it, 0f, 0f, null) }
    }

    private fun drawWithBorder(canvas: Canvas) {
        // Draw transparent area
        transparentPaint.strokeWidth = borderWidth.toFloat() * 4
        transparentAreaRect.apply {
            left = -borderWidth.toFloat() * 1.5f
            top = -borderWidth.toFloat() * 1.5f
            right = canvas.width.toFloat() + borderWidth.toFloat() * 1.5f
            bottom = canvas.height.toFloat() + borderWidth.toFloat() * 1.5f
        }
        canvasForDraw?.drawRoundRect(transparentAreaRect, borderWidth.toFloat() * 2 + cornerRadius, borderWidth.toFloat() * 2 + cornerRadius, transparentPaint)

        // Draw border
        borderPaint.color = borderColor
        borderPaint.strokeWidth = borderWidth.toFloat()
        borderRect.apply {
            left = borderWidth.toFloat() / 2
            top = borderWidth.toFloat() / 2
            right = canvas.width.toFloat() - borderWidth.toFloat() / 2
            bottom = canvas.height.toFloat() - borderWidth.toFloat() / 2
        }
        canvas.drawRoundRect(borderRect, cornerRadius - borderWidth.toFloat() / 2, cornerRadius - borderWidth.toFloat() / 2, borderPaint)
    }

    private fun drawWithoutBorder(canvas: Canvas) {
        // Draw transparent area
        transparentPaint.strokeWidth = cornerRadius * 4
        transparentAreaRect.apply {
            left = -cornerRadius * 2
            top = -cornerRadius * 2
            right = canvas.width.toFloat() + cornerRadius * 2
            bottom = canvas.height.toFloat() + cornerRadius * 2
        }
        canvasForDraw?.drawRoundRect(transparentAreaRect, cornerRadius * 3, cornerRadius * 3, transparentPaint)
    }

}

值:

<declare-styleable name="RoundedImageViewWithBorder">
    <attr name="corner_radius" format="dimension|string" />
    <attr name="border_width" format="dimension|reference" />
    <attr name="border_color" format="color|reference" />
</declare-styleable>

答案 4 :(得分:0)

使用卡片视图,然后将半径设置为卡片视图

例如

 <androidx.cardview.widget.CardView
                            android:layout_width="80dp"
                            android:layout_height="80dp"

                            android:layout_gravity="center"
                            app:cardCornerRadius="5dp"
                            >
                
                            <ImageView
                                android:id="@+id/test"
                                android:layout_width="match_parent"
                                android:layout_height="match_parent"
                                android:src="@drawable/logo"
                               />
                       
                        </androidx.cardview.widget.CardView>