Skip to content
Akshay Arora edited this page Sep 30, 2017 · 31 revisions

This page is a WIP

TOC

  1. Philosophy
  2. Installation Instructions
  3. Contributing

Dev Sprint Summaries/Blog Posts

  1. Our First Dev Sprint meant to get people familiarized with kivy.

After this first Devspring it was decided that we would start working on the app from scratch. For this purpose the master branch was emptied and we have started with blank dir.

Step 1: We setup a basic structure for the app

PyCon-Mobile-App
|
|___ LICENSE
|___ Makefile
|___ README.md
|___ eventsapp
       |___ main.py: "This is the main entry point of our application"
       |___ uix: "This is where our user interface elements go."
             |___ screens: "This is where all our UI screens of the app go."
|
|___ tools: "This is where all our tools including assets etc go."
       |___ images: "This is where all our image assets go."
       |___ raw_assets: "This is where our raw assets from the design team exist."
|___ tests: "All our tests go here"

This is the current app structure, Currently the main.py just has the following data.

from kivy.app import App


class EventsApp(App):
    '''This is our entry point for the application
    '''

    def on_pause(self):
        # allow the app to pause on android and ios
        # set this to False if you do not want that.
        return True

    def on_resume(self):
        pass

# is our app running as main or is it being imported as a module?
if __name__ == '__main__':
    # our app is running as main
    # let us instantiate the app and run it.
    EventsApp().run()

Now run this APP.

python main.py

So this gives you just one simple blank window with nothing in there.

Step 2: Design And Architecture of the project

Keeping in mind the following items::

  • UI Design of the app ref
  • Features ref
  • Usage pattern of the app

We will be sending out a mail to each volunteer group asking for their input on how they want to use the app. This should help us get a better idea of how to have the app designed.

Till that we will be starting with a basic app loads basic screens

The SplashScreen

Starting from the blank screen in step one,

The first thing that happens in our app should be the display of logo on splash screen.

Now what is a ScreenManager?

    [ ] Your physical screen
    [ ] Screen Manager
[1] [2] [3] Screens 1, 2 & 3

At any given point a screen manager would show you a one of the screens 1, 2 or 3.
This allows you to have many screens designed and available ready to be brought inside
the physical screen for display based on any event.

A ScreenManager is a Widget that houses multiple screens that can be loaded in it using different types of transitions, for more info in the subjects please look at https://kivy.org/docs/api-kivy.uix.screenmanager.html

What is a splash screen?

(Wiki) https://en.wikipedia.org/wiki/Splash_screen has a good explanation. Basically it is a Image + Logo, anything that gives the user a idea of what the product does. Some splash screens include versions some do not, look at the wiki for more details.

Now that every one knows what's a splash screen and a ScreenManager, let's make sure that the root Widget of our app is a screen Manager.

https://github.com/pythonindia/PyCon-Mobile-App/blob/master/eventsapp/main.py#L38

The way we do this is to return ScreenManager widget's instance in the build method of the app class.

class EventsApp(App):
    '''This is our entry point for the application
    '''
    
    def build(self):
       from kivy.uix.screenmanager import ScreenManager
       root = ScreenManager()
       #return the root widget here
       return root

Now What is a root widget?

Consider a Tree


      0    This is our root 
    /   \
  0      0
 / \    / \
0   0  0   0

A root widget in terms of the UI tree is the widget that sits at top of everything under it and has no other widget on top of it.

At any given time app.root points to one root widget by default this is the one returned by the build method.

Now that we understand what is a root widget, and that we have ScreenManager as our current root of the app, we can move forward to creating screens for this manager.

Let's first add a load_screen method in our main.py. This method could be used/called by any place in our app to load a screen in any given ScreenManager.

This method is supposed to be used like this::

    app_instance.load_screen('ScreenName')

As a example look at this line

What does this function do?(Only for advanced users, most people do not need to know how and why this works).

A module_path has been setup before hand to be used by, load_screen('ScreenName') for loading the screens, in our case this is uix/screens.

So this method, load_screen looks for a module screenname.py in directory uix/screens/, under the directory where main.py resides and imports it.

Then this imports the class ScreenName from that file and instantiates it. Then this adds it to the screen manager instance.

ok, now that we have a method to load a screen in the ScreenManager, we need to create and load our LogoScreen or splash screen.

Let's create a new dir, uix under the eventsapp folder, add a blank __init__.py in it, so this folder can be imported as a module, then do the same for uix/screens folder adding a __init__.py under it..

cd PyCon-Mobile-App/eventsapp
mkdir uix
touch uix/__init__.py
mkdir uix/screens
touch uix/screens/__init__.py

Next let's create our splash screen.

touch uix/screens/logoscreen.py

Open this file in a editor of your choice.


'''
logo_screen:
=============
Display the logo
'''

from kivy.uix.screenmanager import Screen
from kivy.lang import Builder

class LogoScreen(Screen):
    ''' The screen responsible for displaying a Logo, Splash.
    '''
    Builder.load_string('''
<LogoScreen>
    name: 'LogoScreen'
''')

Important thing to note here. In order to define the UI of any widget, you have to write a rule in KV language denoted by <NameOfWidget>.

Let's just keep this blank for now, and just setup the name of the screen. Note:: name: 'LogoScreen', part is important and should be the same as the name of the class itself.

If we save and run this file, we will see nothing happen, why?

Cause there is nothing inside this screen. Let's add the Splash Image.

First let's take the splash screen from the raw_assets folder, add it to our data/images folder.

Next let us design the UI for this screen.

from kivy.uix.screenmanager import Screen
from kivy.lang import Builder

class LogoScreen(Screen):

   Builder.load_string('''
<LogoScreen>
    name: 'LogoScreen'
    Image
        source: 'data/images/background.png'
        allow_stretch: True
 ''')

Let's save this file and run the app.

python main.py

What do you see?

You see a image on the screen but it is not taking up the entire screen.

Furthermore why is this showing us a square window when we should be designing the app for a mobile?

Let's try and emulate a mobile screen.

Using the Screen Module

python main.py -m screen:droid2,portrait

That's a bit better? Screen should now emulate the appearance of a Droid2 mobile in portrait mode.

Next let us add the PyCon India logo

'''
logo_screen:
=============
Display the logo
'''

from kivy.uix.screenmanager import Screen
from kivy.lang import Builder

class LogoScreen(Screen):

   Builder.load_string('''
<LogoScreen>
    name: 'LogoScreen'
    Image
        source: 'data/images/background.png'
        allow_stretch: True
    Image
    	id: logo_img
    	source: 'data/images/logo.png'
    	allow_stretch: True
    	pos_hint: {'center_x': .5, 'center_y': .5}
''')


So, we just add a simple Image on top of the earlier Image, and make sure it is centered using pos_hint, pos_hint: {'center_x': .5, 'center_y': .5} signifies we want the widget to be centered in it's parent.

Animation

Let's animate the logo.

'''
logo_screen:
=============
Display the logo
'''

from kivy.uix.screenmanager import Screen
from kivy.lang import Builder

class LogoScreen(Screen):

   Builder.load_string('''
<LogoScreen>
    name: 'LogoScreen'
    on_enter:
        from kivy.animation import Animation
        Animation(opacity=1, size=(root.width - dp(90), root.height), d=.5).start(logo_img)
    Image
        source: 'data/images/background.png'
        allow_stretch: True
    Image
    	id: logo_img
    	opacity: 0
    	source: 'data/images/logo.png'
    	allow_stretch: True
    	size_hint: None, None
    	size: 0, 0
    	pos_hint: {'center_x': .5, 'center_y': .5}
'''

The part that animates the widget is this::

...
    on_enter: 
        from kivy.animation import Animation
        Animation(opacity=1, size=(root.width - dp(90), root.height), d=.5).start(logo_img)

So when this screen enters the visible space, a on_enter event is called, where we 1) import Animation, 2) set Animation to happen on opacity and size of the widget. We also make sure to set the opacity and size of the widget to 0 & (0, 0) respectively.

Adding Navigation Drawer

If we follow the wireframe the next logical step is to design a NavigationDrawer.

For this we create a new file named NavigationScreen in the uix/screens folder, make sure to load it by default when the app starts.

We do this on the LogoScreen once we are done animating the logo.

Adding Screens

To the Navigation Drawer

Now all we need to do is create a simple screen like we did before. This is a simple About Screen with a Button.

We load this screen inside the ScreenManager inside the NavigationDrawer

Button
    text: 'About'
    on_release:
        app.navigation_screen.ids.drawer.toggle_state()
        app.load_screen('AboutScreen', manager=app.navigation_screen.ids.nav_manager)

Here first, when the About Button, is released, on_release we first access the navigation_screen using the app.navigation_screen attribute. However where did we set this?

Look at line No. 99

Here we set the attribute app.navigation_screen when the Screen is first loaded into it's manager.

Ok, now that we have access to the screen, we can access all the id under it like so.

so, here we toggle the drawer and load the screen named AboutScreen.

That's it, this is how you create and add a new screen.

Next steps TODO: Feel free to take up tasks from below

  • Adding a Navigation Drawer. [Quanon: Complete][ToDo: Documentation]
  • Adding a Buttons to Navigation Drawer [Quanon: ToDo]
  • Setting ScreensManager inside NavigationDrawer[Quanon: Copmlete ToDo: Documnetation]
  • Getting and sending data as Push Notification(Serverside + Firebase integration)
  • Adding & loading screens to this ScreenManager inside Navigation drawer based on which button was selected.See example above.

Screens for

  • Welcome Screen
  • Schedule
  • Speaker Page
  • Venue
  • About(10% done)
  • Community
  • Tickets
  • Open Spaces
  • Sponsors