2014-10-28 11 views
5

Mam bardzo prostą aplikację testową z niestandardowego komponentu MyView.java - który wyświetla przewijalną i skalowalny obraz (reprezentujący pokład w Scrabble jak gra Word):onScale and Canvas - jak ustawić punkt początkowy po powiększeniu obrazu?

Nexus screenshot

1) W moim skalę słuchacza i ustawić współczynnik skali:

public boolean onScale(ScaleGestureDetector detector) { 
    mScale *= detector.getScaleFactor(); 

    // XXX how to adjust mOffsetX and mOffsetY ? XXX 

    constrainZoom(); 
    constrainOffsets(); 
    invalidate(); 
    return true; 
} 

2), a następnie w sposobie rysowania mojego niestandardowego komponentu i zastosowania translacji i skali współczynnika:

protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 

    canvas.translate(mOffsetX, mOffsetY); 
    canvas.scale(mScale, mScale); 
    gameBoard.setBounds(
     0, 
     0, 
     gameBoard.getIntrinsicWidth(), 
     gameBoard.getIntrinsicHeight() 
    ); 
    gameBoard.draw(canvas); 
} 

Niestety, wydaje się, że mały błąd podczas skalowania z gestu pinch -

widzę, że skala i granice są prawidłowej wielkości po powiększanie, ale przesunięcie obrazu nie jest.

Problem się pogarsza, gdy punkt ostrości gestu szczypania znajduje się daleko od 0, 0 punktu ekranu.

Trudno jest opisać problem słowami, ale kiedy się wymeldujesz my test project from GitHub zobaczysz go natychmiast (i zawsze możesz dwukrotnie dotknąć, aby zresetować offset i skalę).

Jest to prawdopodobnie typowy problem ze standardowym sposobem rozwiązania problemu, ale nie udało mi się go jeszcze znaleźć.

Zdjęcie płyty to CC BY-SA by Denelson83, a kod jest oparty na blogu How-to support the fling gesture with a bounce effect.

+1

zamiast canvas.translate/skala/obrócić użyciu macierzy, jego sposób łatwiejsze w użyciu jeden obiekt Matrix, który może być również używany do mapowania pomiędzy dwoma różnymi systemami (Matrix.mapPoints) – pskink

+0

@pskink dlaczego jest lepszy niż przy użyciu macierzysta matryca w płótnie? https://github.com/android/platform_frameworks_base/blob/3bdbf644d61f46b531838558fabbd5b990fc4913/graphics/java/android/graphics/Canvas.java –

+1

zobacz na przykład moją odpowiedź tutaj: http://stackoverflow.com/questions/21633545/android-imageview -skalowanie-i-tłumaczenia-problemu, jak obrazy mogą być skalowane, obracane i tłumaczone, wszystko w jednym kontrolowanym przez jedną Matrix – pskink

Odpowiedz

1

Przenosisz płótno dwa razy: najpierw z translate, a następnie z scale(sx,sy,px,py);.

Możesz połączyć swoje skupienia z przesunięciami w swoim onScale, a następnie użyć scale(sx,sy).

+0

+1 za ten cenny komentarz, ale nie jestem pewien jak połączyć 'offsetX' i' focusX "poprawnie? –

+1

Prawdopodobnie najłatwiej jest ustawić skalę, przesunięcie i ostrość (currentGestureFocus) jako oddzielne zmienne. Następnie śledź fokus przez jeden czas trwania gestu (od 'onScaleBegin' do' onScaleEnd'). W 'onScaleEnd' dodaj fokus do przesunięcia. Podczas gestu powinieneś dodać offset i skupienie na onDraw. Pamiętaj, że ostrość musi być proporcjonalna do bieżącego gestu i środka ekranu. Matrix byłby łatwiejszy, ponieważ lepiej radzi sobie z łańcuchem, ale wymuszanie granic jest trudniejsze. Mam nadzieję, że to ma sens. – mikkokoo

Powiązane problemy