Kolejnym tematem, jaki weźmiemy dziś na warsztat, są animacje.
Temat myślę, że ciekawy i wręcz banalny, jeśli chodzi o implementację.
Do stworzenia animacji posłuży nam klasa Animation.
Wstęp
Działanie animacji polega na sekwencyjnym wyświetlaniu klatek, które reprezentują pojedynczy obrazek. Klatki odtwarzane wystarczająco szybko tworzą efekt animacji.
Wykorzystanie
Animację możemy wykorzystać jako wskaźnik postępu podczas wykonywania operacji, które wymagają dłuższej chwili na wykonanie, np.:
- łączenie się z Internetem,
- inicjalizacja formularza.
W takim przypadku, jest wręcz naszym obowiązkiem poinformować użytkownika, że aplikacja cały czas wykonuje przewidziane dla niej zadania i się nie zawiesiła.
Uprawnienia
Do wczytywania obrazków potrzebujemy uprawnień Image, które dodajemy do pliku manifest.xml w naszym projekcie.
<?xml version="1.0" encoding="utf-8"?> <Manifest> <Id>93bt1p123e</Id> <Secret>9C645DDBA19C71BAD1204DA4DAA7A0B9</Secret> <AppVersion>1.0.0</AppVersion> <ManifestVersion>1.2</ManifestVersion> <Privileges> <Privilege> <Name>IMAGE</Name> </Privilege> </Privileges> <DeviceProfile> <APIVersion>2.0</APIVersion> </DeviceProfile> </Manifest>
Zasoby
Dla celów tego artykułu stworzyłem pięć klatek animacji paska postępu, które wyświetlane będą sekwencyjnie tworząc prostą animację:
Pliki kopiujemy do folderu domowego aplikacji /Home.
Implementacja
#ifndef _FORM1_H_ #define _FORM1_H_ #include <FBase.h> #include <FUi.h> #include <FMedia.h> #include <FGraphics.h> using namespace Osp::Base; using namespace Osp::Media; using namespace Osp::Graphics; class Form1 : public Osp::Ui::Controls::Form, public Osp::Ui::IActionEventListener, Osp::Ui::IOrientationEventListener { // Construction public: Form1(void); virtual ~Form1(void); bool Initialize(void); // Implementation protected: static const int ID_BUTTON_ANIMATION = 101; Osp::Ui::Controls::Button *__pButtonAnimation; Osp::Base::Collection::ArrayList __AnimationFrames; Osp::Ui::Controls::Animation * __pAnimation; Bitmap* CreateFrame(String fileName, int width, int height); public: virtual result OnInitializing(void); virtual result OnTerminating(void); virtual void OnActionPerformed(const Osp::Ui::Control& source, int actionId); virtual void OnOrientationChanged(const Osp::Ui::Control &source, Osp::Ui::OrientationStatus orientationStatus); }; #endif //_FORM1_H_
#include "Form1.h" using namespace Osp::Base; using namespace Osp::Ui; using namespace Osp::Ui::Controls; Form1::Form1(void) { } Form1::~Form1(void) { } bool Form1::Initialize() { // Construct an XML form Construct(L"IDF_FORM1"); return true; } result Form1::OnInitializing(void) { result r = E_SUCCESS; // TODO: Add your initialization code here AddOrientationEventListener(*this); // Get a button via resource ID __pButtonAnimation = static_cast<Button *>(GetControl(L"IDC_BUTTON_ANIMATION")); if (__pButtonAnimation != null) { __pButtonAnimation->SetActionId(ID_BUTTON_ANIMATION); __pButtonAnimation->AddActionEventListener(*this); } // Wymiary klatki int width = 149; int height = 38; // Wczytujemy obrazki Bitmap* pBitmapFrame1 = CreateFrame(L"/Home/frame_1.png", width, height); Bitmap* pBitmapFrame2 = CreateFrame(L"/Home/frame_2.png", width, height); Bitmap* pBitmapFrame3 = CreateFrame(L"/Home/frame_3.png", width, height); Bitmap* pBitmapFrame4 = CreateFrame(L"/Home/frame_4.png", width, height); Bitmap* pBitmapFrame5 = CreateFrame(L"/Home/frame_5.png", width, height); // Tworzymy klatki animacji AnimationFrame* pAnimationFrame1 = new AnimationFrame(*pBitmapFrame1, 1000); AnimationFrame* pAnimationFrame2 = new AnimationFrame(*pBitmapFrame2, 1000); AnimationFrame* pAnimationFrame3 = new AnimationFrame(*pBitmapFrame3, 1000); AnimationFrame* pAnimationFrame4 = new AnimationFrame(*pBitmapFrame4, 1000); AnimationFrame* pAnimationFrame5 = new AnimationFrame(*pBitmapFrame5, 1000); // Dodajemy klatki animacji do kolekcji __AnimationFrames.Construct(); __AnimationFrames.Add(*pAnimationFrame1); __AnimationFrames.Add(*pAnimationFrame2); __AnimationFrames.Add(*pAnimationFrame3); __AnimationFrames.Add(*pAnimationFrame4); __AnimationFrames.Add(*pAnimationFrame5); // Tworzenie animacji __pAnimation = new Animation(); // Centrowanie int xPos = GetWidth() / 2 - width / 2; // Wywołanie konstruktora animacji __pAnimation->Construct(Rectangle(xPos, 100, width, height), __AnimationFrames); // Ilość powtórzeń animacji __pAnimation->SetRepeatCount(1000); // Dodanie animacji do formularza AddControl(*__pAnimation); return r; } result Form1::OnTerminating(void) { result r = E_SUCCESS; // TODO: Add your termination code here __AnimationFrames.RemoveAll(true); return r; } void Form1::OnActionPerformed(const Osp::Ui::Control& source, int actionId) { switch(actionId) { case ID_BUTTON_ANIMATION: { if (__pAnimation->GetStatus() == ANIMATION_STOPPED) { __pButtonAnimation->SetText(L"Stop"); __pAnimation->Play(); } else { __pButtonAnimation->SetText(L"Play"); __pAnimation->Stop(); } break; } default: break; } } // Zmiana orientacji ekranu - przelicz ponownie współrzędne elementów na formularzu void Form1::OnOrientationChanged(const Osp::Ui::Control &source, Osp::Ui::OrientationStatus orientationStatus) { Osp::Graphics::Rectangle clientArea = GetClientAreaBounds(); __pAnimation->SetPosition(clientArea.width / 2 - __pAnimation->GetWidth() / 2, 50); __pButtonAnimation->SetPosition(clientArea.width / 2 - __pButtonAnimation->GetWidth() / 2, 120); } Bitmap* Form1::CreateFrame(String fileName, int width, int height) { Image pImageFrame; pImageFrame.Construct(); Bitmap* pBitmapFrame = pImageFrame.DecodeN(fileName, BITMAP_PIXEL_FORMAT_RGB565, width, height); return pBitmapFrame; }
Zwalnianie zasobów
Musimy ręcznie zadbać o usuniecie obrazków z kolekcji. Sama klasa Animation zostanie usunięta automatycznie przez formularz, który jest jej rodzicem.
__AnimationFrames.RemoveAll(true);
RemoveAll() przyjmuje jeden argument deallocate. Podanie wartości true oznacza nie tylko usunięcie elementu z kolekcji, ale także zwolnienie pamięci zajmowanej przez ten obiekt.
Opis niektórych metod
Metoda GetStatus() klasy Animation zwraca aktualny status animacji. Lista możliwych stanów:
- ANIMATION_STOPPED,
- ANIMATION_PAUSED,
- ANIMATION_PLAYING.