PageRenderTime 51ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/content/as3-madcomponents-tutorial-series-separation-of-concerns.md

https://gitlab.com/monkmartinez/Caffeine_Industries
Markdown | 355 lines | 273 code | 82 blank | 0 comment | 0 complexity | 444dc3b35a62fe74e032c7cb5c95d643 MD5 | raw file
  1. Title: AS3 MadComponents Tutorial Series - Separation of Concerns
  2. Date: 2011-09-04 16:42
  3. Author: Michael
  4. Category: AS3
  5. Tag: Flash, MadComponents, UI
  6. Slug: as3-madcomponents-tutorial-series-separation-of-concerns
  7. Status: published
  8. Best practices for programming tell us separation of concerns,
  9. encapsulation and modularity are desirable in most, but not all,
  10. application contexts. A complex app with many views and/or items could
  11. quickly get out of control in a plethora of ways within
  12. the monolithic class context.
  13. The project I'm working on has nearly 50 separate views and consist of
  14. mostly textual data. So my first task was learning the method(s) to
  15. separate class files the
  16. [MadComponent](http://code.google.com/p/mad-components/)way. This
  17. example will be quite simple but will illustrate how one would go about
  18. using different AS class files to separate concerns.
  19. <span style="text-decoration: underline;">**User Story:**</span> A list
  20. based component is chosen by the user. This item navigates to a
  21. "details" page or another component with more data.
  22. **Lets build the "landing page" or main application page;**
  23. First the XML layout:
  24. :::actionscript3
  25. public class SeparateClassExample extends Sprite{
  26. protected static const DATA:XML =
  27. ;
  28. protected static const LIST:XML =
  29. {DATA};
  30. //Important
  31. protected static const NAVIGATION:XML =
  32. {LIST}
  33. {Page0.LAYOUT}
  34. {Page1.LAYOUT}
  35. ;
  36. protected var _uiNavigation:UINavigation;
  37. ```
  38. The DATA constant simply defines the items that will populate the list.
  39. The LIST constant accepts the DATA constant and applies some basic
  40. formatting, Ie. colour (note the UK spelling). We also implement the
  41. search feature here which will filter the list based on the item's
  42. label. (I have experimented with different search methods, but have been
  43. unsuccessful thus far... we will explore this later).
  44. The NAVIGATION constant is actually the heart and soul of this simple
  45. app. You can think of the NAVIGATION constant as an Array of data that
  46. you define in XML and classes. As my astute readers will probably note
  47. based on a quick glance. We haven't defined Page0, Page1 and you can't
  48. spot LAYOUT anywhere. These are defined separate class files, although
  49. not completely necessary, it helps me keep things organized.
  50. We declare the _uiNavigation instance or class level variable which
  51. we'll define in subsequent steps.
  52. **Lets move on to the constructor:**
  53. :::actionscript3"}
  54. public function SeparateClassExample(screen:Sprite = null) {
  55. if (screen){
  56. screen.addChild(this);
  57. }
  58. // support autoOrients
  59. stage.align = StageAlign.TOP_LEFT;
  60. stage.scaleMode = StageScaleMode.NO_SCALE;
  61. // Create the main UI or "Landing Page"
  62. UI.create(this, NAVIGATION);
  63. // Initialize "views"
  64. Page0.initialize();
  65. Page1.initialize();
  66. // Navigation layout and behaviour
  67. _uiNavigation = UINavigation(UI.findViewById("nav"));
  68. _uiNavigation.autoForward = false;
  69. // Must set to false otherwise the app scrolls through all the pages in the "stack"
  70. _uiNavigation.autoBack = false;
  71. // Go to the "page" requested
  72. _uiNavigation.addEventListener(UIList.CLICKED, navigationChange);
  73. // Go Back using the Nav bar back button
  74. _uiNavigation.navigationBar.backButton.addEventListener(MouseEvent.MOUSE_UP, goBack);
  75. // Go back using the hardware back button
  76. _uiNavigation.addEventListener(KeyboardEvent.KEY_UP, goBackButton);
  77. _uiNavigation.navigationBar.backButton.colour = 999999;
  78. }
  79. ```
  80. The UI.create method instantiates the UI or "landing page" and all of
  81. the code relating to the use of MadComponents must be implemented after
  82. this method call. We initialize Page0 with a call to a public method
  83. inside the Page0 class. This method can be named anything you like.
  84. We then instantiate the uiNavigation variable to the NAVIGATION
  85. constant defined at the class level through the id we can name
  86. arbitrarily. We can now programmatically add formatting, assign event
  87. listeners and so forth to the uiNavigation variable.
  88. The first event listener UI.CLICKED will direct the navigation to the
  89. "page" that is assigned to the index of the NAVIGATION constant. In this
  90. case 0 is the list itself, while 1 and 2 will be Page0 and Page1
  91. respectively.
  92. The second event listener is assigned to the navigationBar.backButton
  93. and is a simple MouseEvent.MOUSE_UP event. As you will see, this event
  94. will handle the back button that is added to the navigation bar once we
  95. have navigated away from the main list.
  96. The third event listener is added to handle the device back button,
  97. generally this is an Android device. I found through testing that if
  98. autoBack is set to false, you lose back button functionality. In some
  99. cases you may want the autoBack functionality, but its not appropriate
  100. in this context as it will scroll through the stack of items defined in
  101. the NAVIGATION constant. This event listener simply adds the devices
  102. back button into the app.
  103. Daniel is working on documentation as we speak, but a good starting
  104. place to learn about the framework are the PDF(s) included on the
  105. [download page](http://code.google.com/p/mad-components/downloads/list).
  106. You can see what I've done to customize the uiNavigation variable
  107. based on the comments added into the code.
  108. **Now lets handle the events we declared in the constructor:**
  109. :::actionscript3
  110. public function navigationChange(event:Event):void {
  111. var navIndex:int = _uiNavigation.index;
  112. // Check to see if current page is @ 0 to set correct title
  113. if(_uiNavigation.pages[0]){
  114. _uiNavigation.title = "Home";
  115. }
  116. // navigation Stuff
  117. if(navIndex == 0){
  118. _uiNavigation.goToPage(1, UIPages.SLIDE_LEFT);
  119. _uiNavigation.title = "Page 0";
  120. } else if (navIndex == 1){
  121. _uiNavigation.goToPage(2, UIPages.SLIDE_LEFT);
  122. _uiNavigation.title = "Page 1";
  123. }
  124. }
  125. // For the back button in the Navigation bar
  126. protected function goBack(event:Event):void {
  127. _uiNavigation.goToPage(0, UIPages.SLIDE_RIGHT);
  128. _uiNavigation.title = "Home";
  129. }
  130. // With autoBack set to false, you lose the device back button for some reason
  131. // You can use the Native App library to check for a device back button event
  132. protected function goBackButton(event:KeyboardEvent):void{
  133. if(event.keyCode == Keyboard.BACK){
  134. _uiNavigation.goToPage(0, UIPages.SLIDE_RIGHT);
  135. _uiNavigation.title = "Home";
  136. }
  137. }
  138. }
  139. }
  140. ```
  141. In this example, I want the navigationChange event to take the user to
  142. the page associated with the index they select. We let the gotoPage
  143. method do all the heavy lifting and add a nice visual transition. Beyond
  144. that the back button in the navigation bar and the device back button
  145. (if available) simply takes the user back to the list. If you've
  146. followed any of the tutorials mentioned in the starting out post, you
  147. will not see anything surprising here. The exception is maybe the event
  148. handler for the back button which is similar to the way one handles an
  149. event on the decktop or web based flash application.
  150. A little gotcha I found is when you don't explicitly set the title, the
  151. navigation component will leave the previous title in the navigation bar
  152. despite the change. Checking to make sure its set correctly just adds a
  153. bit of polish.
  154. **Now lets add the separate class "views" or Page0 and Page1:**
  155. :::actionscript3
  156. package
  157. {
  158. import com.danielfreeman.madcomponents.*;
  159. import flash.display.Sprite;
  160. import flash.display.StageAlign;
  161. import flash.display.StageScaleMode;
  162. import flash.events.Event;
  163. import flash.system.Capabilities;
  164. import flash.text.TextField;
  165. public class Page0 extends Sprite
  166. {
  167. public static const LAYOUT:XML =
  168. ;
  169. protected static var _message:UILabel;
  170. public function Patient()
  171. {
  172. super();
  173. }
  174. public static function initialize():void{
  175. _message = UILabel(UI.findViewById("message0"));
  176. _message.htmlText = "App Considerations:Is it AWESOME?Are you going to BroGram? Sup?More Stuff";
  177. }
  178. }
  179. }
  180. ```
  181. This is a basic page layout using HTML text. LAYOUT is the constant we
  182. call from within the NAVIGATION constant in the Main class as you've
  183. seen. If I may direct your attention to the constructor, notice that
  184. UI.create is not used here. In this case, we "instantiate" the layout
  185. through the public initialize method mentioned earlier. Also note, ID's
  186. for the components for each page need to be different. Ie. Page0 label
  187. has an id of "message0". Page1 will need a label id of "message1" to
  188. work as one would expect. Flash requires string literals to be on the
  189. same line. In my working app this line is almost ridiculously long, no
  190. need to worry as the text will render as you've defined.
  191. This is the "MAIN" class in all its glory.
  192. :::actionscript3
  193. package
  194. {
  195. import com.danielfreeman.madcomponents.*;
  196. import flash.desktop.NativeApplication;
  197. import flash.display.Sprite;
  198. import flash.display.StageAlign;
  199. import flash.display.StageScaleMode;
  200. import flash.events.Event;
  201. import flash.events.KeyboardEvent;
  202. import flash.events.MouseEvent;
  203. import flash.ui.Keyboard;
  204. public class SeparateClassExample extends Sprite{
  205. protected static const DATA:XML =
  206. ;
  207. protected static const LIST:XML =
  208. {DATA};
  209. // Each additional "Page" needs to have different id's
  210. //for the components, even when they are separated into separate classes
  211. protected static const NAVIGATION:XML =
  212. {LIST}
  213. {Page0.LAYOUT}
  214. {Page1.LAYOUT}
  215. ;
  216. protected var _uiNavigation:UINavigation;
  217. public function SeparateClassExample(screen:Sprite = null) {
  218. if (screen){
  219. screen.addChild(this);
  220. }
  221. // support autoOrients
  222. stage.align = StageAlign.TOP_LEFT;
  223. stage.scaleMode = StageScaleMode.NO_SCALE;
  224. // Create the main UI or "Landing Page"
  225. UI.create(this, NAVIGATION);
  226. // Initialize "views"
  227. Page0.initialize();
  228. Page1.initialize();
  229. // Navigation layout and behaviour
  230. _uiNavigation = UINavigation(UI.findViewById("nav"));
  231. _uiNavigation.autoForward = false;
  232. // Must set to false otherwise the app scrolls through all the pages in the "stack"
  233. _uiNavigation.autoBack = false;
  234. // Go to the "page" requested
  235. _uiNavigation.addEventListener(UIList.CLICKED, navigationChange);
  236. // Go Back using the Nav bar back button
  237. _uiNavigation.navigationBar.backButton.addEventListener(MouseEvent.MOUSE_UP, goBack);
  238. // Go back using the hardware back button
  239. _uiNavigation.addEventListener(KeyboardEvent.KEY_UP, goBackButton);
  240. _uiNavigation.navigationBar.backButton.colour = 999999;
  241. }
  242. public function navigationChange(event:Event):void {
  243. var navIndex:int = _uiNavigation.index;
  244. // Check to see if current page is @ 0 to set correct title
  245. if(_uiNavigation.pages[0]){
  246. _uiNavigation.title = "Home";
  247. }
  248. // navigation Stuff
  249. if(navIndex == 0){
  250. _uiNavigation.goToPage(1, UIPages.SLIDE_LEFT);
  251. _uiNavigation.title = "Page 0";
  252. } else if (navIndex == 1){
  253. _uiNavigation.goToPage(2, UIPages.SLIDE_LEFT);
  254. _uiNavigation.title = "Page 1";
  255. }
  256. }
  257. // For the back button in the Navigation bar
  258. protected function goBack(event:Event):void {
  259. _uiNavigation.goToPage(0, UIPages.SLIDE_RIGHT);
  260. _uiNavigation.title = "Home";
  261. }
  262. // With autoBack set to false, you lose the device back button for some reason
  263. // You can use the Native App library to check for a device back button event
  264. protected function goBackButton(event:KeyboardEvent):void{
  265. if(event.keyCode == Keyboard.BACK){
  266. _uiNavigation.goToPage(0, UIPages.SLIDE_RIGHT);
  267. _uiNavigation.title = "Home";
  268. }
  269. }
  270. }
  271. }
  272. }
  273. ```