2011-11-11 12 views
12

Ho una vista personalizzata in cui utilizzo le trasformazioni. Fin qui tutto bene, funzione come setRotationY(), setScaleX(), setTranslationY() o anche getMatrix() funzionano come previsto, sono in grado di manipolare la mia vista e viene visualizzata correttamente. Il punto in cui colpisco il muro è che un certo numero di funzioni si comporta stranamente dopo di ciò. Ad esempio, funzione come getHitRect() restituisce valori assolutamente strani! Questo non sta aiutando i miei eventi touch.Come ottenere i limiti corretti di una vista dopo la trasformazione Matrix

Ho provato a sovraccaricare la funzione, ma è ancora lontano dal lavorare in particolare quando si utilizza la rotazione o il ridimensionamento (Traduzione che funziona bene attraverso). Penso che questo sia qualcosa a che fare con il fatto che la matrice è espressa in coordinate figlio, quindi come posso farlo coordinare nei genitori?

@Override 
    public void getHitRect(Rect outRect){ 

     RectF rect = new RectF(); 
     rect.top = (float) this.getTop(); 
     rect.bottom = (float) this.getBottom(); 
     rect.left = (float) this.getLeft(); 
     rect.right = (float) this.getRight();  

    this.getMatrix().mapRect(rect); 
     rect.round(outRect); 
    } 

Posso ottenere un valore più diretto direttamente da qualche funzione? Come la nuova altezza, larghezza, superiore o inferiore.

risposta

8

Quando l'override del metodo “getChildStaticTransformation” del ViewGroup o anche utilizzando la funzione di trasformazione come setRotationY(), setScaleX(), setTranslationY(), getMatrix() (disponibile da API 11) si sta interessando solo Matrix rendering. Di conseguenza, la tua Child View personalizzata restituirà i "Rects" dei Bounds lontano da dove il tuo bambino sta ottenendo un pareggio. Questo non è un problema la maggior parte delle volte, ma quando inizi a essere disposto a fare clic su di esso ... i problemi stanno iniziando ... Ecco come risolvo il problema. Sono sicuro che potrebbero esserci modi migliori, ma poiché non ho trovato molte cose sull'argomento, eccolo qui.

Nella ViewGroup sovraccarico:

public interface Itransformable { 
    public void setTransformationMatrix(Matrix trsMatrix); 
} 

@Override 
protected boolean getChildStaticTransformation(View child, Transformation t) { 
    if (child instanceof Itransformable){ 
     t.clear(); 
     t.setTransformationType(Transformation.TYPE_MATRIX); 
     ... 
     // Do whatever transformation you want here 
     ... 
     ((Itransformable)child).setTransformationMatrix(t.getMatrix()); 
     return true; 
    } else { 
     return false; 
    } 
} 

Ecco il Bambino visualizzazione personalizzata: Si noti che non sto memorizzare direttamente la matrice di trasformazione nella visualizzazione personalizzata, ma invece trasformata Rect. Se vuoi andare a memorizzare la matrice (vale a dire per la trasformazione successiva come punto ...) potresti doverla clonare poiché la matrice verrà alterata in qualche modo strano come se fosse riciclata o qualcosa del genere.

public class MyCustomView extends View implements MyViewGroup.Itransformable{ 

private Rect mViewRect = null; 

public void setTransformationMatrix(Matrix trsMatrix){ 
    if (trsMatrix!=null){ 
     RectF rect = new RectF(); 
     rect.top = 0; 
     rect.bottom = (float) this.getHeight(); 
     rect.left = 0; 
     rect.right = (float) this.getWidth(); 

     trsMatrix.mapRect(rect); 
     rect.offset((float) this.getLeft(), (float) this.getTop()); 

     if (mViewRect == null) mViewRect = new Rect(); 
     rect.round(mViewRect); 
    } 
} 

public Rect getTransformatedRect() { 
    if (mViewRect!=null){ 
     // OutOfScreen WorkArround - As the view is not Displayed, mViewRect doesn't get updated. 
     if(getRight() < 0 || getLeft() > mParentWidth){ 
      return new Rect(getLeft(),getTop(),getRight(),getBottom()); 
     } else { 
      return mViewRect; 
     } 
    } else { 
     return new Rect(getLeft(),getTop(),getRight(),getBottom()); 
    } 
} 

@Override 
public void getHitRect(Rect outRect){ 

    if (mViewRect == null){ 
     super.getHitRect(outRect); 
    } else { 
     outRect.set(getTransformatedRect()); 
    } 
} 
+0

grazie mille per la risposta, mi aiuta :) –

+0

Un'altra cosa per Android> = 4.0: 'getHitRect()' non sarà chiamato automaticamente se si sta cliccando sul tuo punto di vista. Per aggiungere compatibilità per i progetti che utilizzano SDK <4.0, l'uso di 'isTransformedTouchPointInView()' su genitore funziona anche se non è perfetto. –

Problemi correlati