Stiamo costruendo un'applicazione Android che comporta l'editing delle immagini. Alcune delle funzioni includono la rotazione di un'immagine e la cancellazione di parte dell'immagine.La cancellazione di un'immagine ruotata in Android non mostra la cancellazione del percorso corretto
Stiamo utilizzando la seguente libreria: https://github.com/nimengbo/StickerView
abbiamo creato con successo una funzione per ruotare e cancellare l'immagine. Tuttavia, quando abbiamo provato a eseguire le seguenti azioni:
- Rotazione di un'immagine in una certa misura.
- Quindi, cancellando l'immagine.
Abbiamo trovato il seguente errore:
- Quando abbiamo cercato di cancellare l'immagine ruotata, il percorso cancellato non rifletteva il percorso che il nostro dito tracciato sullo schermo.
dall'immagine qui sopra, la linea gialla è il movimento reale del dito (verso il basso verticale attraverso l'adesivo). Ma, il percorso cancellato risultante è stato trovato per essere diagonale.
Questo problema esiste solo quando l'immagine viene ruotata. Non esiste quando l'immagine non viene ruotata.
Dopo ulteriore debugging, abbiamo alcune assunzioni dai problemi di cui sopra:
- causa dell'immagine ruotata, x ed y posizione assoluzione viene cambiata. Pertanto, il percorso non riflette il percorso corretto per le rotte tattili.
Come possiamo garantire che il percorso stia ancora facendo riferimento al percorso corretto su ciò che il dito sta toccando anche dopo essere stato ruotato?
Ecco il codice che abbiamo nella nostra classe StickerView.java
che estende la classe ImageView
.
onTouchEvent
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = MotionEventCompat.getActionMasked(event);
float[] pointXY = new float[2];
pointXY = getAbsolutePosition(event.getX(0),event.getY(0));
float xPoint = pointXY[0];
float yPoint = pointXY[1];
switch (action) {
case MotionEvent.ACTION_DOWN:
// first touch
// if it is inside the image
if (isInBitmap(event)) {
// set isInSide to true
isInSide = true;
// if it is a scratch
if(doScratch){
// start creating the scratch path
mScratchPath = new Path();
mScratchPath.moveTo(xPoint, yPoint);
mScratchPath.lineTo(xPoint, yPoint);
paths.add(new Pair<Path, Paint>(mScratchPath, mScratchCurrentPaint));
}
}
break;
case MotionEvent.ACTION_MOVE:
// if two fingers touch and is not a scratch,
// then it means we can rotate/resize/pan
if (isPointerDown && !doScratch) {
// reset matrix
matrix.reset();
// get the center point
scaledImageCenterX = (mImageWidth * mScaleFactor)/2 ;
scaledImageCenterY = (mImageHeight * mScaleFactor)/2;
// ROTATE THE IMAGE !!!
matrix.postRotate(lastRotateDegree, scaledImageCenterX, scaledImageCenterY);
// done to call onDraw
invalidate();
}
break;
}
if (operationListener != null) {
operationListener.onEdit(this);
}
// if it is a scratch
if(doScratch){
// then for every point, create a scratch path
mScratchPath.lineTo(xPoint, yPoint);
invalidate();
}else{
mScaleDetector.onTouchEvent(event);
mRotateDetector.onTouchEvent(event);
mMoveDetector.onTouchEvent(event);
mShoveDetector.onTouchEvent(event);
}
return handled;
}
OnDraw
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// if the image exists
if (mBitmap != null) {
// save canvas
canvas.save();
// if it is a scratch
if(doScratch){
// scratch the image
mFillCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
// Draw our surface, nice an pristine
final Drawable surface = mScratchSurface;
if(surface != null) {
surface.draw(mFillCanvas);
}
//Scratch the surface
if(paths != null) {
for (Pair<Path, Paint> p : paths) {
mFillCanvas.drawPath(p.first,p.second);
}
}
mBitmap = mFillCache;
}
canvas.drawBitmap(mBitmap, matrix, bitmapPaint);
canvas.restore();
}
}
funzione getAbsolutePosition
public float[] getAbsolutePosition(float Ax, float Ay) {
float[] mMatrixValues = new float[9];
matrix.getValues(mMatrixValues);
float x = mImageWidth - ((mMatrixValues[Matrix.MTRANS_X] - Ax)/mMatrixValues[Matrix.MSCALE_X]) - (mImageWidth - getTranslationX());
float y = mImageHeight - ((mMatrixValues[Matrix.MTRANS_Y] - Ay)/mMatrixValues[Matrix.MSCALE_X]) - (mImageHeight - getTranslationY());
return new float[] { x, y};
}
Dove devo applicare la matrice di rotazione? È nella posizione di onTouchEvent? O alla funzione getAbsolutePosition? –
Supponiamo che theta è l'angolo con cui è stato ruotato imageView. Quindi abbiamo bisogno di ruotare la posizione di cancellazione (o la posizione di tocco in corso) per (-theta) i.e negativo di theta. Per fare ciò applicare la trasformazione sul luogo in cui l'utente tocca lo schermo usando (-theta) e quindi cancellare le coordinate ottenute come risultato da imageView. –
È possibile calcolare l'intero percorso di cancellazione, in primo luogo, senza applicare alcuna trasformazione. Quindi, una volta calcolato l'intero percorso, è possibile applicare la trasformazione su tutto il percorso e ottenere un percorso risultante. Quindi cancella questo percorso trasformato dall'immagine –