ฉันจะปิดการใช้งานปุ่มใน Flutter ได้อย่างไร?


116

ฉันเพิ่งจะเริ่มใช้งาน Flutter แต่ฉันมีปัญหาในการหาวิธีตั้งค่าสถานะที่เปิดใช้งานของปุ่ม

จากเอกสารระบุว่าให้ตั้งค่าonPressedเป็น null เพื่อปิดใช้งานปุ่มและให้ค่าเพื่อเปิดใช้งาน ซึ่งใช้ได้ดีหากปุ่มยังคงอยู่ในสถานะเดิมตลอดอายุการใช้งาน

ฉันได้รับความประทับใจที่ต้องสร้างวิดเจ็ต Stateful ที่กำหนดเองซึ่งจะช่วยให้ฉันสามารถอัปเดตสถานะที่เปิดใช้งานของปุ่ม (หรือการโทรกลับ onPressed) อย่างใด

คำถามของฉันคือฉันจะทำอย่างไร? ดูเหมือนจะเป็นข้อกำหนดที่ค่อนข้างตรงไปตรงมา แต่ฉันไม่พบสิ่งใดในเอกสารเกี่ยวกับวิธีการทำ

ขอบคุณ.


คุณช่วยอธิบายความหมายของคุณได้หรือไม่โดย "ใช้ได้ดีหากปุ่มยังคงอยู่ในสถานะเดิมตลอดอายุการใช้งาน" เหรอ?
Seth Ladd

คำตอบ:


128

ฉันคิดว่าคุณอาจต้องการแนะนำฟังก์ชันตัวช่วยบางอย่างให้กับbuildปุ่มของคุณเช่นเดียวกับวิดเจ็ตสถานะพร้อมกับคุณสมบัติบางอย่างที่จะปิด

  • ใช้ StatefulWidget / State และสร้างตัวแปรเพื่อเก็บเงื่อนไขของคุณ (เช่นisButtonDisabled)
  • ตั้งค่านี้เป็นจริงในตอนแรก (หากนั่นคือสิ่งที่คุณต้องการ)
  • เมื่อแสดงผลปุ่มอย่าตั้งonPressedค่าเป็นnullฟังก์ชันอย่างใดอย่างหนึ่งหรือบางฟังก์ชันโดยตรงonPressed: () {}
  • แทน , เงื่อนไขการตั้งค่าโดยใช้ฟังก์ชั่นไตรภาคหรือผู้ช่วย(ตัวอย่างด้านล่าง)
  • ตรวจสอบisButtonDisabledเป็นส่วนหนึ่งของเงื่อนไขนี้และส่งคืนnullฟังก์ชันหรือฟังก์ชันบางอย่าง
  • เมื่อกดปุ่ม (หรือเมื่อใดก็ตามที่คุณต้องการปิดใช้งานปุ่ม) ใช้setState(() => isButtonDisabled = true)เพื่อพลิกตัวแปรเงื่อนไข
  • Flutter จะเรียกใช้build()เมธอดอีกครั้งด้วยสถานะใหม่และปุ่มจะแสดงผลด้วยnullตัวจัดการการกดและถูกปิดใช้งาน

นี่คือบริบทเพิ่มเติมบางส่วนโดยใช้โครงการ Flutter counter

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,
    );
  }
}

ในตัวอย่างนี้ฉันใช้อินไลน์ ternary เพื่อตั้งค่าTextและตามเงื่อนไขonPressedแต่อาจเหมาะสมกว่าสำหรับคุณที่จะแยกสิ่งนี้เป็นฟังก์ชัน (คุณสามารถใช้วิธีการเดียวกันนี้เพื่อเปลี่ยนข้อความของปุ่มได้เช่นกัน):

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
คุณต้องเพิ่มฟังก์ชัน fat arrow เป็นอาร์กิวเมนต์มิฉะนั้นฟังก์ชัน _incrementCounter () จะถูกเรียกทันทีเมื่อเปิดใช้งานปุ่ม วิธีนี้จะรอจนกว่าปุ่มจะถูกคลิก: onPressed ควรมีลักษณะดังนี้:onPressed: _isButtonDisabled ? null : () => _incrementCounter
Vit Veres

2
@vitVeres ที่มักจะเป็นจริง แต่ _counterButtonPress () กำลังส่งคืนฟังก์ชันreturn () {}ดังนั้นนี่คือเจตนา ฉันไม่ต้องการใช้ลูกศรอ้วนที่นี่เพราะฉันต้องการให้ฟังก์ชันดำเนินการและส่งคืนnullและปิดใช้งานปุ่ม
Ashton Thomas

@AshtonThomas ใช่ในเมธอดที่แยกออกมา _counterButtonPress () มันตรงตามที่คุณอธิบาย แต่ฉันอ้างถึงรหัสด้วยตัวดำเนินการที่เกี่ยวข้องก่อนที่คุณจะแนะนำการแยก ในตัวอย่างแรกของคุณจะทำให้เกิดการดำเนินการของ _incrementCounter () วิธีการเมื่อควรเปิดใช้งานปุ่ม ครั้งหน้าฉันจะพยายามชี้ให้เห็นสิ่งที่ฉันหมายถึงอย่างแม่นยำยิ่งขึ้น :)
Vit Veres

30
เกิดอะไรขึ้นกับการใช้disabledคุณสมบัติทีม Flutter? นี่ไม่ใช่เรื่องง่าย: - /
Curly

1
วิธีที่ถูกต้องคือการใช้ AbsorbPointer หรือ IgnorePointer เพียงวิธีวิดเจ็ตแทนที่จะใช้ตรรกะด้วยการตั้งค่า onPressed เป็น null
ejdrian313

95

ตามเอกสาร:

"ถ้าการโทรกลับ onPressed เป็นโมฆะปุ่มจะถูกปิดใช้งานและโดยค่าเริ่มต้นจะมีลักษณะเป็นปุ่มแบนใน disabledColor"

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

ดังนั้นคุณอาจทำสิ่งนี้:

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

2
เมื่อพิจารณาจากเอกสารนี่คือวิธีที่จะนำไปใช้ ด้วยคุณสมบัติที่ตอบรับชอบdisabledElevation, disabledColorและDisabledTextColorจะไม่ทำงานตามที่ตั้งใจไว้
Joel Broström

Pff ขอบคุณสำหรับ Steve คนนี้ไม่ได้วางแผนที่จะอ่านรหัสทั้งหมดของคำตอบที่ยอมรับในปัจจุบัน @ chris84948 ลองเปลี่ยนเป็นคำตอบที่ยอมรับ
CularBytes


17

การตั้งค่า

onPressed: null // disables click

และ

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

1
ในโซลูชันนี้ค่าของonPressedเป็นฟังก์ชันเสมอดังนั้นปุ่มจึงแสดงผลเป็น 'คลิกได้' แม้ว่าจะไม่สนใจเหตุการณ์การคลิกหากisEnabledตั้งค่าคุณสมบัติไว้ หากต้องการปิดใช้งานปุ่มจริงๆให้ใช้RaisedButton(onPressed: isEnabled ? _handleClick : null
Curly

15

สำหรับวิดเจ็ตที่เฉพาะเจาะจงและ จำกัด จำนวนวิดเจ็ตการรวมไว้ในวิดเจ็ตIgnorePointerจะทำเช่นนี้: เมื่อignoringคุณสมบัติถูกตั้งค่าเป็นจริงวิดเจ็ตย่อย (ที่จริงคือทรีย่อยทั้งหมด) จะไม่สามารถคลิกได้

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

มิฉะนั้นหากคุณตั้งใจจะปิดใช้งานทรีย่อยทั้งหมดให้ดูที่ AbsorbPointer ()


9

ฟังก์ชันการเปิดใช้งานและปิดใช้งานจะเหมือนกันสำหรับวิดเจ็ตส่วนใหญ่

เช่นปุ่มสวิตช์ช่องทำเครื่องหมายเป็นต้น

เพียงตั้งค่าไฟล์ onPressedคุณสมบัติตามที่แสดงด้านล่าง

onPressed : nullส่งคืนวิดเจ็ตที่ปิดใช้งาน

onPressed : (){}หรือonPressed : _functionNameส่งกลับวิดเจ็ตที่เปิดใช้งาน


6

คุณยังสามารถใช้ AbsorbPointer และคุณสามารถใช้มันได้ด้วยวิธีต่อไปนี้:

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

หากคุณต้องการทราบข้อมูลเพิ่มเติมเกี่ยวกับวิดเจ็ตนี้คุณสามารถตรวจสอบลิงค์ต่อไปนี้Flutter Docs


2
Ignore- / AbsorbPointer ไม่พิจารณารูปแบบที่ปิดใช้งานเช่นเดียวกับการแจ้งเตือน :-)
Pascal

5

นี่เป็นวิธีที่ง่ายที่สุดในความคิดของฉัน:

RaisedButton(
  child: Text("PRESS BUTTON"),
  onPressed: booleanCondition
    ? () => myTapCallback()
    : null
)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.