Quantcast
Channel: Active questions tagged row - Stack Overflow
Viewing all articles
Browse latest Browse all 482

How to expand list items without affecting other items. (flutter)

$
0
0

I want to create the Netflix home page in flutter, and I'm stuck while creating this hover state.

enter image description here

I have created two base widgets. One for the number plus the thumbnail and the other one for the expanded view when the widget is hovered. Then I put them in a stack with an Inkwell where the onHover changes the state to show the expanded widget.

When I hover on the widget, it does switch between the normal state an expanded state, the problem comes when I try to put a list of these widgets together.

  1. When using row (or ListView) to put them together, after hovering, the expanded widget makes the other widgets move. (which is not the wanted behaviour, I want them to overlap)

enter image description here

  1. When I use it with stack, the widgets do overlap but now it isn't scrollable anymore.

enter image description here

I have added the link to the repo for anyone that wants to clone it and try running it themselves, I'm running it on flutter web.https://github.com/Advait1306/netflix-flutter

Widget with thumbnail and number:

class TopListItem extends StatelessWidget {  final int index;  const TopListItem({Key? key, required this.index}) : super(key: key);  @override  Widget build(BuildContext context) {    const double height = 250;    return SizedBox(      height: height,      child: Row(        mainAxisSize: MainAxisSize.min,        children: [          SvgPicture.asset("assets/numbers/$index.svg",              fit: BoxFit.fitHeight, height: height),          Transform.translate(              offset: const Offset(-30, 0),              child: Image.asset("assets/thumbnails/thumb1.jpg"))        ],      ),    );  }}

Expanded view widget:

import 'package:flutter/material.dart';class HoverMovieTrailer extends StatelessWidget {  const HoverMovieTrailer({Key? key}) : super(key: key);  @override  Widget build(BuildContext context) {    const textTheme = TextStyle(color: Colors.white);    return SizedBox(      width: 400,      height: 400,      child: Container(        clipBehavior: Clip.hardEdge,        decoration: BoxDecoration(            borderRadius: BorderRadius.circular(10),            color: const Color(0xFF242424)),        child: Column(          children: [            Image.asset("assets/backgrounds/background1.jpg"),            const SizedBox(              height: 20,            ),            Padding(              padding: const EdgeInsets.symmetric(horizontal: 18),              child: Row(                mainAxisAlignment: MainAxisAlignment.spaceBetween,                children: [                  Row(                    children: const [                      RoundIconButton(icon: Icons.play_arrow_outlined),                      SizedBox(width: 5),                      RoundIconButton(icon: Icons.add_outlined),                      SizedBox(width: 5),                      RoundIconButton(icon: Icons.thumb_up_alt_outlined),                      SizedBox(width: 5),                    ],                  ),                  Row(                    children: const [                      RoundIconButton(icon: Icons.keyboard_arrow_down_outlined),                    ],                  ),                ],              ),            ),            const SizedBox(              height: 20,            ),            Padding(              padding: const EdgeInsets.symmetric(horizontal: 18),              child: Row(                mainAxisAlignment: MainAxisAlignment.start,                children:  [                  const Text("98% Match",                    style: TextStyle(                      color: Colors.green,                      fontWeight: FontWeight.bold                    ),                  ),                  const SizedBox(width: 5),                  Container(                    padding: const EdgeInsets.all(1),                    decoration: BoxDecoration(                      border: Border.all(color: Colors.white, width: 1)                    ),                    child: const Text("18+",                      style: textTheme,                    ),                  ),                  const SizedBox(width: 5),                  const Text("4 Seasons",                    style: textTheme,                  ),                  const SizedBox(width: 5),                  Container(                    decoration: BoxDecoration(                        border: Border.all(color: Colors.white, width: 1)                    ),                    child: const Text("HD",                      style: textTheme,                    ),                  )                ],              ),            ),            const SizedBox(              height: 5,            ),            Padding(              padding: const EdgeInsets.all(18.0),              child: Row(                mainAxisAlignment: MainAxisAlignment.start,                children: [                  const Text("Captivating",                    style: textTheme,                  ),                  const SizedBox(width: 5),                  Container(                    width: 5,                    height: 5,                    decoration: const BoxDecoration(                      shape: BoxShape.circle,                      color: Colors.white54                    ),                  ),                  const SizedBox(width: 5),                  const Text("Exciting",                    style: textTheme,                  ),                  const SizedBox(width: 5),                  Container(                    width: 5,                    height: 5,                    decoration: const BoxDecoration(                        shape: BoxShape.circle,                        color: Colors.white54                    ),                  ),                  const SizedBox(width: 5),                  const Text("Docuseries",                    style: textTheme,                  ),                ],              ),            ),          ],        ),      ),    );  }}class RoundIconButton extends StatelessWidget {  final IconData icon;  const RoundIconButton({Key? key, required this.icon}) : super(key: key);  @override  Widget build(BuildContext context) {    return Container(      decoration: BoxDecoration(          shape: BoxShape.circle,          color: Colors.transparent,          border: Border.all(width: 2, color: Colors.white)),      margin: const EdgeInsets.all(1),      child: IconButton(        onPressed: () {},        icon: Icon(icon),        color: Colors.white,      ),    );  }}

Combining the widgets in the single widget:

import 'dart:developer';import 'package:flutter/material.dart';import 'package:netflix_flutter/widgets/hover_movie_trailer.dart';import 'package:netflix_flutter/widgets/top_list_item.dart';class TopListItemWithHover extends StatefulWidget {  const TopListItemWithHover({Key? key}) : super(key: key);  @override  State<TopListItemWithHover> createState() => _TopListItemWithHoverState();}class _TopListItemWithHoverState extends State<TopListItemWithHover> {  bool hover = false;  @override  Widget build(BuildContext context) {    return InkWell(      onTap: (){},      onHover: (value){        log("Hover value: $value");        setState(() {          hover = value;        });      },      child: Stack(        clipBehavior: Clip.none,        children: [          TopListItem(index: 1),          if(hover) HoverMovieTrailer(),        ],      ),    );  }}

Lists:

import 'package:flutter/material.dart';import 'package:netflix_flutter/widgets/hover_movie_trailer.dart';import 'package:netflix_flutter/widgets/top_list_item.dart';import 'package:netflix_flutter/widgets/top_list_item_with_hover.dart';void main() {  runApp(const MyApp());}class MyApp extends StatelessWidget {  const MyApp({Key? key}) : super(key: key);  @override  Widget build(BuildContext context) {    return MaterialApp(      title: 'Flutter Demo',      theme: ThemeData(        primarySwatch: Colors.blue,      ),      home: const MyHomePage(title: 'Flutter Demo Home Page'),    );  }}class MyHomePage extends StatefulWidget {  const MyHomePage({Key? key, required this.title}) : super(key: key);  final String title;  @override  State<MyHomePage> createState() => _MyHomePageState();}class _MyHomePageState extends State<MyHomePage> {  @override  Widget build(BuildContext context) {    return Scaffold(      body: Column(        mainAxisAlignment: MainAxisAlignment.start,        crossAxisAlignment: CrossAxisAlignment.start,        children: [          SingleChildScrollView(            scrollDirection: Axis.horizontal,            child: SizedBox(              height: 400,              child: ListView.builder(                shrinkWrap: true,                scrollDirection: Axis.horizontal,                clipBehavior: Clip.none,                itemCount: 8,                itemBuilder: (context, index) {                  return TopListItemWithHover();                },              ),            ),          ),          const SizedBox(height: 50),          SingleChildScrollView(            child: SizedBox(              height: 400,              child: Stack(                fit: StackFit.passthrough,                children: [                  for (var i = 10; i >= 0; i--)                    Positioned(                      left: (i) * 300,                      child: TopListItemWithHover(),                    )                ],              ),            ),          )        ],      ),    );  }}

Viewing all articles
Browse latest Browse all 482

Latest Images

Trending Articles



Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>