创建了CircleImageView,扩展了NetworkImageView,并使用on布局从url动态显示圆形图像。但是在xml布局中,它提供了“ InflateException”二进制XML文件。
我使用的布局:
<com.xxxx.xxxxx.utility.CircleImageView
android:id="@+id/img"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginStart="2dp"
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp"
android:scaleType="fitCenter"
android:background="@drawable/rounded_all_blue"/>
kotlin中的CircleImageView类文件:
1)CircleImageView:
class CircleImageView : NetworkImageView {
private val SCALE_TYPE = ScaleType.CENTER_CROP
private val BITMAP_CONFIG = Bitmap.Config.ARGB_8888
private val COLORDRAWABLE_DIMENSION = 2
private val DEFAULT_BORDER_WIDTH = 0
private val DEFAULT_BORDER_COLOR = Color.BLACK
private val DEFAULT_BORDER_OVERLAY = false
private val mDrawableRect = RectF()
private val mBorderRect = RectF()
private val mShaderMatrix = Matrix()
private val mBitmapPaint = Paint()
private val mBorderPaint = Paint()
private var mBorderColor = DEFAULT_BORDER_COLOR
private var mBorderWidth = DEFAULT_BORDER_WIDTH
private var mBitmap: Bitmap? = null
private var mBitmapShader: BitmapShader? = null
private var mBitmapWidth: Int = 0
private var mBitmapHeight: Int = 0
private var mDrawableRadius: Float = 0.toFloat()
private var mBorderRadius: Float = 0.toFloat()
private var mColorFilter: ColorFilter? = null
private var mReady: Boolean = false
private var mSetupPending: Boolean = false
private var mBorderOverlay: Boolean = false
constructor(context:Context) : super(context) {
init()
}
private fun init() {
super.setScaleType(SCALE_TYPE)
mReady = true
if (mSetupPending) {
setup()
mSetupPending = false
}
}
override fun getScaleType(): ImageView.ScaleType {
return SCALE_TYPE
}
override fun setScaleType(scaleType: ImageView.ScaleType) {
if (scaleType != SCALE_TYPE) {
throw IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType))
}
}
override fun setAdjustViewBounds(adjustViewBounds: Boolean) {
if (adjustViewBounds) {
throw IllegalArgumentException("adjustViewBounds not supported.")
}
}
override fun onDraw(canvas: Canvas) {
if (drawable == null) {
return
}
canvas.drawCircle((width / 2).toFloat(), (height / 2).toFloat(), mDrawableRadius, mBitmapPaint)
if (mBorderWidth !== 0) {
canvas.drawCircle((width / 2).toFloat(), (height / 2).toFloat(), mBorderRadius, mBorderPaint)
}
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
setup()
}
fun getBorderColor(): Int {
return mBorderColor
}
fun setBorderColor(borderColor: Int) {
if (borderColor == mBorderColor) {
return
}
mBorderColor = borderColor
mBorderPaint.color = mBorderColor
invalidate()
}
fun setBorderColorResource(@ColorRes borderColorRes: Int) {
setBorderColor(context.resources.getColor(borderColorRes))
}
fun getBorderWidth(): Int {
return mBorderWidth
}
fun setBorderWidth(borderWidth: Int) {
if (borderWidth == mBorderWidth) {
return
}
mBorderWidth = borderWidth
setup()
}
fun isBorderOverlay(): Boolean {
return mBorderOverlay
}
fun setBorderOverlay(borderOverlay: Boolean) {
if (borderOverlay == mBorderOverlay) {
return
}
mBorderOverlay = borderOverlay
setup()
}
override fun setImageBitmap(bm: Bitmap) {
super.setImageBitmap(bm)
mBitmap = bm
setup()
}
override fun setImageDrawable(drawable: Drawable?) {
super.setImageDrawable(drawable)
mBitmap = getBitmapFromDrawable(drawable)
setup()
}
override fun setImageResource(@DrawableRes resId: Int) {
super.setImageResource(resId)
mBitmap = getBitmapFromDrawable(drawable)
setup()
}
override fun setImageURI(uri: Uri) {
super.setImageURI(uri)
mBitmap = getBitmapFromDrawable(drawable)
setup()
}
override fun setColorFilter(cf: ColorFilter) {
if (cf === mColorFilter) {
return
}
mColorFilter = cf
mBitmapPaint.colorFilter = mColorFilter
invalidate()
}
private fun getBitmapFromDrawable(drawable: Drawable?): Bitmap? {
if (drawable == null) {
return null
}
if (drawable is BitmapDrawable) {
return drawable.bitmap
}
try {
val bitmap: Bitmap
if (drawable is ColorDrawable) {
bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG)
} else {
bitmap = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, BITMAP_CONFIG)
}
val canvas = Canvas(bitmap)
drawable.setBounds(0, 0, canvas.width, canvas.height)
drawable.draw(canvas)
return bitmap
} catch (e: OutOfMemoryError) {
return null
}
}
private fun setup() {
if (!mReady) {
mSetupPending = true
return
}
if (mBitmap == null) {
return
}
mBitmapShader = BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
mBitmapPaint.isAntiAlias = true
mBitmapPaint.shader = mBitmapShader
mBorderPaint.style = Paint.Style.STROKE
mBorderPaint.isAntiAlias = true
mBorderPaint.color = mBorderColor
mBorderPaint.setStrokeWidth(mBorderWidth.toFloat())
mBitmapHeight = mBitmap!!.height
mBitmapWidth = mBitmap!!.width
mBorderRect.set(0F, 0F, width.toFloat(), height.toFloat())
mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, (mBorderRect.width() - mBorderWidth) / 2)
mDrawableRect.set(mBorderRect)
if (!mBorderOverlay) {
mDrawableRect.inset(mBorderWidth.toFloat(), mBorderWidth.toFloat())
}
mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2)
updateShaderMatrix()
invalidate()
}
private fun updateShaderMatrix() {
val scale: Float
var dx = 0f
var dy = 0f
mShaderMatrix.set(null)
if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {
scale = mDrawableRect.height() / mBitmapHeight as Float
dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f
} else {
scale = mDrawableRect.width() / mBitmapWidth as Float
dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f
}
mShaderMatrix.setScale(scale, scale)
mShaderMatrix.postTranslate((dx + 0.5f).toInt() + mDrawableRect.left, (dy + 0.5f).toInt() + mDrawableRect.top)
mBitmapShader?.setLocalMatrix(mShaderMatrix)
}
}
2)动态调用图像的方法
fun loadImage(url:String, avatar: CircleImageView){
val imageLoader: ImageLoader by lazy {
ImageLoader(ApiConnect.instance.requestQueue, LruBitmapCache())
}
avatar.setImageUrl(url,imageLoader);
}
3)我们可以加载图像
APIController().loadImage(imageurlpath,holder.img)
当我使用“ NetworkImageView”时图像显示,但问题是它不适合圆形,我已经阅读并将“ CircleImageView”转换为kotlin并使用过,但是它给出了错误,请帮忙。
//错误日志:
2019-07-05 18:29:20.721 21385-21385/com.xxxx.xxxxxx E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.xxxx.xxxxxx, PID: 21385
android.view.InflateException: Binary XML file line #11: Binary XML file line #11: Error inflating class com.xxxx.xxxxxx.utility.CircleImageView
Caused by: android.view.InflateException: Binary XML file line #11: Error inflating class com.xxxx.xxxxx.utility.CircleImageView
Caused by: java.lang.NoSuchMethodException: <init> [class android.content.Context, interface android.util.AttributeSet]
at java.lang.Class.getConstructor0(Class.java:2327)
at java.lang.Class.getConstructor(Class.java:1725)
答案 0 :(得分:0)
问题是您的自定义视图不能正确覆盖必要的构造函数。该错误为NoSuchMethodException
,因为应该使用具有Context
和AttributeSet
的构造函数。这不存在。
您可以创建此构造函数并调用super(context, attributeSet)
或使用JvmOverload
批注。
因此,您可以像这样实现构造函数:
class CustomView : View {
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) {
//do stuff
}
}
或使用如下注释:
class CustomView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
}