According to this topic: How to override method in library?
I would like to override some methods and variables from InkView
.
Is it possible? :)
I have created class:
class MyInkView: InkView {
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int = 0): super(context, attrs, defStyleAttr)
constructor(context: Context, attrs: AttributeSet): super(context, attrs)
constructor(context: Context): super(context)
// include any other constructors you need based on the ones in the superclass
var bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
// clean up existing bitmap
if (bitmap != null) {
bitmap.recycle()
}
// init bitmap cache
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
canvas = Canvas(bitmap)
// notify listeners
for (listener in listeners) {
listener.onInkClear()
}
invalidate()
isEmpty = true
}
}
Of course it gives some error of accidental overrides:
Accidental override: The following declarations have the same JVM signature (getBitmap()Landroid/graphics/Bitmap;):
Cannot access 'canvas': it is invisible (private in a supertype) in 'MyInkView'
Cannot access 'listeners': it is invisible (private in a supertype) in 'MyInkView'
Entire InkView
https://justpaste.it/27rn0
If I make it empty it doesn't create any bitmap and I have error with this.
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.isRecycled()' on a null object reference
1 EDIT:
I make this function:
fun getBitmap(backgroundColor: Int, lineColor: Int): Bitmap? {
val currentPaint: Paint = readPrivateField("paint") ?: return null
val linePaint = Paint(currentPaint)
linePaint.colorFilter = PorterDuffColorFilter(lineColor, PorterDuff.Mode.SRC_IN)
val currentBitmap: Bitmap = readPrivateField("bitmap") ?: return null
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val bitmapCanvas = Canvas(bitmap)
bitmapCanvas.drawColor(backgroundColor)
bitmapCanvas.drawBitmap(currentBitmap, 0f, 0f, linePaint)
return bitmap
}
Previously without custom class view it worked like this in .extension
:
fun InkView.getBitmap(backgroundColor: Int, lineColor: Int): Bitmap? {
val currentPaint: Paint = readPrivateField("paint") ?: return null
val linePaint = Paint(currentPaint)
linePaint.colorFilter = PorterDuffColorFilter(lineColor, PorterDuff.Mode.SRC_IN)
val currentBitmap: Bitmap = readPrivateField("bitmap") ?: return null
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val bitmapCanvas = Canvas(bitmap)
bitmapCanvas.drawColor(backgroundColor)
bitmapCanvas.drawBitmap(currentBitmap, 0f, 0f, linePaint)
return bitmap
}
Unfortunately it make crash during saving this bitmap.
Caused by: java.lang.NoSuchFieldException: No field paint in class Lcom/application/core/view/MyInkView; (declaration of 'com.application.core.view.MyInkView' appears in base.apk!classes2.dex)
at java.lang.Class.getDeclaredField(Native Method)
at com.application.core.view.MyInkView.getBitmap(MyInkView.kt:50)
That's where this error occurs:
inline fun <T : Any, reified R> T.readPrivateField(name: String): R? {
val field = javaClass.getDeclaredField(name) -<<<< CRASH
field.isAccessible = true
val result = field.get(this) as? R
field.isAccessible = false
return result
}
CodePudding user response:
Here's how I'd attempt what you described in the comments. It disables the clear()
function, but allows you to manually clear it by calling forceClear()
.
class MyInkView: InkView {
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int = 0): super(context, attrs, defStyleAttr)
constructor(context: Context, attrs: AttributeSet): super(context, attrs)
constructor(context: Context): super(context)
override fun clear() {}
fun forceClear() = super.clear()
}
However, I suspect you actually need to allow it to clear if the view truly changes size, because otherwise the bitmap will be the wrong size for the view. I would do this instead, exit the function early when the size has not actually changed. Also ignore sizes of 0 in case there's ever a transitionary size 0 state.
class MyInkView: InkView {
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int = 0): super(context, attrs, defStyleAttr)
constructor(context: Context, attrs: AttributeSet): super(context, attrs)
constructor(context: Context): super(context)
private var lastAcceptedWidth = -1
private var lastAcceptedHeight = -1
private var preventClear = false;
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
preventClear = (w == lastAcceptedWidth && h == lastAcceptedHeight) || w == 0 || h == 0
if (!preventClear) {
lastAcceptedWidth = w
lastAcceptedHeight = h
}
super.onSizeChanged(w, h, oldw, oldh)
preventClear = false
}
override fun clear() {
if (!preventClear) super.clear()
}
}