Android 如何在具有中心裁剪的自定义图像视图中生成圆形图像?
我想为头像创建自定义图像视图,它可以在两种模式下工作:Android 如何在具有中心裁剪的自定义图像视图中生成圆形图像?,android,kotlin,imageview,android-custom-view,Android,Kotlin,Imageview,Android Custom View,我想为头像创建自定义图像视图,它可以在两种模式下工作: 如果android:src为空,则显示圆圈中有名称的第一个字母 Else显示圆形化身 现在,如果我使用android:src我的drawable不在中心,我如何才能使它成为中心裁剪 以下是自定义视图的代码: class AvatarImageView : AppCompatImageView{ private var letter = "" private var avatarBackgroundColor = 0
class AvatarImageView : AppCompatImageView{
private var letter = ""
private var avatarBackgroundColor = 0
private var avatarLetterColor = 0
private val paintBackground = Paint()
private val paintLetter = Paint(Paint.LINEAR_TEXT_FLAG)
private val paintAvatarImage = Paint()
private var circleX = 0f
private var circleY = 0f
private var circleRadius = 0f
private var letterX = 0f
private var letterY = 0f
private val avatarImageRect = RectF(0f, 0f, 0f, 0f)
constructor(context : Context)
: this(context, null)
constructor(context: Context, attrs : AttributeSet?)
: this(context, attrs, 0)
constructor(context: Context, attrs : AttributeSet?, defStyleAttr : Int)
: super(context, attrs, defStyleAttr){
attrs?.let{
val array = context.obtainStyledAttributes(it, R.styleable.AvatarImageView)
letter = array.getString(R.styleable.AvatarImageView_signature)?.trim()?.substring(0..0)?.toUpperCase(Locale.ROOT) ?: ""
avatarBackgroundColor = array.getColor(R.styleable.AvatarImageView_background_color, Color.BLUE)
avatarLetterColor = array.getColor(R.styleable.AvatarImageView_letter_color, Color.WHITE)
array.recycle()
}
init()
}
private fun init(){
paintBackground.style = Paint.Style.FILL
paintBackground.color = avatarBackgroundColor
paintLetter.color = avatarLetterColor
paintLetter.textAlign = Paint.Align.CENTER
paintLetter.isAntiAlias = true
paintLetter.style = Paint.Style.FILL
drawable?.let{
paintAvatarImage.isAntiAlias = true
val shader = BitmapShader(getBitmapFromDrawable(it), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
paintAvatarImage.shader = shader
}
}
private fun getBitmapFromDrawable(drawable: Drawable): Bitmap{
if (drawable is BitmapDrawable) {
drawable.bitmap?.let {
return drawable.bitmap
}
}
val bitmap: Bitmap = Bitmap.createBitmap(
drawable.intrinsicWidth,
drawable.intrinsicHeight,
Bitmap.Config.ARGB_8888
)
return bitmap
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
val availableWidth = width
val availableHeight = height
circleX = availableWidth / 2f
circleY = availableHeight / 2f
circleRadius = min(availableWidth, availableHeight) / 2f
paintLetter.textSize = availableHeight / 2f
letterX = availableWidth / 2f
letterY = availableHeight / 2f - ((paintLetter.descent() + paintLetter.ascent()) / 2f)
avatarImageRect.right = width.toFloat()
avatarImageRect.bottom = height.toFloat()
}
override fun onDraw(canvas: Canvas?) {
drawable?.let{
canvas?.drawRoundRect(avatarImageRect, width.toFloat(), height.toFloat(), paintAvatarImage)
} ?:run {
canvas?.drawCircle(circleX, circleY, circleRadius, paintBackground)
canvas?.drawText(letter, letterX, letterY, paintLetter)
}
}
}
我的xml文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:padding="16dp"
tools:context=".ui.AvatarsFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.test.test.views.AvatarImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:src="@drawable/avatar"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"
style="@style/TextAppearance.AppCompat.Medium"
android:text="Ivan Ivanov"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="10dp">
<com.test.test.views.AvatarImageView
android:layout_width="32dp"
android:layout_height="32dp"
app:signature="Ivan Ivanov"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"
style="@style/TextAppearance.AppCompat.Medium"
android:text="Ivan Ivanov"/>
</LinearLayout>
</LinearLayout>
更新:我知道其他库,但我不想使用它们。我使用CircleImageView显示图像,毕加索将图像加载到CircleImageView 毕加索将图像居中并裁剪 它对我有用…解决了: 我现在使用此代码从以下位置裁剪图像:
遵循此循环图像视图,我想在没有图书馆的情况下进行此操作这仍然是一个很好的起点。。。该库的代码如下:(您可以提取循环裁剪的相关部分)。
private fun getCircleBitmap(bitmap: Bitmap): Bitmap {
val output = Bitmap.createBitmap(
bitmap.width,
bitmap.height,
Bitmap.Config.ARGB_8888
)
val canvas = Canvas(output)
val color = -0xbdbdbe
val paint = Paint()
val rect = Rect(0, 0, bitmap.width, bitmap.height)
paint.isAntiAlias = true
canvas.drawARGB(0, 0, 0, 0)
paint.color = color
canvas.drawCircle(
bitmap.width / 2f, bitmap.height / 2f,
bitmap.width / 2f, paint
)
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
canvas.drawBitmap(bitmap, rect, rect, paint)
return output
}