Flutter로 시작하기: Fancy Lateral Menu

이 기사의 측면 메뉴를 기억하십니까? 예, 이것은:



꽤 못생겼죠? 더 멋져보이게 해보자!

목록 중앙에



가장 제한적인 기능 중 하나를 제거하거나 최소한 변경하는 것부터 시작하겠습니다. 바로 목록입니다. 열로 변경하고 목록을 자식으로 추가합니다.

endDrawer: Container(
        width: 200,
        color: Colors.white,
        child: Column(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ListView.builder(
              shrinkWrap: true,
              physics: NeverScrollableScrollPhysics(),
              itemCount: 4,
              itemBuilder: (context, index) {
                return Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: GestureDetector(
                    onTap: () {
                      Navigator.pop(context);
                      setState(() {
                        item = index;
                      });
                    },
                    child: Text('Item $index')
                  ),
                );
              },
            ),
          ],
        ),
      ),


목록은 이제 열의 자식이며 열 높이를 설정하고 목록을 shrinkWrap로 설정하고(또는 목록이 제대로 렌더링되지 않음) 스크롤 가능한 동작을 차단해야 했습니다. 또한 더 깔끔한 모양을 얻기 위해 요소를 중앙에 배치하고 있습니다.

반올림



이제 Container를 ClipRRect로 래핑하여 보기 흉한 네모난 흰색 메뉴를 둥글게 만들고 메뉴에 멋진 곡선을 만들어 봅시다!

      endDrawer: ClipRRect(
        borderRadius: BorderRadius.only(topLeft: Radius.circular(24), bottomLeft: Radius.circular(24)),
        child: Container(
          width: 200,
          color: Colors.white,




이제 메뉴는 다음과 같습니다.

절반 작업 완료, 이제 고기 부분에 가자!

더 나은 아이템



항목에 대한 새로운 모양을 설정하고 클릭한 항목을 표시해 보겠습니다.

메뉴의 "둥근"전통을 유지하면서 ClipRRect 위젯과 멋진 빨간색을 사용하여 모든 버튼에 새 배경을 제공합니다. 목록 항목에 약간의 복잡성을 추가하여 기본 위젯에서 페이지 컨트롤을 유지 관리하는 호출 함수를 사용하여 완전히 새로운 항목StatelessWidget을 만들 것입니다.

ListView.builder(
                shrinkWrap: true,
                physics: NeverScrollableScrollPhysics(),
                itemCount: 4,
                itemBuilder: (context, index) {
                  return ListItem(
                    title: 'Item $index',
                    onClick: () {
                      Navigator.pop(context);
                      setState(() {
                        item = index;
                      });
                    },
                  );
                },
              ),


//That's our item
class ListItem extends StatelessWidget {
  final String title;
  final VoidCallback onClick;

  const ListItem({Key key, this.title, this.onClick}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 8, left: 8),
      child: GestureDetector(
        onTap: () => onClick(),
        child: ClipRRect(
          borderRadius: BorderRadius.only(topLeft: Radius.circular(30), bottomLeft: Radius.circular(30)),
          child: Container(
            color: Colors.red.shade500,
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Text(
                title,
                style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white, fontSize: 14),
              ),
            ),
          ),
        ),
      ),
    );
  }
}


최종 효과는 꽤 좋을 것입니다.



이제 하나의 항목을 "선택됨"으로 설정하여 다른 항목과 다르게 표시하려고 합니다. 따라서 "선택됨"속성을 추가하여 항목에 빨간색 배경이 아닌 주황색 배경이 있음을 알려줍니다.

//How the new value is set:
                  return ListItem(
                    title: 'Item $index',
                    selected: index == item,
                    //Rest of the item...

/**The list item:**/
final bool selected;

child: ClipRRect(
          borderRadius: BorderRadius.only(topLeft: Radius.circular(30), bottomLeft: Radius.circular(30)),
          child: Container(
            color: selected ? Colors.orangeAccent : Colors.red.shade500,
            child: Padding(
            //Rest of the item...


클릭 효과



마지막으로 CupertinoButton 위젯을 사용하여 항목에 클릭 효과를 추가합니다. 이번에도 내부에 CupertinoButton가 있는 사용자 지정 위젯을 사용합니다. 버튼이 자식 크기만큼 커지도록 하려면 minSize를 0으로 설정해야 합니다.

class TappableWidget extends StatelessWidget {
  final Widget child;
  final VoidCallback onTap;

  const TappableWidget({
    Key key,
    this.onTap,
    this.child,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return CupertinoButton(
        minSize: 0,
        padding: EdgeInsets.zero,
        onPressed: onTap,
        child: child
    );
  }
}

ListItem 위젯은 다음과 같습니다.

class ListItem extends StatelessWidget {
  final String title;
  final VoidCallback onClick;
  final bool selected;

  const ListItem({Key key, this.title, this.onClick, this.selected}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return TappableWidget(
      onTap: () => onClick(),
      child: Padding(
        padding: const EdgeInsets.only(bottom: 8, left: 8),
        child: ClipRRect(
          borderRadius: BorderRadius.only(topLeft: Radius.circular(30), bottomLeft: Radius.circular(30)),
          child: Container(
            width: MediaQuery.of(context).size.width,
            color: selected ? Colors.orangeAccent : Colors.red.shade500,
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Text(
                title,
                style: TextStyle(
                    fontWeight: FontWeight.bold,
                    color: Colors.white,
                    fontSize: 14
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}


클릭하는 동안 멋진 페이드 효과가 있는 최종 결과는 다음과 같습니다.



지금은 훨씬 나아졌습니다!



저희 메뉴가 전보다 훨씬 보기도 좋고, 상대적으로 쉬웠죠? 원하는 대로 메뉴를 사용자 정의할 수 있지만 새로운 애니메이션이나 동작을 추가하려면 코드를 완전히 변경해야 합니다. 다음 시간을 위해 저장하겠습니다. 계속 지켜봐!

좋은 웹페이지 즐겨찾기