วิธีแสดงวิดเจ็ตเช่นป๊อปอัป
ขณะนี้ฉันมีมุมมองแบบตาราง เมื่อฉันแตะมันฉันจะไปที่หน้าอื่นโดยใช้วิดเจ็ตฮีโร่
ในหน้านั้นฉันมีเพียงคอนเทนเนอร์ที่แสดงข้อมูลเกี่ยวกับไทล์กริดนั้น
สิ่งที่ฉันต้องการคือให้คอนเทนเนอร์นั้นมาอยู่ด้านบนของมุมมองกริดแทนที่จะเป็นเพจอื่น
โผล่มาแบบนั้นได้ยังไง และถ้าเป็นไปได้ฉันควรเก็บแอนิเมชันของฮีโร่ไว้
คำตอบ
คุณควรใช้วิธี showDialog ดังนี้:
InkWell(
child: GridItem(),
onTap: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
content: Hero(child: Card(child: YourWidget()))
); // you can use SimpleDialog, specify barrier dismissible etc
},
)
นี่คือลิงค์เกี่ยวกับคลาสโต้ตอบ https://api.flutter.dev/flutter/material/Dialog-class.html
เกี่ยวกับฮีโร่ฉันไม่แน่ใจเพราะฉันเขียนเหมือนจากส่วนหัว แต่มันควรทำเคล็ดลับ (ofc ต่อท้ายแท็กเดียวกันคุณไม่จำเป็นต้องใช้การ์ดพาเรนต์หากวิดเจ็ตของคุณมีวิดเจ็ตอยู่แล้ว - ฮีโร่ต้องการวิดเจ็ต Material )
ฉันโพสต์สิ่งที่ฉันทำลงไปเพราะมันได้ผล
สิ่งที่ @Nonstapp และ @Parth แนะนำให้ใช้งานได้ยกเว้นการเปลี่ยนฮีโร่เนื่องจากใช้กับ PageRoutes เท่านั้น
ดังนั้นฉันจึงพบวิธีอื่นในการแสดงป๊อปอัปที่คล้ายกันกับ PageRoute
วิดเจ็ตข้อมูลที่ฉันแสดง:
return Padding(
padding: EdgeInsets.fromLTRB(
MediaQuery.of(context).size.width / 8,
MediaQuery.of(context).size.height / 4,
MediaQuery.of(context).size.width / 8,
0),
child: Material(
color: Colors.transparent,
child: ...
เห็นได้ชัดว่าช่องว่างภายในมีไว้สำหรับการวางตำแหน่งและวิดเจ็ต Material คือการให้สไตล์ Material และวิดเจ็ตที่เปิดใช้งานเช่น IconButton ให้วิดเจ็ต Material เป็นสีโปร่งใส
นี่คือวิธีที่ฉันเรียกมันว่า:
void seeDetails(BuildContext context, Book book) {
Navigator.push(
context,
PageRouteBuilder(
fullscreenDialog: true,
opaque: false,
pageBuilder: (_, __, ___) => ChangeNotifierProvider.value(
value: book,
child: DetailCard(),
),
),
);
}
ฉันใช้ PageRouter เพื่อแสดงกล่องโต้ตอบแบบเต็มหน้าจอ แต่เนื่องจากการตั้งค่าของฉันอยู่ที่นั่นจึงมองเห็นเฉพาะการ์ดข้อมูลเท่านั้น
ข้อเสียคือฉันไม่สามารถเปิดใช้งานสิ่งกีดขวางได้
นี่คือผลลัพธ์ของฉัน:
อย่างไรก็ตามวิธีแก้ปัญหาที่แท้จริงคือสิ่งที่ @pskink แนะนำไว้ข้างต้น ต้องมีการตั้งค่าและการปรับแต่งเพิ่มเติมและฉันมีปัญหากับผู้ให้บริการ นี่คือวิธีที่คุณสามารถนำไปใช้ได้
คุณสามารถใช้กล่องโต้ตอบที่กำหนดเอง: -
onPressed: () {
showDialog(
context: context,
builder: (_) => Center(
child: RaisedButton(
child: Text("Show dialog"),
onPressed: () {
showDialog(
context: context,
builder: (context) {
return Dialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
elevation: 16,
child: Container(
height: 400.0,
width: 360.0,
child: ListView(
children: <Widget>[
SizedBox(height: 20),
Center(
child: Text(
"Leaderboard",
style: TextStyle(fontSize: 24, color: Colors.blue, fontWeight: FontWeight.bold),
),
),
SizedBox(height: 20),
_buildName(imageAsset: 'assets/chocolate.jpg', name: "Name 1", score: 1000),
_buildName(imageAsset: 'assets/chocolate.jpg', name: "Name 2", score: 2000),
_buildName(imageAsset: 'assets/chocolate.jpg', name: "Name 3", score: 3000),
_buildName(imageAsset: 'assets/chocolate.jpg', name: "Name 4", score: 4000),
_buildName(imageAsset: 'assets/chocolate.jpg', name: "Name 5", score: 5000),
_buildName(imageAsset: 'assets/chocolate.jpg', name: "Name 6", score: 6000),
],
),
),
);
},
);
},
),
),
);
}
Widget _buildName({String imageAsset, String name, double score}) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Column(
children: <Widget>[
SizedBox(height: 12),
Container(height: 2, color: Colors.redAccent),
SizedBox(height: 12),
Row(
children: <Widget>[
CircleAvatar(
backgroundImage: AssetImage(imageAsset),
radius: 30,
),
SizedBox(width: 12),
Text(name),
Spacer(),
Container(
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 20),
child: Text("${score}"),
decoration: BoxDecoration(
color: Colors.yellow[900],
borderRadius: BorderRadius.circular(20),
),
),
],
),
],
),
);
}