How to display image with top and bottom gradient shadow in flutter?
Asked Answered
E

3

15

I am working on flutter to display a image with top and bottom gradient overlay. Some portion of image top and bottom should be display with shadow like covered by other color like gray.

Please find the attached image for reference which is drawn by me.

I have used Container with CachedNetworkImage. And tried using BoxDecoration. Which is not giving me the expected result. The effect with the below code only applying shadow below the image. But i would like to display on top of my image as a overlay top and bottom gradient effect.

Please provide me suggestion.

Code reference:

 Container(
  height: 174.0,
  width: 116.0,
    decoration: new BoxDecoration(
    boxShadow: [
    BoxShadow(
    color: Colors.red,
    blurRadius: 20.0, // has the effect of softening the shadow
    spreadRadius: 5.0, // has the effect of extending the shadow
    offset: Offset(
    10.0, // horizontal, move right 10
    10.0, // vertical, move down 10
),
)
],),
child: CachedNetworkImage(...),

Image for representing expectation:

enter image description here

Elanorelapid answered 31/3, 2020 at 13:25 Comment(0)
R
9

I wrote down a code below for the top and bottom shadow box decoration, this means there are going to be two containers. You can use this solution in two ways,

  1. Nested containers, which is to put your image inside Container(topShadow) => Container(bottomShadow)=> Image

  2. Put your 2 containers and your image inside Stack, align the containers at the top and at the bottom and give your containers fixed heights like the area you marked in your picture. (Make sure the containers are below the image item inside stack otherwise the shadow will be covered by the image)

 decoration: new BoxDecoration(
                gradient: new LinearGradient(
                  end: const Alignment(0.0, -1),
                  begin: const Alignment(0.0, 0.6),
                  colors: <Color>[
                    const Color(0x8A000000),
                    Colors.black12.withOpacity(0.0)
                  ],
                ),

              ),


decoration: new BoxDecoration(
                gradient: new LinearGradient(
                  end: const Alignment(0.0, -1),
                  begin: const Alignment(0.0, 0.6),
                  colors: <Color>[
                    const Color(0x8A000000),
                    Colors.black12.withOpacity(0.0)
                  ],
                ),

              ),

Second approach(point 2) working code:

Stack(
            children: <Widget>[
            //image code
            Image(..),
            //top grey shadow
            Align(
                alignment: Alignment.topCenter,
                child: Container(
                  height: 50,
                  width: double.infinity,
                  decoration: new BoxDecoration(
                    gradient: new LinearGradient(
                      end: const Alignment(0.0, 0.4),
                      begin: const Alignment(0.0, -1),
                      colors: <Color>[
                        const Color(0x8A000000),
                        Colors.black12.withOpacity(0.0)
                      ],
                    ),

                  ),
                ),
              ),
              //bottom grey shadow
              Align(
                alignment: Alignment.bottomCenter,
                child: Container(
                  height: 50,
                  width: double.infinity,
                  decoration: new BoxDecoration(
                    gradient: new LinearGradient(
                      end: const Alignment(0.0, -1),
                      begin: const Alignment(0.0, 0.4),
                      colors: <Color>[
                        const Color(0x8A000000),
                        Colors.black12.withOpacity(0.0)
                      ],
                    ),

                  ),
                ),
              ),
            
            ],),
Ranket answered 31/3, 2020 at 14:51 Comment(6)
Thanks @Ranket for the valuable response. Its worked for me perfectly. You saved my lot of time.Elanorelapid
For the top container, i used the following values "end: const Alignment(0.0, 0.6), begin: const Alignment(0.0, -1),"Elanorelapid
I am glad it worked, you can play with the positions and the colors, which one have you used the 1st or the 2nd ?Ranket
I used the second approach, used stack to hold imageview and my 2 containers(top and bottom) with in Align() as parent. So that one i set it on topCenter and another one set it on bottomCenter.Elanorelapid
thanks for editing, I would prefer the 2nd approach too .Ranket
2nd approach is the way to go but alignment is not working so just replace them with positioned widget and you are good to go. plus if their are some content in the shadow container the remove the height and add some padding solves all the issues.Haslet
H
25

as an option, you can control spread black color by changing stops values

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Container(
            width: 116.0,
            height: 174.0,
            foregroundDecoration: BoxDecoration(
              gradient: LinearGradient(
                colors: [Colors.black, Colors.transparent, Colors.transparent, Colors.black],
                begin: Alignment.topCenter,
                end: Alignment.bottomCenter,
                stops: [0, 0.2, 0.8, 1],
              ),
            ),
            child: Image.network('https://i.picsum.photos/id/200/400/600.jpg'),
          ),
        ),
      ),
    );
  }
}

enter image description here

Humph answered 31/3, 2020 at 15:5 Comment(1)
I have implemented the way suggested by @Henok. Yes your approach also will work. Appreciates your response.Elanorelapid
R
9

I wrote down a code below for the top and bottom shadow box decoration, this means there are going to be two containers. You can use this solution in two ways,

  1. Nested containers, which is to put your image inside Container(topShadow) => Container(bottomShadow)=> Image

  2. Put your 2 containers and your image inside Stack, align the containers at the top and at the bottom and give your containers fixed heights like the area you marked in your picture. (Make sure the containers are below the image item inside stack otherwise the shadow will be covered by the image)

 decoration: new BoxDecoration(
                gradient: new LinearGradient(
                  end: const Alignment(0.0, -1),
                  begin: const Alignment(0.0, 0.6),
                  colors: <Color>[
                    const Color(0x8A000000),
                    Colors.black12.withOpacity(0.0)
                  ],
                ),

              ),


decoration: new BoxDecoration(
                gradient: new LinearGradient(
                  end: const Alignment(0.0, -1),
                  begin: const Alignment(0.0, 0.6),
                  colors: <Color>[
                    const Color(0x8A000000),
                    Colors.black12.withOpacity(0.0)
                  ],
                ),

              ),

Second approach(point 2) working code:

Stack(
            children: <Widget>[
            //image code
            Image(..),
            //top grey shadow
            Align(
                alignment: Alignment.topCenter,
                child: Container(
                  height: 50,
                  width: double.infinity,
                  decoration: new BoxDecoration(
                    gradient: new LinearGradient(
                      end: const Alignment(0.0, 0.4),
                      begin: const Alignment(0.0, -1),
                      colors: <Color>[
                        const Color(0x8A000000),
                        Colors.black12.withOpacity(0.0)
                      ],
                    ),

                  ),
                ),
              ),
              //bottom grey shadow
              Align(
                alignment: Alignment.bottomCenter,
                child: Container(
                  height: 50,
                  width: double.infinity,
                  decoration: new BoxDecoration(
                    gradient: new LinearGradient(
                      end: const Alignment(0.0, -1),
                      begin: const Alignment(0.0, 0.4),
                      colors: <Color>[
                        const Color(0x8A000000),
                        Colors.black12.withOpacity(0.0)
                      ],
                    ),

                  ),
                ),
              ),
            
            ],),
Ranket answered 31/3, 2020 at 14:51 Comment(6)
Thanks @Ranket for the valuable response. Its worked for me perfectly. You saved my lot of time.Elanorelapid
For the top container, i used the following values "end: const Alignment(0.0, 0.6), begin: const Alignment(0.0, -1),"Elanorelapid
I am glad it worked, you can play with the positions and the colors, which one have you used the 1st or the 2nd ?Ranket
I used the second approach, used stack to hold imageview and my 2 containers(top and bottom) with in Align() as parent. So that one i set it on topCenter and another one set it on bottomCenter.Elanorelapid
thanks for editing, I would prefer the 2nd approach too .Ranket
2nd approach is the way to go but alignment is not working so just replace them with positioned widget and you are good to go. plus if their are some content in the shadow container the remove the height and add some padding solves all the issues.Haslet
D
0

Just wrap your widget.

foregroundDecoration: BoxDecoration(
          gradient: LinearGradient(
            colors: [Colors.grey, Colors.transparent, Colors.transparent, Colors.transparent],
            begin: Alignment.topCenter,
            end: Alignment.bottomCenter,
            stops: [0, 0.2, 0.2, 0],
          ),
        ),
Deliver answered 8/11, 2023 at 12:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.