2015-05-03 32 views
5

Próbuję pokazać obrazy w widoku pełnoekranowym i stosując następujący kod:pobierania obrazu i zmiany rozmiaru w celu uniknięcia błędów OOM, Picasso Fit() zniekształca obraz

// Target to write the image to local storage. 
Target target = new Target() { 
    // Target implementation. 
} 

// (1) Download and save the image locally. 
Picasso.with(context) 
     .load(url) 
     .into(target); 

// (2) Use the cached version of the image and load the ImageView. 
Picasso.with(context) 
     .load(url) 
     .into(imgDisplay); 

ten kod działa dobrze w nowszych telefonach ale na telefonach z maszynami wirtualnymi 32MB, mam problemy z pamięcią. Tak więc próbowałem zmienić (2) na:

Picasso.with(context) 
     .load(url) 
     .fit() 
     .into(imgDisplay); 

Doprowadziło to do zniekształcenia obrazów. Ponieważ nie wiem, wymiary obrazu, dopóki nie zostanie pobrana, nie mogę ustawić wymiary ImageView, a więc obraz jest zmieniany bez rozpatrzenia proporcjami w moim ImageView:

<ImageView 
    android:id="@+id/imgDisplay" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:scaleType="fitCenter" 
    android:layout_alignParentTop="true" 
    android:layout_alignParentLeft="true" 
    android:layout_alignParentStart="true" /> 

Co jest najlepszy sposób na poradzenie sobie z tą sytuacją? Moje oryginalne obrazy mają maksymalną szerokość 768 i wysokość 1024, i chcę obniżyć próbę, gdy ekrany są znacznie mniejsze. Jeśli spróbuję użyć resize(), mój kod staje się skomplikowany, ponieważ muszę czekać (1), aby zakończyć pobieranie, a następnie dodać resize() w (2).

Zakładam, że transformacje nie pomagają w tym przypadku, ponieważ dane wejściowe do public Bitmap transform(Bitmap source) będą już miały dużą bitmapę, co spowoduje, że zabraknie mi pamięci.

Odpowiedz

5

Można łączyć fit() z centerCrop() lub centerInside(), w zależności od tego, jak chcesz obraz, aby dopasować swoją View:

Picasso.with(context) 
    .load(url) 
    .fit() 
    .centerCrop() 
    .into(imgDisplay); 

Picasso.with(context) 
    .load(url) 
    .fit() 
    .centerInside() 
    .into(imgDisplay); 
+1

To działa! Zostałem odrzucony przez dokumentację, która spowodowała, że ​​pomyślałem, że 'centerInside()' musi być używane z 'resize()' [From Doc] (https://square.github.io/picasso/javadoc/com/ squareup/picasso/RequestCreator.html # centerInside--): 'Wyśrodkowuje obraz wewnątrz granic określonych przez zmianę rozmiaru (int, int). To skaluje obraz tak, że oba wymiary są równe lub mniejsze niż wymagane granice. " – wislo

+0

Wiem, że jest to powszechny błąd i doktorzy nie są tego świadomi. FYI, 'fit()' tylko czeka, aż View zdobędzie jego wymiary, ale w rzeczywistości nic nie ** skali ** obrazu do tego rozmiaru – Sebastiano

+0

[fit()] (https://square.github.io/picasso /javadoc/com/squareup/picasso/RequestCreator.html#fit--) mówi 'Próba zmiany rozmiaru obrazu tak, aby dokładnie pasowała do granic docelowego ImageView. Więc czy nie skaluje mapy bitowej? Jestem nieco zdezorientowany twoim ostatnim komentarzem. Chcę upewnić się, że próbkowanie w dół zostało wykonane i ładuję poprawnie dobraną bitmapę, aby uniknąć marnowania pamięci. Jaki jest najlepszy sposób na zrobienie tego? BTW, mam kolejną 'View' w mojej aplikacji, która ma stały wymiar NxN, gdzie użyłem' fit() 'wraz z' centerCrop() 'przy założeniu, że nastąpi downsampling. – wislo