Flutter'da bir Düğmeyi nasıl devre dışı bırakırım?


122

Flutter'ı yeni anlamaya başlıyorum, ancak bir düğmenin etkin durumunu nasıl ayarlayacağımı bulmakta zorlanıyorum.

Dokümanlardan, onPressedbir düğmeyi devre dışı bırakmak için null olarak ayarlanması ve etkinleştirmek için ona bir değer verilmesi yazıyor . Düğme yaşam döngüsü boyunca aynı durumda kalmaya devam ederse bu sorun değildir.

Düğmenin etkin durumunu (veya onPressed geri aramayı) bir şekilde güncellememe izin verecek özel bir Stateful widget oluşturmam gerektiği izlenimini edindim.

Öyleyse sorum şu, bunu nasıl yapacağım? Bu oldukça basit bir gereklilik gibi görünüyor, ancak belgelerde nasıl yapılacağına dair hiçbir şey bulamıyorum.

Teşekkürler.


"Düğme yaşam döngüsü boyunca aynı durumda kalmaya devam ederse bu sorun değil" ile ne demek istediğinizi netleştirebilir misiniz? ?
Seth Ladd

Yanıtlar:


133

Sanırım builddüğmenize bazı yardımcı işlevler ve ayrıca bir Durum bilgisi bileşeninin yanı sıra tuşunu kapatabileceğiniz bazı özellikler eklemek isteyebilirsiniz.

  • Bir StatefulWidget / State kullanın ve koşulunuzu tutmak için bir değişken oluşturun (ör. isButtonDisabled)
  • Bunu başlangıçta doğru olarak ayarlayın (eğer arzuladığınız şey buysa)
  • Düğmeyi oluştururken, değeri doğrudanonPressednull işlevlerden birine veya bir işlevine ayarlamayınonPressed: () {}
  • Bunun yerine , üçlü veya yardımcı bir işlev kullanarak koşullu olarak ayarlayın (aşağıdaki örnek)
  • Koşulunun bir isButtonDisabledparçası olarak kontrol edin ve nullişlevlerden birini veya bir kısmını geri döndürün .
  • Düğmeye basıldığında (veya düğmeyi devre dışı bırakmak istediğinizde) setState(() => isButtonDisabled = true)koşullu değişkeni çevirmek için kullanın .
  • Flutter build(), yeni durumla yöntemi tekrar çağıracak ve düğme bir nullbasın işleyici ile işlenecek ve devre dışı bırakılacaktır.

İşte Flutter sayaç projesini kullanarak biraz daha bağlam.

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  bool _isButtonDisabled;

  @override
  void initState() {
    _isButtonDisabled = false;
  }

  void _incrementCounter() {
    setState(() {
      _isButtonDisabled = true;
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("The App"),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Text(
              'You have pushed the button this many times:',
            ),
            new Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
            _buildCounterButton(),
          ],
        ),
      ),
    );
  }

  Widget _buildCounterButton() {
    return new RaisedButton(
      child: new Text(
        _isButtonDisabled ? "Hold on..." : "Increment"
      ),
      onPressed: _isButtonDisabled ? null : _incrementCounter,
    );
  }
}

Bu örnekte ben set şartlı bir satır içi ve üçlü kullanıyorum Textve onPressed, ama bir fonksiyonun içine bu ayıklamak için daha uygun olabilir (eğer düğmeye metnini de değiştirmek için bu aynı yöntemi kullanabilirsiniz):

Widget _buildCounterButton() {
    return new RaisedButton(
      child: new Text(
        _isButtonDisabled ? "Hold on..." : "Increment"
      ),
      onPressed: _counterButtonPress(),
    );
  }

  Function _counterButtonPress() {
    if (_isButtonDisabled) {
      return null;
    } else {
      return () {
        // do anything else you may want to here
        _incrementCounter();
      };
    }
  }

3
Bağımsız değişken olarak kalın ok işlevini eklemeniz gerekir, aksi takdirde _incrementCounter () işlevi düğme etkinleştirildiğinde hemen çağrılır. Bu şekilde aslında düğme tıklanana kadar bekleyecektir: onPressed şöyle görünmelidir:onPressed: _isButtonDisabled ? null : () => _incrementCounter
Vit Veres

2
@vitVeres genellikle doğrudur ancak _counterButtonPress () bir işlev döndürdüğünden, return () {}bu kasıtlıdır. Fonksiyonun nulldüğmeyi çalıştırmasını ve geri dönmesini ve devre dışı bırakmasını istediğim için burada şişman oku kullanmak istemiyorum .
Ashton Thomas

@AshtonThomas Evet, çıkarılan yöntemde _counterButtonPress () tam olarak açıkladığınız gibi, ancak siz ayıklamayı önermeden önce koda üçlü operatörle başvuruyordum. İlk örneğinizde, düğmenin etkinleştirilmesi gerektiğinde _incrementCounter () yönteminin çalıştırılmasına neden olacaktır. Bir dahaki sefere ne demek istediğimi daha kesin bir şekilde ifade etmeye çalışacağım :)
Vit Veres

31
Bir disabledmülkü kullanmanın nesi yanlıştı , Flutter ekibi? Bu sadece sezgisel değil: - /
Curly

1
doğru yol AbsorbPointer veya IgnorePointer ile. OnPressed'i null olarak ayarlayarak mantık yerine basitçe widget yolu.
ejdrian313

99

Dokümanlara göre:

"OnPressed geri arama boşsa, düğme devre dışı bırakılacak ve varsayılan olarak disabledColor'daki düz bir düğmeye benzeyecektir."

https://docs.flutter.io/flutter/material/RaisedButton-class.html

Öyleyse, şöyle bir şey yapabilirsiniz:

    RaisedButton(
      onPressed: calculateWhetherDisabledReturnsBool() ? null : () => whatToDoOnPressed,
      child: Text('Button text')
    );

2
Dokümanlara bakılırsa, bu nasıl uygulanacağıdır. Gibi kabul cevap özelliklerine sahip disabledElevation, disabledColorve DisabledTextColoramaçlandığı gibi eser olmaz.
Joel Broström

Bunun için Pff teşekkürler Steve, şu anda kabul edilen cevabın tüm kodlarını gözden geçirmeyi planlamıyordu. @ chris84948, bunu kabul edilen yanıta değiştirmeyi düşünün.
CularBytes


17

Ayar

onPressed: null // disables click

ve

onPressed: () => yourFunction() // enables click

1
Bu çözümde değeri onPressedher zaman bir işlevdir, bu nedenle düğme 'tıklanabilir' olarak işlenir, ancak isEnabledözellik ayarlanmışsa click olayını yoksayacaktır . Düğmeyi gerçekten devre dışı bırakmak için şunu kullanınRaisedButton(onPressed: isEnabled ? _handleClick : null
Curly

16

IgnorePointer , belirli ve sınırlı sayıda pencere öğesi için tam olarak bunu yapar: ignoringözelliği true olarak ayarlandığında, alt pencere öğesi (aslında alt ağacın tamamı) tıklanamaz.

IgnorePointer(
    ignoring: true, // or false
    child: RaisedButton(
        onPressed: _logInWithFacebook,
        child: Text("Facebook sign-in"),
        ),
),

Aksi takdirde, bir alt ağacın tamamını devre dışı bırakmak istiyorsanız, AbsorbPointer () 'a bakın.


9

Etkinleştirme ve Devre Dışı Bırakma işlevselliği çoğu widget için aynıdır.

Örn, düğme, anahtar, onay kutusu vb.

onPressedMülkü aşağıda gösterildiği gibi ayarlamanız yeterlidir

onPressed : nullDevre Dışı widget'ı döndürür

onPressed : (){}veya Etkin widget'ıonPressed : _functionName döndürür


7

AbsorbPointer'ı da kullanabilir ve aşağıdaki şekilde kullanabilirsiniz:

AbsorbPointer(
      absorbing: true, // by default is true
      child: RaisedButton(
        onPressed: (){
          print('pending to implement onPressed function');
        },
        child: Text("Button Click!!!"),
      ),
    ),

Bu widget hakkında daha fazla bilgi edinmek istiyorsanız, aşağıdaki Flutter Docs bağlantısını kontrol edebilirsiniz.


2
Ignore- / AbsorbPointer, devre dışı bırakılan stilleri sadece HATIRLATICI olarak kabul etmez :-)
Pascal

5

Bence en kolay yol bu:

RaisedButton(
  child: Text("PRESS BUTTON"),
  onPressed: booleanCondition
    ? () => myTapCallback()
    : null
)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.