Vintage appMaker의 Tech Blog

[Flutter] Widget에 그라데이션(Gradation) 효과주기 - ShaderMask, BoxDecoration 본문

Source code or Tip/Flutter & Dart

[Flutter] Widget에 그라데이션(Gradation) 효과주기 - ShaderMask, BoxDecoration

VintageappMaker 2022. 7. 28. 08:59

 


App에서 그라데이션을 적용해야 할 경우는 종종 발생한다. 배경만 간단하게 적용해야 할 경우라면 Container의 파라메터 decoration에 BoxDecoration 위젯을 사용하면 된다. 그러나 이미지나 다른 위젯 전체 에 적용해야 한다면 ShaderMask를 사용해야 한다.

 

 

BoxDecoration class - painting library - Dart API

An immutable description of how to paint a box. The BoxDecoration class provides a variety of ways to draw a box. The box has a border, a body, and may cast a boxShadow. The shape of the box can be a circle or a rectangle. If it is a rectangle, then the bo

api.flutter.dev

 

 

ShaderMask class - widgets library - Dart API

A widget that applies a mask generated by a Shader to its child. For example, ShaderMask can be used to gradually fade out the edge of a child by using a ui.Gradient.linear mask. This example makes the text look like it is on fire: assignment ShaderMask( s

api.flutter.dev

 

🍕ShaderMask를 이해하기 쉽게 설명한 강의

 


다음은 ShaderMask와 Container의 BoxDecoration을 사용한 간단한 예제이다. 

 

 

Shader를 사용하기 위해 LinearGradinet()를 사용했는데, 여기서 주의깊게 볼 것은 colors 배열을 Widget 전체 비율(height)에서 들어가야할 색상값을 나열했다는 것이다. Flutter 공식문서에는 언급되지 않았지만, stops 필드에 수치를 넣는 것보다는 colors에 위와 같이 하는 것이 직관적으로 그라데이션 효과가 좋았다.

 

[전체소스]

import 'package:flutter/material.dart';

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

// https://www.youtube.com/watch?v=JD5IDUD-Moo
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final title = '그라데이션 예제';

    Widget BoxDecoItem(String msg) {
      return Center(
        child: Container(
          decoration: BoxDecoration(
              gradient: LinearGradient(
            begin: Alignment.topRight,
            end: Alignment.bottomLeft,
            colors: [
              Color.fromARGB(99, 69, 11, 11),
              Color.fromARGB(255, 69, 11, 11),
            ],
          )),
          child: Center(
            child: Container(
              padding: const EdgeInsets.all(10),
              child: Row(
                children: [
                  Text(
                    msg,
                    style: TextStyle(
                      fontSize: 28.0,
                      fontWeight: FontWeight.bold,
                      color: Colors.white,
                    ),
                  ),
                  Spacer(),
                  Text(
                    "(BoxDecoration)",
                    style: TextStyle(
                      fontSize: 15.0,
                      fontWeight: FontWeight.bold,
                      color: Colors.white,
                    ),
                  )
                ],
              ),
            ),
          ),
        ),
      );
    }

    Widget ShaderItem() {
      return Center(
        child: Stack(
          children: [
            ShaderMask(
                shaderCallback: (Rect bound) {
                  return LinearGradient(
                      begin: Alignment.topCenter,
                      end: Alignment.bottomCenter,
                      // 그라데이션 분포 비율로 컬러를 설정했음
                      colors: [
                        Colors.transparent,
                        Colors.transparent,
                        Colors.transparent,
                        Colors.transparent,
                        Colors.transparent,
                        Color.fromARGB(99, 69, 11, 11),
                        Color.fromARGB(199, 69, 11, 11),
                        Color.fromARGB(255, 69, 11, 11),
                      ]).createShader(bound);
                },
                blendMode: BlendMode.color,
                child: Image.network(
                    "https://d2x8kymwjom7h7.cloudfront.net/live/application_no/96001/application_no/96001/default/3d020d8552fb4ef98b9d82930a83335e.png")),
            Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    'ShaderMask 입니다.',
                    style: TextStyle(
                      fontSize: 18.0,
                      fontWeight: FontWeight.bold,
                      color: Color.fromARGB(199, 69, 11, 11),
                    ),
                  ),
                ],
              ),
            )
          ],
        ),
      );
    }

    return MaterialApp(
      title: title,
      home: Scaffold(
        appBar: AppBar(title: Text(title)),
        body: ListView(
          children: <Widget>[
            Center(child: Text("원본이미지")),
            Image.network(
                "https://d2x8kymwjom7h7.cloudfront.net/live/application_no/96001/application_no/96001/default/3d020d8552fb4ef98b9d82930a83335e.png"),
            for (var i = 0; i < 10; i++) ...{
              Column(
                children: [BoxDecoItem('${i}'), ShaderItem()],
              )
            }
          ],
        ),
      ),
    );
  }
}

 

Comments