|
|
|
@ -8,6 +8,7 @@ import android.graphics.drawable.ColorDrawable |
|
|
|
|
import android.graphics.drawable.Drawable |
|
|
|
|
import android.net.Uri |
|
|
|
|
import android.os.Build |
|
|
|
|
import android.text.TextPaint |
|
|
|
|
import android.util.AttributeSet |
|
|
|
|
import android.view.MotionEvent |
|
|
|
|
import android.view.View |
|
|
|
@ -19,6 +20,7 @@ import androidx.annotation.RequiresApi |
|
|
|
|
import androidx.appcompat.widget.AppCompatImageView |
|
|
|
|
import io.legado.app.R |
|
|
|
|
import io.legado.app.utils.getCompatColor |
|
|
|
|
import io.legado.app.utils.sp |
|
|
|
|
import kotlin.math.min |
|
|
|
|
import kotlin.math.pow |
|
|
|
|
|
|
|
|
@ -31,6 +33,12 @@ class CircleImageView : AppCompatImageView { |
|
|
|
|
private val mBitmapPaint = Paint() |
|
|
|
|
private val mBorderPaint = Paint() |
|
|
|
|
private val mCircleBackgroundPaint = Paint() |
|
|
|
|
private val textPaint by lazy { |
|
|
|
|
val textPaint = TextPaint() |
|
|
|
|
textPaint.isAntiAlias = true |
|
|
|
|
textPaint.textAlign = Paint.Align.CENTER |
|
|
|
|
textPaint |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private var mBorderColor = DEFAULT_BORDER_COLOR |
|
|
|
|
private var mBorderWidth = DEFAULT_BORDER_WIDTH |
|
|
|
@ -105,22 +113,43 @@ class CircleImageView : AppCompatImageView { |
|
|
|
|
setup() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
constructor(context: Context) : super(context) { |
|
|
|
|
private var text: String? = null |
|
|
|
|
|
|
|
|
|
private var textColor = context.getCompatColor(R.color.tv_text_default) |
|
|
|
|
|
|
|
|
|
constructor(context: Context) : super(context) { |
|
|
|
|
init() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@JvmOverloads |
|
|
|
|
constructor(context: Context, attrs: AttributeSet, defStyle: Int = 0) : super(context, attrs, defStyle) { |
|
|
|
|
constructor(context: Context, attrs: AttributeSet, defStyle: Int = 0) : super( |
|
|
|
|
context, |
|
|
|
|
attrs, |
|
|
|
|
defStyle |
|
|
|
|
) { |
|
|
|
|
|
|
|
|
|
val a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0) |
|
|
|
|
|
|
|
|
|
mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_civ_border_width, DEFAULT_BORDER_WIDTH) |
|
|
|
|
mBorderColor = a.getColor(R.styleable.CircleImageView_civ_border_color, DEFAULT_BORDER_COLOR) |
|
|
|
|
mBorderOverlay = a.getBoolean(R.styleable.CircleImageView_civ_border_overlay, DEFAULT_BORDER_OVERLAY) |
|
|
|
|
mBorderWidth = a.getDimensionPixelSize( |
|
|
|
|
R.styleable.CircleImageView_civ_border_width, |
|
|
|
|
DEFAULT_BORDER_WIDTH |
|
|
|
|
) |
|
|
|
|
mBorderColor = |
|
|
|
|
a.getColor(R.styleable.CircleImageView_civ_border_color, DEFAULT_BORDER_COLOR) |
|
|
|
|
mBorderOverlay = |
|
|
|
|
a.getBoolean(R.styleable.CircleImageView_civ_border_overlay, DEFAULT_BORDER_OVERLAY) |
|
|
|
|
mCircleBackgroundColor = |
|
|
|
|
a.getColor(R.styleable.CircleImageView_civ_circle_background_color, DEFAULT_CIRCLE_BACKGROUND_COLOR) |
|
|
|
|
|
|
|
|
|
a.getColor( |
|
|
|
|
R.styleable.CircleImageView_civ_circle_background_color, |
|
|
|
|
DEFAULT_CIRCLE_BACKGROUND_COLOR |
|
|
|
|
) |
|
|
|
|
text = a.getString(R.styleable.CircleImageView_text) |
|
|
|
|
if (a.hasValue(R.styleable.CircleImageView_textColor)) { |
|
|
|
|
textColor = a.getColor( |
|
|
|
|
R.styleable.CircleImageView_textColor, |
|
|
|
|
context.getCompatColor(R.color.tv_text_default) |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
a.recycle() |
|
|
|
|
|
|
|
|
|
init() |
|
|
|
@ -161,20 +190,54 @@ class CircleImageView : AppCompatImageView { |
|
|
|
|
super.onDraw(canvas) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (mBitmap == null) { |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (mCircleBackgroundColor != Color.TRANSPARENT) { |
|
|
|
|
canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mCircleBackgroundPaint) |
|
|
|
|
canvas.drawCircle( |
|
|
|
|
mDrawableRect.centerX(), |
|
|
|
|
mDrawableRect.centerY(), |
|
|
|
|
mDrawableRadius, |
|
|
|
|
mCircleBackgroundPaint |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mBitmapPaint) |
|
|
|
|
canvas.drawCircle( |
|
|
|
|
mDrawableRect.centerX(), |
|
|
|
|
mDrawableRect.centerY(), |
|
|
|
|
mDrawableRadius, |
|
|
|
|
mBitmapPaint |
|
|
|
|
) |
|
|
|
|
if (mBorderWidth > 0) { |
|
|
|
|
canvas.drawCircle(mBorderRect.centerX(), mBorderRect.centerY(), mBorderRadius, mBorderPaint) |
|
|
|
|
canvas.drawCircle( |
|
|
|
|
mBorderRect.centerX(), |
|
|
|
|
mBorderRect.centerY(), |
|
|
|
|
mBorderRadius, |
|
|
|
|
mBorderPaint |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
drawText(canvas) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private fun drawText(canvas: Canvas) { |
|
|
|
|
text?.let { |
|
|
|
|
textPaint.color = textColor |
|
|
|
|
textPaint.textSize = 15.sp.toFloat() |
|
|
|
|
val fm = textPaint.fontMetrics |
|
|
|
|
canvas.drawText( |
|
|
|
|
it, |
|
|
|
|
width * 0.5f, |
|
|
|
|
(height * 0.5f + (fm.bottom - fm.top) * 0.5f - fm.bottom), |
|
|
|
|
textPaint |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fun setTextColor(@ColorInt textColor: Int) { |
|
|
|
|
this.textColor = textColor |
|
|
|
|
invalidate() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { |
|
|
|
|
super.onSizeChanged(w, h, oldw, oldh) |
|
|
|
|
setup() |
|
|
|
@ -249,7 +312,11 @@ class CircleImageView : AppCompatImageView { |
|
|
|
|
BITMAP_CONFIG |
|
|
|
|
) |
|
|
|
|
} else { |
|
|
|
|
Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, BITMAP_CONFIG) |
|
|
|
|
Bitmap.createBitmap( |
|
|
|
|
drawable.intrinsicWidth, |
|
|
|
|
drawable.intrinsicHeight, |
|
|
|
|
BITMAP_CONFIG |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
val canvas = Canvas(bitmap) |
|
|
|
@ -306,7 +373,10 @@ class CircleImageView : AppCompatImageView { |
|
|
|
|
|
|
|
|
|
mBorderRect.set(calculateBounds()) |
|
|
|
|
mBorderRadius = |
|
|
|
|
min((mBorderRect.height() - mBorderWidth) / 2.0f, (mBorderRect.width() - mBorderWidth) / 2.0f) |
|
|
|
|
min( |
|
|
|
|
(mBorderRect.height() - mBorderWidth) / 2.0f, |
|
|
|
|
(mBorderRect.width() - mBorderWidth) / 2.0f |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
mDrawableRect.set(mBorderRect) |
|
|
|
|
if (!mBorderOverlay && mBorderWidth > 0) { |
|
|
|
@ -347,7 +417,10 @@ class CircleImageView : AppCompatImageView { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
mShaderMatrix.setScale(scale, scale) |
|
|
|
|
mShaderMatrix.postTranslate((dx + 0.5f).toInt() + mDrawableRect.left, (dy + 0.5f).toInt() + mDrawableRect.top) |
|
|
|
|
mShaderMatrix.postTranslate( |
|
|
|
|
(dx + 0.5f).toInt() + mDrawableRect.left, |
|
|
|
|
(dy + 0.5f).toInt() + mDrawableRect.top |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
mBitmapShader!!.setLocalMatrix(mShaderMatrix) |
|
|
|
|
} |
|
|
|
|