Hirdetés

Alkalmazásfejlesztés badára: Egyedi listák

Holdmester kedden megmutatta, hogy hogyan lehet többsoros feliratokat készíteni az EnrichedText osztály segítségével. Ezt a gondolatot (egyébként párhuzamosan) továbbvíve megmutatom, hogy lehet ezt egy görgethető listában felhasználni. Nem volt könnyű kibogozni.

Az IRC kliens UI koncepciójában leírtam, hogy olyan listát szeretnék az üzenetek megjelenítésére, mely a gyári üzenetkezelő alkalmazáshoz hasonlóan lekerekített, az iránytól és az üzenet fajtájától függően eltérő színű téglalapokat tartalmaz. Ez a gyári listák között nem található meg, úgyhogy elő kell venni egy kevéssé dokumentált osztályt a zsákból: ez a CustomList.

A CustomList lényege, hogy változó méretű és felépítésű elemek keverhetőek össze gyakorlatilag szabadon. A beépített, fix szerkezetű listákhoz képest itt nekünk kell definiálni az egyes elemek szerkezetét pixel pontossággal. A résztvevő osztályok a következő ábrán láthatók.

A CustomListItem osztály a lista egy sorát reprezentálja, ennek példányait adhatjuk hozzá a listához. Nem szükséges leszármazott osztályt készíteni, de praktikus, mert ellenkező esetben sok konfigurálást kell elvégezni az osztályon kívül. A rajta megjelenő feliratok, képek illetve egyedileg rajzolt elemek helyét a CustomListItemFormat osztály definiálja, ez gyakorlatilag egy hashmap, mely int azonosítókat rendel a befoglaló téglalapokhoz és néhány egyéb paraméterhez. Amint a formátumot hozzárendeltük a listaelemhez, elkezdhetjük a tényleges adatok feltöltését a SetElement metódusok segítségével. Az egy soros szövegek és sima Bitmapek beállítása triviális, a dolgok az egyedi elemeknél bonyolódnak el.

Az iOS-szel ellentétben itt nem helyezhetünk el tetszőleges Controlt a sorokban, helyette az IcustomListElement interfészt realizáló objektumokat rakhatunk csak fel. Az interfésznek egyetlen implementálandó metódusa van, a DrawElement, mely paraméterül kap egy Canvast – erre kell rajzolni – a listaelem méretét, valamint egy státuszt, miszerint az adott elem ki van-e jelölve, vagy fókuszban van-e esetleg.

Mivel egy teljes értékű Canvast kapunk, bármilyen rajzoló osztály és metódus használható, a folytatásban a már említett EnrichedTextet, valamint a nine-patch bitmaprajzolást használom fel. Előtte viszont megmutatom, hogy hogyan vontam össze az előbb felsorolt osztályokat a saját megoldásomban.

Feleslegesnek érzem a listaelem viselkedésének három osztályra bontását, valamint az üzenetforgalmat is figyelni kell, így a CustomList és a CustomListItem osztályokból is leszármazottakat készítettem. A ConvList annyit ad hozzá az őséhez, hogy az Irc::IConversationEventListener interfészen keresztül érkező, megjelenítendő üzeneteket ő fogadja, létrehozva és hozzáadva a listaelemeket. A MessageListItem összevonja a korábban felsorolt osztályokat, ahogy a következő ábrán látható.

A konfigurálás a Construct metódusba tömörödik össze. Az EnrichedText létrehozása sok újat nem hoz, a paraméterben átadott dimenzió lehet érdekes: bár nem szól róla a dokumentáció, ha a tördelés be van állítva, akkor a függőleges méret egyfajta maximum, a létrejövő objektum nem lóg túl a szükségesnél, ezért biztonságosan megadható neki akár 800 pixeles magasság is. A hívások sorrendje fontos, hogy a szöveg magassága ismert legyen – a GetTotalLineHeight() metódus erre ad választ – mert a listaelem magasságát is nekünk kell megadni az ősosztály számára. Az elem hátteréül szolgáló nine-patch képet lusta betöltéssel egy másik osztályom végzi. Lehetne spórolni azzal, hogy csak egy CustomListItemFormatot példányosítok, de az rontana az összevonáson, a statikus adattagokkal meg eddig problémáim voltak – a BitmapFactoryt akartam így implementálni –így maradt a pazarló megoldás.

A rajzolás ezek után már egyszerű, az eltárolt elemeket kell csak feldobni a Canvasra. Ha valaki nem ismerné, a nine-patch egy rettentő praktikus dolog, amit – mobilon – először az Androidon láttam. Egy olyan képről van szó, mely tetszőleges méretre nyújtható úgy, hogy a sarkai érintetlenek maradnak, csak a közepét nyújtja szét a rendszer. Tehát egy apró képpel nagy felületeket is le lehet fedni, mint például az esetemben az üzenetek hátterét. Egy furcsa bug, hogy kaotikusan viselkedik, ha a célméret kisebb, mint a kiindulási. Erre figyelni kell! Maga a kép 32-bites, ARGB8888 Bitmap, melynek a felső és a bal szélső sorában fekete pixelekkel kell jelölni, hogy melyik rész nyújtható meg. Ha nincs legalább egy ilyen pixel, akkor E_INVALID_ARG hibát kapunk rajzoláskor. Az átlátszóság fontos, mert ha nincs alpha, akkor könnyen lehet, hogy a jelzősorok teljesen feketévé válnak, így a teljes képet szétnyújtja a rendszer. Nem szép látvány. A következő screenshot a Paint.NET-ben rajzolt szürke alapot mutatja.

A következő képeken látható eredeti méretben az a három bitmap, amit a különböző üzenettípusokhoz jelenleg használok, illetve screenshotok a futó alkalmazásból, ahogy a telefonon megjelennek. Ez még nem végleges, egy kicsit hiányos, de már nagyon közelít.

Az ezt megvalósító kódrészlet itt érhető el, összemásoltam a header- és forrásfájlok jelentős részét. A legérdekesebb rész a fájl vége: a MessageListItem osztály.

Karma

Azóta történt

Előzmények