投稿時点で、fletにはアコーディオン的な、折り畳みが可能なWidget(control)がなかったので、
flutterでいうところのExpansionTile
を作ってみた。
dropdownContainer.py
from typing import List, Optional
from flet import *
from flet_core.control import Control, OptionalNumber
from flet_core.types import AnimationValue,BorderRadiusValue,MarginValue,PaddingValue
class DropDownContainer(UserControl):
def __init__(
self,
leading:Optional[Control] = None,
title:Optional[Control] = None,
inner_contents:Optional[List[Control]] = None,
inner_content_height:OptionalNumber = 25,
action_button_icon:Optional[str] = icons.ARROW_DROP_DOWN_CIRCLE_ROUNDED,
action_button_icon_size:OptionalNumber = 20,
height:OptionalNumber = 70,
width:OptionalNumber = 265,
padding: PaddingValue = None,
margin: MarginValue = None,
bgcolor: Optional[str] = None,
border: Optional[Border] = None,
border_radius: BorderRadiusValue = None,
animate: AnimationValue = animation.Animation(400,"decelerate"),
disabled: Optional[bool] = None,
clip_behavior: Optional[ClipBehavior] = ClipBehavior.HARD_EDGE):
self.leading = leading
self.title = title
self.inner_contents = inner_contents
self.inner_content_height = inner_content_height
self.inner_contents_height = len(self.inner_contents) * self.inner_content_height
self.action_button_icon = action_button_icon
self.action_button_icon_size = action_button_icon_size
self.dd_height = height
self.dd_width = width
self.dd_padding = padding
self.dd_margin = margin
self.dd_bgcolor = bgcolor
self.dd_border = border
self.dd_border_radius = border_radius
self.dd_animate = animate
self.dd_disabled = disabled
self.dd_clip_behavior = clip_behavior
self.full_width = (width+padding.left+padding.right) if padding is not None else width
self.full_height = (height+padding.top+padding.bottom) if padding is not None else height
super().__init__()
def ExpandContainer(self,e):
openHeight = self.full_height + self.inner_contents_height
if self.controls[0].height != openHeight:
self.controls[0].height = openHeight
self.controls[0].update()
else:
self.controls[0].height = self.full_height
self.controls[0].update()
def TitleContainer(self):
return Container(
width=self.dd_width,
height=self.dd_height,
content=Row(
alignment=MainAxisAlignment.SPACE_BETWEEN,
vertical_alignment=CrossAxisAlignment.CENTER,
controls=[
self.leading,
self.title,
IconButton(
icon=self.action_button_icon,
icon_size=self.action_button_icon_size,
on_click=lambda e:self.ExpandContainer(e),
)
]
)
)
def InnerContainer(self):
return Container(
width=self.dd_width,
height=self.inner_contents_height,
content=Column(
alignment=MainAxisAlignment.START,
spacing=0,
controls=self.inner_contents
)
)
def build(self):
return Container(
width = self.full_width,
height = self.full_height,
bgcolor = self.dd_bgcolor,
border = self.dd_border,
border_radius = self.dd_border_radius,
animate = self.dd_animate,
disabled = self.disabled,
padding = self.dd_padding,
clip_behavior = self.dd_clip_behavior,
content=Column(
spacing=0,
alignment=MainAxisAlignment.START,
horizontal_alignment=CrossAxisAlignment.CENTER,
controls=[
self.TitleContainer(),
self.InnerContainer(),
]
)
)
使用例
myDropdownContainer.py
from flet import *
from dropDownContainer import DropDownContainer
def myDropDownContainer(title:str,sub_title:str = None,inner_contents:list =[]):
def _getInnerData(inner_contents):
l = []
for item in inner_contents:
l.append(
Container(
padding=padding.only(left=20),
content=Row(
height=25,
spacing=0,
controls=[
Container(
padding=padding.only(right=10),
content=Icon(icons.FOLDER,size=14),
),
Text(item,size=9,weight="bold",color="white54")
]
)
)
)
return l
sub_title_widget = Text(sub_title,size=9,color="white54")
title_container = Container(
height=70,
content=Column(
spacing=1,
alignment=MainAxisAlignment.CENTER,
controls=[
Text(title,size=11),
]
)
)
if sub_title is not None :
title_container.content.controls.append(sub_title_widget)
return DropDownContainer(
leading=Icon(icons.FOLDER),
title=title_container,
inner_contents=_getInnerData(inner_contents),
inner_content_height=25,
bgcolor="white54",
border_radius=11,
height=70,
width=265,
padding=padding.only(left=10,right=10),
)
main.py
import flet
from flet import *
from myDropDownContainer import myDropDownContainer
def main(page:Page):
page.title = 'expandingcontainer'
main_container = Container(
width=400,
height=600,
padding=20,
content = Column(
scroll="hidden",
controls=[
myDropDownContainer(
title='MyDropDownContainer',
sub_title="doropdown_container",
inner_contents=["hoge_folder1","hoge_folder2","hoge_folder3"]
),
myDropDownContainer(
title='MyDropDownContainer',
inner_contents=["hoge_folder1","hoge_folder2","hoge_folder3"]
),
]
)
)
page.add(main_container)
page.update()
if __name__ == '__main__':
flet.app(target=main)
大満足です!