FlutterComponent最佳實踐之Shadow怎麼就這麼簡單
設計三件寶,模糊陰影和圓角。這些在原生開發中被設計摧殘N年的東西,在Flutter中,居然是輕而易舉的實現。
新增Shadow
在Flutter中,Container可以使用BoxDecoration來新增Shadow,如果是單獨的Widget,可以通過DecoratedBox來新增陰影。
下面我們以Container為例,演示Flutter的Shadow實現。原始效果如圖所示。
child: Container( height: 100, width: 100, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), shape: BoxShape.rectangle, boxShadow: const [ BoxShadow(), ], ), )
在Flutter中,陰影本身並不模糊,其大小也足以使其可見。BoxShadow有幾個屬性可以讓我們對它進行配置,我們將使用這三個屬性。
- Offset
- Blur radius
- Spread radius
由此可見,Flutter不愧是Chrome團隊的產物,這些引數和CSS中的Shadow引數是一致的,當然這也方便了開發者和設計師的溝通。
首先,我們來看一下Offset。它代表陰影相對於當前Widget的偏移量,它的效果就好比我們將光源放置在物體的左上角,那麼陰影將偏移至右下角這樣的效果。
我們設定Offset(4, 4),效果如上所示。
你可以發現,陰影不會被Blur,所以,我們使用blurRadius這個引數,來控制陰影被Blur的程度,通過spreadRadius來控制陰影向外擴散的程度,當你不設定它時,陰影與原始Widget是同樣的大小。
瞭解了這些引數之後,我們找到設計稿,找到相應的引數配置,就得到了下面這個陰影。
child: Container( height: 100, width: 100, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), shape: BoxShape.rectangle, boxShadow: [ BoxShadow( color: Colors.black.withAlpha(25), offset: const Offset(0, 14), blurRadius: 24, spreadRadius: 0, ), ], ), )
這可能就是國內設計師夢寐以求的陰影吧。
PhysicalModel & PhysicalShape
Flutter的元件茫茫多,PhysicalModel和PhysicalShape這兩個元件,也同樣能模擬陰影的實現,但它的實現實際上是Material Design中的elevation的實現效果,程式碼如下所示。
return Center(
child: PhysicalModel(
borderRadius: BorderRadius.circular(20),
color: Colors.white,
elevation: 16,
shadowColor: Colors.black.withAlpha(25),
child: const SizedBox(
height: 100,
width: 100,
),
),
);
Text Shadow
在TextStyle中,同樣支援Shadows引數。
child: Text(
"中華人民共和國",
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.w700,
shadows: [
Shadow(
color: Colors.red.shade300,
blurRadius: 8,
offset: const Offset(2, 2),
)
],
),
)
除此之外,文字陰影還有一種實現,那就是通過BackdropFilter來進行模擬,BackdropFilter的作用也是建立Blur效果,所以,它也可以用來替代陰影,但是效果沒有Shadow靈活(類似的還有ImageFiltered)。
var style = const TextStyle(
fontSize: 32,
fontWeight: FontWeight.w700,
);
var text = "中華人民共和國";
return Center(
child: Stack(
children: [
Text(
text,
style: style,
),
BackdropFilter(
filter: ui.ImageFilter.blur(
sigmaX: 2,
sigmaY: 2,
),
child: Text(
text,
style: style,
),
)
],
),
);
Neumorphism
Neumorphism是一種全新的設計風格,通常被稱為新的擬物風格,它其實就是通過陰影來實現的。
擬態陰影通常都由兩個Shadow組合而成,一個Shadow比Widget Color更淺,另一個Shadow更深,我們通過下面這個例子來看下如何實現擬態陰影。
return Center(
child: Text(
'中華人民共和國',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 40,
shadows: [
const Shadow(
offset: Offset(3, 3),
color: Colors.black38,
blurRadius: 10,
),
Shadow(
offset: const Offset(-3, -3),
color: Colors.white.withOpacity(0.85),
blurRadius: 10,
),
],
color: Colors.grey.shade300,
),
),
);
在shadows中配置兩個相對於中心互相偏離的Shadow,並使得它們的顏色是互補的,例如黑和白,而Widget Color通常和背景色相同。
例如下面這樣的配置:
light mode:
Background color: Color(0xFFEFEEEE)
Light shadow: Colors.white.withOpacity(0.8),
Dark shadow: Colors.black.withOpacity(0.1)
dark mode:
Background color: Color(0xFF292D32)
Light shadow: Colors.white.withOpacity(0.1),
Dark shadow: Colors.black.withOpacity(0.4)
如果是Container的話,類似上面的Shadow實現,程式碼如下所示。
return Center(
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Colors.grey.shade300,
boxShadow: [
const BoxShadow(
offset: Offset(10, 10),
color: Colors.black38,
blurRadius: 20,
),
BoxShadow(
offset: const Offset(-10, -10),
color: Colors.white.withOpacity(0.85),
blurRadius: 20,
),
],
),
),
);
由此可見,擬物陰影的核心,實際上就是兩組互補色的陰影疊加,當Widget Color和背景色相同時,在邊緣就會產生類似擬物的陰影風格。
通過下面這個工具,你可以方便的設計擬物陰影,找到不同的顏色下的最佳效果。