skip to Main Content

I want to make this UI, but it seems really hard. The card Images with numbers and shadow on them.

What I want

2

Answers


  1. Here is the sample code for you, you can do some more configurations if you want to

    ListView.builder(
                        shrinkWrap: true,
                        scrollDirection: Axis.vertical,
                        itemCount: 5,
                        itemBuilder: (context, index) {
                          return Container(
                            height: 200,
                            width: 200,
                            child: Stack(
                              children: [
                                Image.network(
                                  'https://picsum.photos/250?image=$index',
                                  fit: BoxFit.fill,
                                ),
                                Align(
                                  alignment: Alignment.bottomLeft,
                                  child: Stack(
                                    children: <Widget>[
                                      // Stroked text as border.
                                      Text(
                                        "${index + 1}",
                                        style: TextStyle(
                                          fontWeight: FontWeight.bold,
                                          fontSize: 100,
                                          shadows: [
                                            Shadow(
                                              blurRadius: 10.0,
                                              color: Colors.grey.shade600,
                                              offset: const Offset(5, 5),
                                            ),
                                            // font size and color of the text
                                          ],
                                          foreground: Paint()
                                            ..style = PaintingStyle.stroke
                                            ..strokeWidth = 6
                                            ..color = Colors.grey.shade500,
                                        ),
                                      ),
                                      // Solid text as fill.
                                      Text(
                                        "${index + 1}",
                                        style: const TextStyle(
                                          fontWeight: FontWeight.bold,
                                          fontSize: 100,
                                          color: Colors.black,
                                        ),
                                      ),
                                    ],
                                  ),
                                )
                              ],
                            ),
                          );
                        },
                      )
    

    Output will look like this

    enter image description here

    Login or Signup to reply.
  2. Code solution with comments, uploaded to GitHub:

    [GitHub Repository] https://github.com/Itay-Lavi/flutter-netflix-numbering-ui

    [Website Demo] https://movies-nunbering-ui.netlify.app/#/

    Image:
    enter image description here

    Main Widget:

    import 'package:flutter/gestures.dart';
    import 'package:flutter/material.dart';
    
    import './cards.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          scrollBehavior: MyCustomScrollBehavior(),
          title: 'Netflix Stacked Listview Demo',
          home: const Cards(),
        );
      }
    }
    
    //Make Drag available in horizontal in web
    class MyCustomScrollBehavior extends MaterialScrollBehavior {
      @override
      Set<PointerDeviceKind> get dragDevices => {
            PointerDeviceKind.touch,
            PointerDeviceKind.mouse,
          };
    }
    

    Cards Widget:

    import 'package:flutter/material.dart';
    import './item_card.dart';
    
    class Cards extends StatefulWidget {
      const Cards({super.key});
    
      @override
      State<Cards> createState() => _CardsState();
    }
    
    class _CardsState extends State<Cards> {
      final ScrollController controller = ScrollController();
    
      @override
      void initState() {
        super.initState();
        //Runs only after all widgets builded
        WidgetsBinding.instance.addPostFrameCallback((_) => _scrollToEnd(context));
      }
    
    //Scroll to the start, because list is reversed
      void _scrollToEnd(BuildContext context) {
        controller.jumpTo(controller.position.maxScrollExtent);
      }
    
      @override
      Widget build(BuildContext context) {
        List<ItemCard> cards = [];
    
        stackedList() {
          for (int i = 0; i < 9; i++) {
            cards.add(ItemCard(index: i));
          }
          //Reversed to make up on the reverse boolean in listview
          cards = cards.reversed.toList();
        }
    
    //generate array, should get array from state management / API
        stackedList();
    
        return Scaffold(
          backgroundColor: const Color.fromARGB(255, 8, 8, 8),
          body: ListView.builder(
            controller: controller,
            //Reverse is set to make left card stacked over the right card
            reverse: true,
            scrollDirection: Axis.horizontal,
            itemBuilder: (context, index) {
              return Align(
                alignment: Alignment.center,
                widthFactor: 0.94, //Cuts the card (Cutting the number)
                child: cards[index],
              );
            },
            itemCount: cards.length,
          ),
        );
      }
    }
    

    Card Widget:

    import 'package:flutter/material.dart';
    
    class ItemCard extends StatelessWidget {
      final int index;
    
      const ItemCard({
        Key? key,
        required this.index,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        final String cardNumStr = (index + 1).toString();
        const double fontSize = 280;
        const double fontHeight =
            1.66; //RichText vertical padding, need to be calibrated every change in font or height size
        const Color borderColor = Color.fromARGB(255, 191, 191, 191);
    
        return SizedBox(
          width: 325,
          height: 380,
          child: Stack(
            children: [
              Align(
                alignment: Alignment.centerRight,
                child: Container(
                  //Card Shadow
                  decoration: const BoxDecoration(
                    boxShadow: [
                      BoxShadow(
                        color: Color.fromARGB(255, 8, 8, 8),
                        blurRadius: 20.0,
                        offset: Offset(30, 0),
                      ),
                    ],
                  ),
                  width: 250,
                  height: 380,
                  //Image Card
                  child: Card(
                    color: Colors.transparent,
                    child: ClipRRect(
                      borderRadius: BorderRadius.circular(10),
                      child: Image.network(
                        'https://picsum.photos/id/$index/250/400',
                        fit: BoxFit.cover,
                      ),
                    ),
                  ),
                ),
              ),
              //Number Text
              Align(
                alignment: Alignment.bottomLeft,
                child: Stack(
                  children: [
                    //Grey Border With Shadow
                    Text(
                      cardNumStr,
                      style: TextStyle(
                          shadows: const [
                            Shadow(blurRadius: 12, color: borderColor),
                          ],
                          height: fontHeight,
                          fontWeight: FontWeight.bold,
                          fontSize: fontSize,
                          //www.kindacode.com/snippet/adding-a-border-to-text-in-flutter/
                          foreground: Paint()
                            ..style = PaintingStyle.stroke
                            ..strokeWidth = 6.5
                            ..color = borderColor),
                    ),
                    //Black Text Over White Text
                    Text(
                      cardNumStr,
                      style: const TextStyle(
                        height: fontHeight,
                        fontWeight: FontWeight.bold,
                        fontSize: fontSize,
                        color: Color.fromARGB(255, 18, 18, 18),
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search