Utknąłem w tym problem przez osiem godzin, więc pomyślałem, że nadszedł czas, aby uzyskać pomoc.Canvas Pinch-Zoom do punktu w granicach
Zanim zacznę mój problem, dam znać, że przeszedłem przez tę stronę i Google, i żadna z odpowiedzi, które znalazłem, nie pomogła. (This jest jeden, another i another.)
Oto oferta: Mam klasy, która rozciąga SurfaceView
(nazwijmy go MySurface
) i zastępuje wiele metod w nim. Zwykle rysuje kilka kwadratów i pól tekstowych, co jest w porządku. Gdy tylko użytkownik zacznie się dotykać, konwertuje na Bitmap
, a następnie rysuje każdą klatkę, aż użytkownik zwolni.
Oto pocieranie: chcę zaimplementować taką funkcjonalność, że użytkownik może umieścić dwa palce na ekranie, uszczypnąć, aby powiększyć, a także przesuwać (ale TYLKO dwoma palcami w dół).
znalazłem kilka implementacje pinch-to-zoom i dostosować je do mojego Canvas
obiektu w MySurface
poprzez następujący:
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.scale(mScaleVector.z, mScaleVector.z); // This is the scale factor as seen below
canvas.translate(mScaleVector.x, mScaleVector.y); // These are offset values from 0,0, both working fine
// Start draw code
// ...
// End draw code
canvas.restore();
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
float factor = detector.getScaleFactor();
if (Math.abs(factor - 1.0f) >= 0.0075f) {
mScaleVector.z *= factor;
mScaleVector.z = Math.max(MIN_ZOOM, Math.min(mScaleVector.z, MAX_ZOOM));
}
// ...
invalidate();
return true;
}
}
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;
int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
if (event.getPointerCount() == 2) {
if (action == MotionEvent.ACTION_POINTER_DOWN && pointerIndex == 1) {
// The various pivot coordinate codes would belong here
}
}
detector.onTouchEvent(event); // Calls the Scale Gesture Detector
return true;
}
Chociaż oba elementy działają dobrze - przewijanie w przód iw tył, a pinch -to-zoom - jest jeden duży problem. Przybliżanie do powiększenia, gdy jest używane, powoduje powiększenie do punktu 0,0
zamiast przybliżania palcem.
Próbowałem wiele sposobów, aby rozwiązać ten problem:
- Korzystanie
canvas.scale(mScaleVector.z, mScaleVector.z, mScaleVector.x, mScaleVector.y);
; oczywiście, powoduje to niepożądane wyniki, ponieważ wartości xiy są wartościami zerowymi. - Zarządzanie współrzędną "przestawną", która używa tego samego przesunięcia co metoda
translate()
, ale powoduje to ten sam problem z numerem0,0
lub przeskakiwanie po dotknięciu widoku. - Wiele innych rzeczy ... Dużo zrobiłem z wyżej wymienioną współrzędną obrotu, próbując oprzeć swoją lokalizację na pierwszym dotknięciu użytkownika i przesuwając ją względem tego dotknięcia każdego kolejnego gestu.
Dodatkowo to płótno musi być ograniczone, aby użytkownik nie mógł przewijać na zawsze. Jednak, gdy używam metody .scale(sx, sy, px, py)
, powoduje ona przesunięcie elementów poza wszelkie granice ustawione w .translate()
.
Jestem ... całkiem otwarty na wszystko w tym momencie. Wiem, że tę funkcjonalność można dodać, co widać w galerii systemu Android 4.0 (podczas oglądania pojedynczego obrazu). Próbowałem wyśledzić kod źródłowy, który to obsługuje, bez skutku.
Osobiście obsługuję pozycje dwóch palców bezpośrednio za pomocą 'onTouchEvent'. Dzięki temu można łatwo znaleźć punkt środkowy i ile skalowania jest wymagane. – Doomsknight
Czy możesz opublikować rozwiązanie, jeśli rozwiązałeś problem, z którym się borykam, a mój klient jest .... :(, czy możesz mi powiedzieć, jak rozwiązałeś problem, dziękuję – AkashG