Widgets

Button

Giriş

Nylo Website kullanıma hazır sekiz button stili ile bir Button sınıfı sağlar. Her button şunlar için yerleşik destek sunar:

  • Async yükleme durumları -- onPressed'den bir Future döndürün ve button otomatik olarak bir yükleme göstergesi gösterir
  • Animasyon stilleri -- clickable, bounce, pulse, squeeze, jelly, shine, ripple, morph ve shake efektleri arasından seçin
  • Splash stilleri -- ripple, highlight, glow veya ink dokunma geri bildirimi ekleyin
  • Form gönderimi -- bir button'ı doğrudan bir NyFormData örneğine bağlayın

Uygulamanızın button tanımlarını lib/resources/widgets/buttons/buttons.dart dosyasında bulabilirsiniz. Bu dosya, her button türü için statik metotlar içeren bir Button sınıfı içerir ve projeniz için varsayılan değerleri özelleştirmeyi kolaylaştırır.

Temel Kullanım

Button sınıfını widget'larınızın herhangi bir yerinde kullanın. İşte bir sayfa içindeki basit bir örnek:

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: SafeArea(
      child: Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          children: [
            Button.primary(
              text: "Sign Up",
              onPressed: () {
                routeTo(SignUpPage.path);
              },
            ),

            SizedBox(height: 12),

            Button.secondary(
              text: "Learn More",
              onPressed: () {
                routeTo(AboutPage.path);
              },
            ),

            SizedBox(height: 12),

            Button.outlined(
              text: "Cancel",
              onPressed: () {
                Navigator.pop(context);
              },
            ),
          ],
        ),
      ),
    ),
  );
}

Her button türü aynı kalıbı izler -- bir text etiketi ve bir onPressed callback'i geçirin.

Mevcut Button Türleri

Tüm button'lara statik metotlar kullanarak Button sınıfı üzerinden erişilir.

Primary

Temanızın birincil rengini kullanan, gölgeli dolgulu bir button. Ana eylem çağrısı öğeleri için en uygun.

Button.primary(
  text: "Sign Up",
  onPressed: () {
    // Handle press
  },
)

Secondary

Daha yumuşak bir yüzey rengi ve hafif gölge ile dolgulu bir button. Birincil button'ın yanındaki ikincil eylemler için uygundur.

Button.secondary(
  text: "Learn More",
  onPressed: () {
    // Handle press
  },
)

Outlined

Kenarlık çizgisi olan şeffaf bir button. Daha az belirgin eylemler veya iptal button'ları için kullanışlıdır.

Button.outlined(
  text: "Cancel",
  onPressed: () {
    // Handle press
  },
)

Kenarlık ve metin renklerini özelleştirebilirsiniz:

Button.outlined(
  text: "Custom Outline",
  borderColor: Colors.red,
  textColor: Colors.red,
  onPressed: () {},
)

Text Only

Arka planı veya kenarlığı olmayan minimal bir button. Satır içi eylemler veya bağlantılar için idealdir.

Button.textOnly(
  text: "Skip",
  onPressed: () {
    // Handle press
  },
)

Metin rengini özelleştirebilirsiniz:

Button.textOnly(
  text: "View Details",
  textColor: Colors.blue,
  onPressed: () {},
)

Icon

Metnin yanında bir simge gösteren dolgulu bir button. Simge varsayılan olarak metnin önünde görünür.

Button.icon(
  text: "Add to Cart",
  icon: Icon(Icons.shopping_cart),
  onPressed: () {
    // Handle press
  },
)

Arka plan rengini özelleştirebilirsiniz:

Button.icon(
  text: "Download",
  icon: Icon(Icons.download),
  color: Colors.green,
  onPressed: () {},
)

Gradient

Doğrusal gradyan arka plana sahip bir button. Varsayılan olarak temanızın birincil ve üçüncül renklerini kullanır.

Button.gradient(
  text: "Get Started",
  onPressed: () {
    // Handle press
  },
)

Özel gradyan renkleri sağlayabilirsiniz:

Button.gradient(
  text: "Premium",
  gradientColors: [Colors.purple, Colors.pink],
  onPressed: () {},
)

Rounded

Tamamen yuvarlatılmış köşelere sahip hap şeklinde bir button. Kenarlık yarıçapı varsayılan olarak button yüksekliğinin yarısıdır.

Button.rounded(
  text: "Continue",
  onPressed: () {
    // Handle press
  },
)

Arka plan rengini ve kenarlık yarıçapını özelleştirebilirsiniz:

Button.rounded(
  text: "Apply",
  backgroundColor: Colors.teal,
  borderRadius: BorderRadius.circular(20),
  onPressed: () {},
)

Transparency

Arka plan bulanıklaştırma efektli buzlu cam tarzı bir button. Görüntülerin veya renkli arka planların üzerine yerleştirildiğinde iyi çalışır.

Button.transparency(
  text: "Explore",
  onPressed: () {
    // Handle press
  },
)

Metin rengini özelleştirebilirsiniz:

Button.transparency(
  text: "View More",
  color: Colors.white,
  onPressed: () {},
)

Async Yükleme Durumu

Nylo Website button'larının en güçlü özelliklerinden biri otomatik yükleme durumu yönetimidir. onPressed callback'iniz bir Future döndürdüğünde, button otomatik olarak bir yükleme göstergesi gösterir ve işlem tamamlanıncaya kadar etkileşimi devre dışı bırakır.

Button.primary(
  text: "Submit",
  onPressed: () async {
    await sleep(3); // Simulates a 3 second async task
  },
)

Async işlem çalışırken, button bir iskelet yükleme efekti gösterir (varsayılan olarak). Future tamamlandığında, button normal durumuna döner.

Bu, herhangi bir async işlemle çalışır -- API çağrıları, veritabanı yazmaları, dosya yüklemeleri veya Future döndüren herhangi bir şey:

Button.primary(
  text: "Save Profile",
  onPressed: () async {
    await api<ApiService>((request) =>
      request.updateProfile(name: "John", email: "john@example.com")
    );
    showToastSuccess(description: "Profile saved!");
  },
)
Button.secondary(
  text: "Sync Data",
  onPressed: () async {
    await fetchAndStoreData();
    await clearOldCache();
  },
)

isLoading durum değişkenlerini yönetmeye, setState çağırmaya veya herhangi bir şeyi StatefulWidget ile sarmaya gerek yok -- Nylo Website her şeyi sizin için halleder.

Nasıl Çalışır

Button, onPressed'in bir Future döndürdüğünü algıladığında, şunları yapmak için lockRelease mekanizmasını kullanır:

  1. Bir yükleme göstergesi gösterme (LoadingStyle tarafından kontrol edilir)
  2. Çift dokunmayı önlemek için button'ı devre dışı bırakma
  3. Future'ın tamamlanmasını bekleme
  4. Button'ı normal durumuna geri yükleme

Animasyon Stilleri

Button'lar ButtonAnimationStyle aracılığıyla basma animasyonlarını destekler. Bu animasyonlar, bir kullanıcı bir button ile etkileşime girdiğinde görsel geri bildirim sağlar. Button'larınızı lib/resources/widgets/buttons/buttons.dart dosyasında özelleştirirken animasyon stilini ayarlayabilirsiniz.

Clickable

Duolingo tarzı bir 3D basma efekti. Button basıldığında aşağı hareket eder ve bırakıldığında geri zıplar. Birincil eylemler ve oyun benzeri UX için en uygun.

animationStyle: ButtonAnimationStyle.clickable()

Efekti ince ayarlayın:

ButtonAnimationStyle.clickable(
  translateY: 6.0,        // How far the button moves down (default: 4.0)
  shadowOffset: 6.0,      // Shadow depth (default: 4.0)
  duration: Duration(milliseconds: 100),
  enableHapticFeedback: true,
)

Bounce

Button'ı basıldığında küçültür ve bırakıldığında geri zıplatır. Sepete ekle, beğen ve favori button'ları için en uygun.

animationStyle: ButtonAnimationStyle.bounce()

Efekti ince ayarlayın:

ButtonAnimationStyle.bounce(
  scaleMin: 0.90,         // Minimum scale on press (default: 0.92)
  duration: Duration(milliseconds: 150),
  curve: Curves.easeOutBack,
  enableHapticFeedback: true,
)

Pulse

Button basılı tutulurken hafif sürekli bir ölçek nabız atışı. Uzun basma eylemleri veya dikkat çekmek için en uygun.

animationStyle: ButtonAnimationStyle.pulse()

Efekti ince ayarlayın:

ButtonAnimationStyle.pulse(
  pulseScale: 1.08,       // Max scale during pulse (default: 1.05)
  duration: Duration(milliseconds: 800),
  curve: Curves.easeInOut,
)

Squeeze

Button'ı basıldığında yatay olarak sıkıştırır ve dikey olarak genişletir. Eğlenceli ve etkileşimli kullanıcı arayüzleri için en uygun.

animationStyle: ButtonAnimationStyle.squeeze()

Efekti ince ayarlayın:

ButtonAnimationStyle.squeeze(
  squeezeX: 0.93,         // Horizontal scale (default: 0.95)
  squeezeY: 1.07,         // Vertical scale (default: 1.05)
  duration: Duration(milliseconds: 120),
  enableHapticFeedback: true,
)

Jelly

Sallanımlı elastik bir deformasyon efekti. Eğlenceli, rahat veya eğlence uygulamaları için en uygun.

animationStyle: ButtonAnimationStyle.jelly()

Efekti ince ayarlayın:

ButtonAnimationStyle.jelly(
  jellyStrength: 0.2,     // Wobble intensity (default: 0.15)
  duration: Duration(milliseconds: 300),
  curve: Curves.elasticOut,
  enableHapticFeedback: true,
)

Shine

Basıldığında button üzerinden geçen parlak bir vurgu. Premium özellikler veya dikkat çekmek istediğiniz CTA'lar için en uygun.

animationStyle: ButtonAnimationStyle.shine()

Efekti ince ayarlayın:

ButtonAnimationStyle.shine(
  shineColor: Colors.white,  // Color of the shine streak (default: white)
  shineWidth: 0.4,           // Width of the shine band (default: 0.3)
  duration: Duration(milliseconds: 600),
)

Ripple

Dokunma noktasından genişleyen geliştirilmiş bir dalga efekti. Material Design vurgusu için en uygun.

animationStyle: ButtonAnimationStyle.ripple()

Efekti ince ayarlayın:

ButtonAnimationStyle.ripple(
  rippleScale: 2.5,       // How far the ripple expands (default: 2.0)
  duration: Duration(milliseconds: 400),
  curve: Curves.easeOut,
  enableHapticFeedback: true,
)

Morph

Button'ın kenarlık yarıçapı basıldığında artar ve bir şekil değiştirme efekti oluşturur. İnce, zarif geri bildirim için en uygun.

animationStyle: ButtonAnimationStyle.morph()

Efekti ince ayarlayın:

ButtonAnimationStyle.morph(
  morphRadius: 30.0,      // Target border radius on press (default: 24.0)
  duration: Duration(milliseconds: 150),
  curve: Curves.easeInOut,
)

Shake

Yatay bir sallama animasyonu. Hata durumları veya geçersiz eylemler için en uygun -- bir şeylerin yanlış gittiğini belirtmek için button'ı sallayın.

animationStyle: ButtonAnimationStyle.shake()

Efekti ince ayarlayın:

ButtonAnimationStyle.shake(
  shakeOffset: 10.0,      // Horizontal displacement (default: 8.0)
  shakeCount: 4,          // Number of shakes (default: 3)
  duration: Duration(milliseconds: 400),
  enableHapticFeedback: true,
)

Animasyonları Devre Dışı Bırakma

Animasyonsuz bir button kullanmak için:

animationStyle: ButtonAnimationStyle.none()

Varsayılan Animasyonu Değiştirme

Bir button türü için varsayılan animasyonu değiştirmek için, lib/resources/widgets/buttons/buttons.dart dosyanızı düzenleyin:

class Button {
  static Widget primary({
    required String text,
    VoidCallback? onPressed,
    ...
  }) {
    return PrimaryButton(
      text: text,
      onPressed: onPressed,
      animationStyle: ButtonAnimationStyle.bounce(), // Change the default
    );
  }
}

Splash Stilleri

Splash efektleri button'larda görsel dokunma geri bildirimi sağlar. Bunları ButtonSplashStyle aracılığıyla yapılandırın. Splash stilleri, katmanlı geri bildirim için animasyon stilleriyle birleştirilebilir.

Mevcut Splash Stilleri

Splash Factory Açıklama
Ripple ButtonSplashStyle.ripple() Dokunma noktasından standart Material dalgası
Highlight ButtonSplashStyle.highlight() Dalga animasyonu olmadan hafif vurgulama
Glow ButtonSplashStyle.glow() Dokunma noktasından yayılan yumuşak parıltı
Ink ButtonSplashStyle.ink() Hızlı mürekkep sıçraması, daha hızlı ve daha duyarlı
None ButtonSplashStyle.none() Splash efekti yok
Custom ButtonSplashStyle.custom() Splash factory üzerinde tam kontrol

Örnek

class Button {
  static Widget outlined({
    required String text,
    VoidCallback? onPressed,
    ...
  }) {
    return OutlinedButton(
      text: text,
      onPressed: onPressed,
      splashStyle: ButtonSplashStyle.ripple(),
      animationStyle: ButtonAnimationStyle.clickable(),
    );
  }
}

Splash renklerini ve opaklığını özelleştirebilirsiniz:

ButtonSplashStyle.ripple(
  splashColor: Colors.blue,
  highlightColor: Colors.blue,
  splashOpacity: 0.2,
  highlightOpacity: 0.1,
)

Yükleme Stilleri

Async işlemler sırasında gösterilen yükleme göstergesi LoadingStyle tarafından kontrol edilir. Bunu buttons dosyanızda button türü başına ayarlayabilirsiniz.

Skeletonizer (Varsayılan)

Button üzerinde bir shimmer iskelet efekti gösterir:

loadingStyle: LoadingStyle.skeletonizer()

Normal

Bir yükleme widget'ı gösterir (varsayılan olarak uygulama yükleyicisi):

loadingStyle: LoadingStyle.normal(
  child: Text("Please wait..."),
)

None

Button'ı görünür tutar ancak yükleme sırasında etkileşimi devre dışı bırakır:

loadingStyle: LoadingStyle.none()

Form Gönderimi

Tüm button'lar, button'ı bir NyForm'a bağlayan submitForm parametresini destekler. Dokunulduğunda, button formu doğrulayacak ve form verileriyle başarı işleyicinizi çağıracaktır.

Button.primary(
  text: "Submit",
  submitForm: (LoginForm(), (data) {
    // data contains the validated form fields
    print(data);
  }),
  onFailure: (error) {
    // Handle validation errors
    print(error);
  },
)

submitForm parametresi iki değerli bir record kabul eder:

  1. Bir NyFormData örneği (veya String olarak form adı)
  2. Doğrulanmış verileri alan bir callback

Varsayılan olarak, showToastError true'dur ve form doğrulaması başarısız olduğunda bir toast bildirimi gösterir. Hataları sessizce ele almak için false olarak ayarlayın:

Button.primary(
  text: "Login",
  submitForm: (LoginForm(), (data) async {
    await api<AuthApiService>((request) => request.login(data));
  }),
  showToastError: false,
  onFailure: (error) {
    // Custom error handling
  },
)

submitForm callback'i bir Future döndürdüğünde, button async işlem tamamlanıncaya kadar otomatik olarak bir yükleme durumu gösterecektir.

Button'ları Özelleştirme

Tüm button varsayılanları projenizde lib/resources/widgets/buttons/buttons.dart dosyasında tanımlanır. Her button türünün lib/resources/widgets/buttons/partials/ içinde karşılık gelen bir widget sınıfı vardır.

Varsayılan Stilleri Değiştirme

Bir button'ın varsayılan görünümünü değiştirmek için, Button sınıfını düzenleyin:

class Button {
  static Widget primary({
    required String text,
    VoidCallback? onPressed,
    (dynamic, Function(dynamic data))? submitForm,
    Function(dynamic error)? onFailure,
    bool showToastError = true,
    double? width,
  }) {
    return PrimaryButton(
      text: text,
      onPressed: onPressed,
      submitForm: submitForm,
      onFailure: onFailure,
      showToastError: showToastError,
      loadingStyle: LoadingStyle.skeletonizer(),
      width: width,
      height: 52.0,
      animationStyle: ButtonAnimationStyle.bounce(),
      splashStyle: ButtonSplashStyle.glow(),
    );
  }
}

Bir Button Widget'ını Özelleştirme

Bir button türünün görsel görünümünü değiştirmek için, lib/resources/widgets/buttons/partials/ içindeki ilgili widget'ı düzenleyin. Örneğin, birincil button'ın kenarlık yarıçapını veya gölgesini değiştirmek için:

// lib/resources/widgets/buttons/partials/primary_button_widget.dart

class PrimaryButton extends StatefulAppButton {
  ...

  @override
  Widget buildButton(BuildContext context) {
    final theme = Theme.of(context);
    final bgColor = backgroundColor ?? theme.colorScheme.primary;
    final fgColor = contentColor ?? theme.colorScheme.onPrimary;

    return Container(
      width: width ?? double.infinity,
      height: height,
      decoration: BoxDecoration(
        color: bgColor,
        borderRadius: BorderRadius.circular(8), // Change the radius
      ),
      child: Center(
        child: Text(
          text,
          style: TextStyle(
            color: fgColor,
            fontSize: 16,
            fontWeight: FontWeight.w600,
          ),
        ),
      ),
    );
  }
}

Yeni Bir Button Türü Oluşturma

Yeni bir button türü eklemek için:

  1. lib/resources/widgets/buttons/partials/ içinde StatefulAppButton'ı genişleten yeni bir widget dosyası oluşturun.
  2. buildButton metodunu uygulayın.
  3. Button sınıfına bir statik metot ekleyin.
// lib/resources/widgets/buttons/partials/danger_button_widget.dart

class DangerButton extends StatefulAppButton {
  DangerButton({
    required super.text,
    super.onPressed,
    super.submitForm,
    super.onFailure,
    super.showToastError,
    super.loadingStyle,
    super.width,
    super.height,
    super.animationStyle,
    super.splashStyle,
  });

  @override
  Widget buildButton(BuildContext context) {
    return Container(
      width: width ?? double.infinity,
      height: height,
      decoration: BoxDecoration(
        color: Colors.red,
        borderRadius: BorderRadius.circular(14),
      ),
      child: Center(
        child: Text(
          text,
          style: TextStyle(
            color: Colors.white,
            fontSize: 16,
            fontWeight: FontWeight.w600,
          ),
        ),
      ),
    );
  }
}

Ardından Button sınıfına kaydedin:

class Button {
  ...

  static Widget danger({
    required String text,
    VoidCallback? onPressed,
    (dynamic, Function(dynamic data))? submitForm,
    Function(dynamic error)? onFailure,
    bool showToastError = true,
    double? width,
  }) {
    return DangerButton(
      text: text,
      onPressed: onPressed,
      submitForm: submitForm,
      onFailure: onFailure,
      showToastError: showToastError,
      loadingStyle: LoadingStyle.skeletonizer(),
      width: width,
      height: 52.0,
      animationStyle: ButtonAnimationStyle.shake(),
    );
  }
}

Parametre Referansı

Ortak Parametreler (Tüm Button Türleri)

Parametre Tür Varsayılan Açıklama
text String zorunlu Button etiket metni
onPressed VoidCallback? null Button'a dokunulduğunda callback. Otomatik yükleme durumu için bir Future döndürün
submitForm (dynamic, Function(dynamic))? null Form gönderim kaydı (form örneği, başarı callback'i)
onFailure Function(dynamic)? null Form doğrulaması başarısız olduğunda çağrılır
showToastError bool true Form doğrulama hatasında toast bildirimi göster
width double? null Button genişliği (varsayılan tam genişlik)

Türe Özel Parametreler

Button.outlined

Parametre Tür Varsayılan Açıklama
borderColor Color? Tema outline rengi Kenarlık çizgi rengi
textColor Color? Tema birincil rengi Metin rengi

Button.textOnly

Parametre Tür Varsayılan Açıklama
textColor Color? Tema birincil rengi Metin rengi

Button.icon

Parametre Tür Varsayılan Açıklama
icon Widget zorunlu Gösterilecek simge widget'ı
color Color? Tema birincil rengi Arka plan rengi

Button.gradient

Parametre Tür Varsayılan Açıklama
gradientColors List<Color>? Birincil ve üçüncül renkler Gradyan renk durakları

Button.rounded

Parametre Tür Varsayılan Açıklama
backgroundColor Color? Tema primary container rengi Arka plan rengi
borderRadius BorderRadius? Hap şekli (yükseklik / 2) Köşe yarıçapı

Button.transparency

Parametre Tür Varsayılan Açıklama
color Color? Tema uyumlu Metin rengi

ButtonAnimationStyle Parametreleri

Parametre Tür Varsayılan Açıklama
duration Duration Türe göre değişir Animasyon süresi
curve Curve Türe göre değişir Animasyon eğrisi
enableHapticFeedback bool Türe göre değişir Basıldığında dokunsal geri bildirim tetikle
translateY double 4.0 Clickable: dikey basma mesafesi
shadowOffset double 4.0 Clickable: gölge derinliği
scaleMin double 0.92 Bounce: basıldığında minimum ölçek
pulseScale double 1.05 Pulse: nabız sırasında maksimum ölçek
squeezeX double 0.95 Squeeze: yatay sıkıştırma
squeezeY double 1.05 Squeeze: dikey genişleme
jellyStrength double 0.15 Jelly: sallanma yoğunluğu
shineColor Color Colors.white Shine: vurgu rengi
shineWidth double 0.3 Shine: parlaklık bandı genişliği
rippleScale double 2.0 Ripple: genişleme ölçeği
morphRadius double 24.0 Morph: hedef kenarlık yarıçapı
shakeOffset double 8.0 Shake: yatay yer değiştirme
shakeCount int 3 Shake: sallanma sayısı

ButtonSplashStyle Parametreleri

Parametre Tür Varsayılan Açıklama
splashColor Color? Tema surface rengi Splash efekt rengi
highlightColor Color? Tema surface rengi Highlight efekt rengi
splashOpacity double 0.12 Splash opaklığı
highlightOpacity double 0.06 Highlight opaklığı
borderRadius BorderRadius? null Splash klip yarıçapı