1 komentarz

NinePatch – bezstratne skalowanie elementów graficznych

Lipiec 29, 2011 Kompatybilność Narzędzia Tutoriale UI

Czy kiedykolwiek zastanawiałeś się w jaki sposób zrealizowany jest mechanizm wyświetlania typowych przycisków w Androidzie? Co sprawia, że niezależnie od rozmiaru, ciągle są tak samo „gładkie” i nigdzie nie widać efektów przeskalowania grafiki?
Na pewno obrazki tego typu nie są rysowane przez system. Nie ma też żadnej ogromnej bazy plików graficznych z różnymi rozmiarami. :) Jest za to bardzo prosty mechanizm, który nazywa się NinePatch. I to jemu poświęcimy dzisiejszy wpis.

Czym jest NinePatch

NinePatch to plik rastrowy graficzny, który od zwykłego obrazka PNG różni się dwoma rzeczami. Pierwszą jest jego nazwa, która powinna wyglądać w ten sposób – <nazwa pliku>.9.png. Drugą jest jednopikselowa ramka, która stanowi informację o miejscach obrazka podatnych na bezproblemowe rozciąganie.
Domyślam się, że powyższy opis może być nieco enigmatyczny dlatego poniżej przygotowałem przykład, który pozwoli dobrze zrozumieć ideę NinePatch.

Tworzenie NinePatch

Proces tworzenia obrazków NinePatch jest niezwykle prosty. Wystarczy, że przygotujemy obrazek, który chcielibyśmy skalować. Oczywiście musi on posiadać choćby najmniejszy obszar, który można powielać zarówno w pionie jak i w poziomie.
Oto przykładowy plik z jakiego będę korzystał:

Aby dodać do niego wspomnianą ramkę wystarczy skorzystać z niewielkiej aplikacji Draw 9-patch, którą dostarcza nam Android SDK. Możemy ją znaleźć albo w folderze \tools\draw9patch.bat, albo uruchomić z linii komend wpisując draw9patch (pod warunkiem, że folder tools mamy dopisany do zmiennej środowiskowej PATH).
Po jej uruchomieniu i załadowaniu pliku powinniśmy zobaczyć takie okno:

Interfejs aplikacji składa się z kilku elementów. Poniżej, na pasku mamy dwa suwaki:

  • Zoom do przybliżania widoku głównego okna,
  • Patch scale, do powiększania przeskalowanych przykładów zawartych w oknie obok.

Oraz trzy checkboxy:

  • Show lock – pokazuje nam obszar obrazka po którym nie możemy rysować (do rysowania przeznaczony jest jednopikselowy obszar wokół obrazka)
  • Show patches – zaznacza na różowo część obrazka, która będzie skalowana. Jak widać, na razie jest to cały obrazek (a efekt takiego skalowania widzimy w oknie obok).
  • Show content – W oknie obok, na niebiesko zaznacza obszar „użytkowy” obrazka.

Ostatnią rzeczą jest przycisk Hide/Show bad patches powyżej głównego okna, który ukazuje nam obszar, który może sprawić problemy podczas skalowania (czerwona ramka).

Na obrazku możemy zaznaczyć cztery obszary (każdy na innej krawędzi obrazka):

Linie u góry oraz po lewej stronie obrazka wskazują miejsca, które mogą być rozciągane. Dzięki nim system wie jakie partie mogą być powielana, a jakie nie. I tym też sposobem rozciągając „środek” pozostawiamy nietknięte zaokrąglone brzegi lub jakieś inne niestandardowe elementy.
Linie po prawej oraz na dole obrazka wskazują obszar przeznaczony na treść. Dzięki temu, zamiast edytować atrybuty padding w pliku XML, możemy już na poziomie edycji pliku zaznaczyć granice „contentu”.

Po zapisaniu powyższych modyfikacji powinniśmy uzyskać mniej więcej coś takiego:

Wykorzystanie obrazków NinePatch

Z plików *.9.png w systemie Android korzystamy dokładnie tak samo jak z wszystkich innych. Warunkiem wykorzystania zrobionej przez nas ramki jest jedynie umieszczenie ich w folderze /res/drawable/ oraz nadanie nazwy zgodnie z konwencją.
Aby od razu przejść do rzeczy – należy założyć nowy projekt i od razu przejść do edycji pliku XML (plik java głównej Aktywności w tym przykładzie pozostanie nieruszony).

Aby zaprezentować jak działa skalowanie stworzonego przez nas obrazka tworzymy 4 buttony. Trzy z nich w atrybucie android:background będą miały ustawiony obrazek NinePatch, czwarty natomiast zwykły obrazek:

<Button
    android:id="@+id/Button01"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/btn_bg"
    android:textSize="5sp"
    android:text="TextSize = 5sp" />
<Button
    android:id="@+id/Button02"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/btn_bg"
    android:textSize="15sp"
    android:text="TextSize = 15sp" />
<Button
    android:id="@+id/Button03"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/btn_bg_notnine"
    android:padding="30dp"
    android:text="Not NinePatch Image"
    android:textSize="20sp" />
<Button
    android:id="@+id/Button04"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/btn_bg"
    android:text="TextSize = 50sp"
    android:textSize="40sp" />

Jak widać, każdy z nich ma inną wielkość czcionki. Spowoduje to rozciągnięcie obrazka do takich rozmiarów by pomieścić cały napis.

Dodatkowo zademonstruję też działanie ramki wskazującej miejsce na zawartość dodając poniższy kod do naszego layoutu:

<RelativeLayout
    android:id="@+id/RelativeLayout01"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/btn_bg">
    <TextView
        android:id="@+id/TextView01"
        android:layout_height="fill_parent"
        android:layout_width="fill_parent"
        android:textColor="#FFFFFF"
        android:background="#000000"
        android:text="Padding presentation (text background fill all free space)"
        android:padding="10dp" />
</RelativeLayout>

Pole RelativeLayout zostanie pokryte naszym obrazkiem NinePatch, natomiast znajdujące się węwnątrz pole TextView swoją czarną tapetą pokryje cały dostępny mu obszar. Jak można zauważyć na poniższym zrzucie ekranu – obszar ten jest dokładnie tym, na co wskazywał edytor Draw 9-patch w swoim bocznym oknie.

Komentarze (1) Subskrybuj

 

  1. [...] Wygląd widżetu definiujemy dokładnie tak samo jak wygląd całej aplikacji, czyli w pliku XML. W związku z tym w folderze /res/layout/ tworzymy nowy plik (np. poprzez prawy klik na projekt -> new -> Other -> Andorid XML File -> nazwa widget.xml, typ Layout). Jako tło dla naszego Widżetu wykorzystamy poniższy obrazek zapisany w technice NinePatch: [...]

Prześlij komentarz

Zaloguj się lub skorzystaj z profilu:

[rpxlogin redirect="http://www.android4devs.pl" prompt="" style="large"]

Możesz również zostawić komentarz bez rejestracji, korzystając z poniższego formularza:

Musisz być zalogowany aby móc pisać komentarze.