Liquid Glass Easy

شريط التبويبات

تبويبات في كبسولة زجاجية واحدة، بلا حاجة إلى هيكل.

LiquidGlassTabBar هو الشريط وحده: أنت تضعه، وأنت تحفظ الفهرس، وأنت تقرّر ما تفعله الصفحة به. وهو كالشريط العلوي عدسةٌ واحدة، فيريد على Skia LiquidGlassView أباً خلفيته هي الصفحة التي ينبغي أن يكسرها.

Dart
LiquidGlassTabBar(
  items: const [
    LiquidGlassTabBarItem(
      icon: Icons.today_outlined,
      selectedIcon: Icons.today_rounded,
      label: 'Today',
    ),
    LiquidGlassTabBarItem(icon: Icons.bar_chart_rounded, label: 'Charts'),
  ],
  selectedIndex: index,
  onChanged: (i) => setState(() => index = i),
  width: 330,
)

ليس شرطاً أن تكون تلك الخلفية هي الصفحة. فعرض الشريط داخل بطاقة يتوسّط بالشريط بطاقةً ويسلّمه سطحَ البطاقة نفسه، فيقف الزجاج عند حافتها — أما الصفحة حولها فلا تُلتقط ولا تنكسر، وليس خلف الشريط سوى مادة البطاقة. والقرار الوحيد هو أيّ مسار يحتاجه الشريط، وresolveGlassPill() يجيب عنه على المُصيِّر الحالي: صحيح فتريد الحبةُ الزجاجية آلةَ الشريط ذات العرضين عبر buildGlassPillBar(body: …)، وخطأ فالمستوى المسطّح عدسةٌ واحدة، ويكفيه LiquidGlassView واحد فوق البطاقة.

Dart
final bar = LiquidGlassTabBar(
  items: _items,
  selectedIndex: index,
  onChanged: (i) => setState(() => index = i),
  width: cardWidth - 26,
  // The card is the whole world the bar sits in: dead centre, no gap.
  alignment: Alignment.center,
  margin: EdgeInsets.zero,
);

SizedBox(
  width: cardWidth,
  height: 112,
  child: ClipRRect(
    borderRadius: BorderRadius.circular(26),
    child: bar.resolveGlassPill()
        ? bar.buildGlassPillBar(body: cardSurface)
        : LiquidGlassView(
            backgroundWidget: cardSurface,
            child: Center(child: bar),
          ),
  ),
)
المعاملالافتراضيما يفعله
itemsعناصر LiquidGlassTabBarItem: أيقونة وأيقونة محدَّدة ونص.
selectedIndex / onChangedالفهرس ملكك.
width / height320 / 64الكبسولة.
margin / itemPadding / alignmentأين يجلس الشريط وكيف تتباعد العناصر بداخله.
itemStyleLiquidGlassTabItemStyle()ألوان الأيقونات والنصوص ومقاساتها وأوزانها — انظر أدناه.
pillStyleLiquidGlassTabPillStyle()كل ما يخصّ علامة التحديد — انظر أدناه.
style / visibilitynull / trueزجاج كبسولة الشريط نفسه، والمفتاح الذي يطفئه.

تنسيق العناصر#

الألوان والمقاسات مجمَّعة لا مسطّحة، فينتقل مظهر الشريط كقيمة واحدة. وunderGlassIconSize وunderGlassLabelFontSize هما الزوج اللافت: فالشريط ذو الحبة الزجاجية يرسم كل تبويب مرتين — مرة عادية ومرة تحت الحبة — ويتيح هذان أن تكون النسخة التي تحت الزجاج بمقاس مختلف، وبهذا يُلغى أثر التكبير.

Dart
itemStyle: const LiquidGlassTabItemStyle(
  selectedColor: Colors.white,
  unselectedColor: Colors.white70,
  iconSize: 24,
  underGlassIconSize: 21,      // cancels the pill's magnification
  labelFontSize: 10.5,
  selectedFontWeight: FontWeight.w600,
)

رموز مخصصة#

التبويبات ليست محصورة في IconData. مرّر iconBuilder — أو labelBuilder — فتعمل SvgPicture وImage وCustomPaint جميعها.

Dart
LiquidGlassTabBarItem(
  label: 'Home',
  iconBuilder: (context, i) => SvgPicture.asset(
    i.selected ? 'assets/home_fill.svg' : 'assets/home.svg',
    width: i.size,
    height: i.size,
    colorFilter: ColorFilter.mode(i.color, BlendMode.srcIn),
  ),
)

يُسلَّم البنّاء LiquidGlassGlyph: اللون الذي حسمه الشريط للطبقة المرسومة، ومقاس صندوق الرمز، وهل هذه الطبقة هي المحدَّدة، وهل هي النسخة التي تحت الزجاج. لوّن بـ i.color فيتبع رسمُك اللوحةَ وكشفَ الحبة المتحولة. أما الرسم متعدد الألوان فيمكنه تجاهل اللون تماماً.

المستويان#

`pillStyle.mode`ما هو التحديد
noneإبراز شفاف داخل عدسة الشريط الواحدة. فوري، أو انزلاق ناعم مع animated: true. ورخيص في كل مكان.
impellerOnlyالحبة المتحولة الزجاجية حيث تكون مجانية، والإبراز على Skia.
both (الافتراضي)الحبة المتحولة على المحركين — سطح كاسر ثانٍ يثني الشريط نفسه. وعلى Skia تحت الزجاج الخفيف فقط — انظر الملاحظة أدناه.

بقية الحبة#

يحمل LiquidGlassTabPillStyle التحديد كله: هل يظهر أصلاً، ولونه وضبابيته، وشكله، والزجاج الذي يلبسه مرفوعاً والأسلوب البسيط الذي يلبسه ساكناً، وسرعة سفره، وكيف يتشوّه في الطريق.

الحقلالافتراضيما يفعله
showtrueرسم علامة تحديد من الأساس.
animatedfalseفي وضع none، انزلاق الإبراز بدل قفزه.
color / blur0x2EAEAEB2 / —تعبئة العلامة وضبابية خلفيتها.
growHeight9كم يزيد ارتفاع الحبة عن صف العناصر.
distortion / distortionWidth / magnification0.04 / 12 / 1انكسار الحبة نفسها، فوق الشريط تحتها.
travelStiffness / travelDamping280 / 31.4النابض الذي يحملها بين التبويبات.
glassStyle / rest / shapenullتجاوزات كاملة لمظهر الرفع ومظهر السكون والمحيط.

تتشوّه الحبة المتحركة أثناء سفرها، بالنموذج نفسه الذي يستخدمه مقبض المزلاج: فـpillStyle.motion هو LiquidGlassLensMotionSpec، مضبوط هنا بسقف أرفق لمسافة التبويبات. انظر الحركة.

شريط مستقل على Impeller#

Dart
Stack(
  children: [
    MyPage(),
    LiquidGlassTabBar.withImpeller(
      items: items,
      selectedIndex: index,
      onChanged: (i) => setState(() => index = i),
    ),
  ],
)

.withImpeller هو الشريط بلا جسم: بلا هيكل وبلا صفحة تُسلَّم إليه. وهو يتمدّد ليملأ، فضعه آخر ابن في Stack. وعلى Skia يتراجع إلى شريط مصنفر يظل يُظهر المحتوى عبره.

التعليقات

التعليقات هي مناقشات GitHub — يمكنك الرد من أيٍّ من المكانين.