├── .gitignore ├── README.md ├── assets ├── icon.png └── images │ ├── 1.png │ └── ui.png ├── custom_checkbox.py ├── main.py └── ui.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | #.idea/ 161 | *qr.png 162 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flet-todo-app-Tutorials 2 | ![ui](ui.png) -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1Mr-Newton/Flet-todo-app-Tutorials/68c860bfdeab037137755a0bd7ac574b1830c6dc/assets/icon.png -------------------------------------------------------------------------------- /assets/images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1Mr-Newton/Flet-todo-app-Tutorials/68c860bfdeab037137755a0bd7ac574b1830c6dc/assets/images/1.png -------------------------------------------------------------------------------- /assets/images/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1Mr-Newton/Flet-todo-app-Tutorials/68c860bfdeab037137755a0bd7ac574b1830c6dc/assets/images/ui.png -------------------------------------------------------------------------------- /custom_checkbox.py: -------------------------------------------------------------------------------- 1 | from flet import * 2 | class CustomCheckBox(UserControl): 3 | def __init__(self,color,label='',selection_fill='#183588',size=25,stroke_width=2,animation=None, checked=False, font_size=17, pressed=None): 4 | super().__init__() 5 | self.selection_fill = selection_fill 6 | self.color = color 7 | self.label = label 8 | self.size = size 9 | self.stroke_width = stroke_width 10 | self.animation=animation 11 | self.checked=checked 12 | self.font_size=font_size 13 | self.pressed = pressed 14 | def _checked(self): 15 | self.check_box = Container( 16 | animate=self.animation, 17 | width=self.size,height=self.size, 18 | border_radius=(self.size/2)+5, 19 | bgcolor=self.CHECKED, 20 | content=Icon(icons.CHECK_ROUNDED,size=15,),) 21 | return self.check_box 22 | 23 | def _unchecked(self): 24 | self.check_box = Container( 25 | animate=self.animation, 26 | width=self.size,height=self.size, 27 | border_radius=(self.size/2)+5, 28 | bgcolor=None, 29 | border = border.all(color=self.color,width=self.stroke_width), 30 | content=Container(), 31 | ) 32 | return self.check_box 33 | 34 | def build(self): 35 | self.BG = '#041955' 36 | self.FG = '#3450a1' 37 | self.PINK = '#eb06ff' 38 | self.CHECKED = '#183588' 39 | 40 | if self.checked == True: 41 | return Column(controls=[ 42 | Container( 43 | on_click = lambda e: self.checked_check(e), 44 | content=Row( 45 | controls=[ 46 | self._checked(), 47 | Text(self.label, 48 | font_family='poppins', 49 | size=self.font_size, 50 | weight=FontWeight.W_300,), 51 | ])) 52 | ]) 53 | 54 | else: 55 | return Column( 56 | controls=[ 57 | Container(on_click = lambda e: self.checked_check(e), 58 | content=Row( 59 | controls=[ 60 | self._unchecked(), 61 | Text(self.label, 62 | font_family='poppins', 63 | size=self.font_size, 64 | weight=FontWeight.W_300,), 65 | ])) 66 | ]) 67 | 68 | def checked_check(self,e): 69 | print(self.checked) 70 | if self.checked == False: 71 | self.checked = True 72 | self.check_box.border = None 73 | self.check_box.bgcolor = self.CHECKED 74 | self.check_box.content = Icon(icons.CHECK_ROUNDED,size=15,) 75 | self.update() 76 | 77 | 78 | elif self.checked == True: 79 | self.checked = False 80 | self.check_box.bgcolor = None 81 | self.check_box.border = border.all(color=self.color,width=self.stroke_width) 82 | self.check_box.content.visible = False 83 | self.update() 84 | 85 | 86 | if self.pressed: 87 | self.run() 88 | def is_checked(self): 89 | return self.checked 90 | 91 | def run(self,*args): 92 | self.pressed(args) -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from flet import * 2 | 3 | from custom_checkbox import CustomCheckBox 4 | 5 | 6 | def main(page: Page): 7 | BG = "#041955" 8 | FWG = "#97b4ff" 9 | FG = "#3450a1" 10 | PINK = "#eb06ff" 11 | 12 | circle = Stack( 13 | controls=[ 14 | Container(width=100, height=100, border_radius=50, bgcolor="white12"), 15 | Container( 16 | gradient=SweepGradient( 17 | center=alignment.center, 18 | start_angle=0.0, 19 | end_angle=3, 20 | stops=[0.5, 0.5], 21 | colors=["#00000000", PINK], 22 | ), 23 | width=100, 24 | height=100, 25 | border_radius=50, 26 | content=Row( 27 | alignment="center", 28 | controls=[ 29 | Container( 30 | padding=padding.all(5), 31 | bgcolor=BG, 32 | width=90, 33 | height=90, 34 | border_radius=50, 35 | content=Container( 36 | bgcolor=FG, 37 | height=80, 38 | width=80, 39 | border_radius=40, 40 | content=CircleAvatar( 41 | opacity=0.8, 42 | foreground_image_src="https://images.unsplash.com/photo-1545912452-8aea7e25a3d3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80", 43 | ), 44 | ), 45 | ) 46 | ], 47 | ), 48 | ), 49 | ] 50 | ) 51 | 52 | def shrink(e): 53 | page_2.controls[0].width = 120 54 | page_2.controls[0].scale = transform.Scale( 55 | 0.8, alignment=alignment.center_right 56 | ) 57 | page_2.controls[0].border_radius = border_radius.only( 58 | top_left=35, top_right=0, bottom_left=35, bottom_right=0 59 | ) 60 | page_2.update() 61 | 62 | def restore(e): 63 | page_2.controls[0].width = 400 64 | page_2.controls[0].border_radius = 35 65 | page_2.controls[0].scale = transform.Scale(1, alignment=alignment.center_right) 66 | page_2.update() 67 | 68 | create_task_view = Container( 69 | content=Container( 70 | on_click=lambda _: page.go("/"), height=40, width=40, content=Text("x") 71 | ) 72 | ) 73 | 74 | tasks = Column( 75 | height=400, 76 | scroll="auto", 77 | # controls=[ 78 | # Container(height=50,width=300,bgcolor='red'), 79 | # Container(height=50,width=300,bgcolor='red'), 80 | # Container(height=50,width=300,bgcolor='red'), 81 | # Container(height=50,width=300,bgcolor='red'), 82 | # ] 83 | ) 84 | for i in range(10): 85 | tasks.controls.append( 86 | Container( 87 | height=70, 88 | width=400, 89 | bgcolor=BG, 90 | border_radius=25, 91 | padding=padding.only( 92 | left=20, 93 | top=25, 94 | ), 95 | content=CustomCheckBox(color=PINK, label="Create interesting content!"), 96 | ), 97 | ) 98 | 99 | categories_card = Row(scroll="auto") 100 | categories = ["Business", "Family", "Friends"] 101 | for i, category in enumerate(categories): 102 | categories_card.controls.append( 103 | Container( 104 | border_radius=20, 105 | bgcolor=BG, 106 | width=170, 107 | height=110, 108 | padding=15, 109 | content=Column( 110 | controls=[ 111 | Text("40 Tasks"), 112 | Text(category), 113 | Container( 114 | width=160, 115 | height=5, 116 | bgcolor="white12", 117 | border_radius=20, 118 | padding=padding.only(right=i * 30), 119 | content=Container( 120 | bgcolor=PINK, 121 | ), 122 | ), 123 | ] 124 | ), 125 | ) 126 | ) 127 | 128 | first_page_contents = Container( 129 | content=Column( 130 | controls=[ 131 | Row( 132 | alignment="spaceBetween", 133 | controls=[ 134 | Container( 135 | on_click=lambda e: shrink(e), content=Icon(icons.MENU) 136 | ), 137 | Row( 138 | controls=[ 139 | Icon(icons.SEARCH), 140 | Icon(icons.NOTIFICATIONS_OUTLINED), 141 | ], 142 | ), 143 | ], 144 | ), 145 | Container(height=20), 146 | Text(value="What's up, Olivia!"), 147 | Text(value="CATEGORIES"), 148 | Container( 149 | padding=padding.only( 150 | top=10, 151 | bottom=20, 152 | ), 153 | content=categories_card, 154 | ), 155 | Container(height=20), 156 | Text("TODAY'S TASKS"), 157 | Stack( 158 | controls=[ 159 | tasks, 160 | FloatingActionButton( 161 | bottom=2, 162 | right=20, 163 | icon=icons.ADD, 164 | on_click=lambda _: page.go("/create_task"), 165 | ), 166 | ] 167 | ), 168 | ], 169 | ), 170 | ) 171 | 172 | page_1 = Container( 173 | # width=400, 174 | # height=850, 175 | bgcolor=BG, 176 | border_radius=35, 177 | padding=padding.only(left=50, top=60, right=200), 178 | content=Column( 179 | controls=[ 180 | Row( 181 | alignment="end", 182 | controls=[ 183 | Container( 184 | border_radius=25, 185 | padding=padding.only( 186 | top=13, 187 | left=13, 188 | ), 189 | # height=50, 190 | # width=50, 191 | border=border.all(color="white", width=1), 192 | on_click=lambda e: restore(e), 193 | content=Text("<"), 194 | ) 195 | ], 196 | ), 197 | Container(height=20), # height=20 198 | circle, 199 | Text("Olivia\nMitchel", size=32, weight="bold"), 200 | Container(height=25), 201 | Row( 202 | controls=[ 203 | Icon(icons.FAVORITE_BORDER_SHARP, color="white60"), 204 | Text( 205 | "Templates", 206 | size=15, 207 | weight=FontWeight.W_300, 208 | color="white", 209 | font_family="poppins", 210 | ), 211 | ] 212 | ), 213 | Container(height=5), 214 | Row( 215 | controls=[ 216 | Icon(icons.CARD_TRAVEL, color="white60"), 217 | Text( 218 | "Templates", 219 | size=15, 220 | weight=FontWeight.W_300, 221 | color="white", 222 | font_family="poppins", 223 | ), 224 | ] 225 | ), 226 | Container(height=5), 227 | Row( 228 | controls=[ 229 | Icon(icons.CALCULATE_OUTLINED, color="white60"), 230 | Text( 231 | "Templates", 232 | size=15, 233 | weight=FontWeight.W_300, 234 | color="white", 235 | font_family="poppins", 236 | ), 237 | ] 238 | ), 239 | Image( 240 | src=f"/images/1.png", 241 | width=300, 242 | height=200, 243 | ), 244 | Text( 245 | "Good", 246 | color=FG, 247 | font_family="poppins", 248 | ), 249 | Text( 250 | "Consistency", 251 | size=22, 252 | ), 253 | ] 254 | ), 255 | ) 256 | 257 | page_2 = Row( 258 | alignment="end", 259 | controls=[ 260 | Container( 261 | width=400, 262 | height=850, 263 | bgcolor=FG, 264 | border_radius=35, 265 | animate=animation.Animation(600, AnimationCurve.DECELERATE), 266 | animate_scale=animation.Animation(400, curve="decelerate"), 267 | padding=padding.only(top=50, left=20, right=20, bottom=5), 268 | content=Column(controls=[first_page_contents]), 269 | ) 270 | ], 271 | ) 272 | 273 | container = Container( 274 | width=400, 275 | height=850, 276 | bgcolor=BG, 277 | border_radius=35, 278 | content=Stack( 279 | controls=[ 280 | page_1, 281 | page_2, 282 | ] 283 | ), 284 | ) 285 | 286 | pages = { 287 | "/": View( 288 | "/", 289 | [ 290 | container, 291 | ], 292 | ), 293 | "/create_task": View( 294 | "/create_task", 295 | [create_task_view], 296 | ), 297 | } 298 | 299 | def route_change(route): 300 | page.views.clear() 301 | new_view = pages[route.route] 302 | page.views.append(new_view) 303 | page.update() 304 | 305 | page.on_route_change = route_change 306 | page.go(page.route) 307 | 308 | 309 | app(target=main, assets_dir="assets") 310 | -------------------------------------------------------------------------------- /ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1Mr-Newton/Flet-todo-app-Tutorials/68c860bfdeab037137755a0bd7ac574b1830c6dc/ui.png --------------------------------------------------------------------------------