Home Coding Bắt đầu với Flutter – Dogs App: Routing 1: Pages on the Fly

Bắt đầu với Flutter – Dogs App: Routing 1: Pages on the Fly

by Khanh Tran

Trong bài này chúng ta sẽ xây dựng một số trang khác cho ứng dụng của chúng ta. Ta sẽ xây dựng trang chi tiết cho ứng dụng Dogs App.

Create a Dog Detail Page:

Tạo một file mới có tên là dog_detail_page.dart.

Đây sẽ là một StatefulWidgetđể người dùng ứng dụng của bạn có thể xếp hạng, đánh giá về chú cún sau này. Nhưng hiện tại, sẽ không có state nào quản lý.

Và đây là những gì bạn sẽ xây dựng:

dog detail screenshot
Hình 1: Dog Detail Page
// dog_detail_page.dart
import 'package:flutter/material.dart';
import 'dog_model.dart';
class DogDetailPage extends StatefulWidget {
  final Dog dog;
  DogDetailPage(this.dog);
  @override
  _DogDetailPageState createState() => _DogDetailPageState();
}
class _DogDetailPageState extends State<DogDetailPage> {
  // Arbitrary size choice for styles
  final double dogAvatarSize = 150.0;
  Widget get dogImage {
    // Containers define the size of its children.
    return Container(
      height: dogAvatarSize,
      width: dogAvatarSize,
      // Use Box Decoration to make the image a circle
      // and add an arbitrary shadow for styling.
      decoration: BoxDecoration(
        shape: BoxShape.circle,
        // Like in CSS you often want to add multiple
        // BoxShadows for the right look so the
        // boxShadow property takes a list of BoxShadows.
        boxShadow: [
          const BoxShadow(
              // just like CSS:
              // it takes the same 4 properties
              offset: const Offset(1.0, 2.0),
              blurRadius: 2.0,
              spreadRadius: -1.0,
              color: const Color(0x33000000)),
          const BoxShadow(
              offset: const Offset(2.0, 1.0),
              blurRadius: 3.0,
              spreadRadius: 0.0,
              color: const Color(0x24000000)),
          const BoxShadow(
              offset: const Offset(3.0, 1.0),
              blurRadius: 4.0,
              spreadRadius: 2.0,
              color: const Color(0x1F000000)),
        ],
        // This is how you add an image to a Container's background.
        image: DecorationImage(
          fit: BoxFit.cover,
          image: NetworkImage(widget.dog.imageUrl),
        ),
      ),
    );
  }
  // The rating section that says ★ 10/10.
  Widget get rating {
    // Use a row to lay out widgets horizontally.
    return Row(
      // Center the widgets on the main-axis
      // which is the horizontal axis in a row.
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Icon(
          Icons.star,
          size: 40.0,
        ),
        Text(' ${widget.dog.rating} / 10',
            style: Theme.of(context).textTheme.display2),
      ],
    );
  }
  // The widget that displays the image, rating and dog info.
  Widget get dogProfile {
    return Container(
      padding: EdgeInsets.symmetric(vertical: 32.0),
      decoration: BoxDecoration(
        // This would be a great opportunity to create a custom LinearGradient widget
        // that could be shared throughout the app but I'll leave that to you.
        gradient: LinearGradient(
          begin: Alignment.topRight,
          end: Alignment.bottomLeft,
          stops: [0.1, 0.5, 0.7, 0.9],
          colors: [
            Colors.indigo[800],
            Colors.indigo[700],
            Colors.indigo[600],
            Colors.indigo[400],
          ],
        ),
      ),
      // The Dog Profile information.
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          dogImage,
          Text(
            '${widget.dog.name}  🎾',
            style: TextStyle(fontSize: 32.0),
          ),
          Text(
            widget.dog.location,
            style: TextStyle(fontSize: 20.0),
          ),
          Padding(
            padding:
                const EdgeInsets.symmetric(horizontal: 32.0, vertical: 16.0),
            child: Text(widget.dog.description),
          ),
          rating
        ],
      ),
    );
  }
  //Finally, the build method:
  //
  // Aside:
  // It's often much easier to build UI if you break up your widgets the way I
  // have in this file rather than trying to have one massive build method
  @override
  Widget build(BuildContext context) {
    // This is a new page, so you need a new Scaffold!
    return Scaffold(
      backgroundColor: Colors.black87,
      appBar: AppBar(
        backgroundColor: Colors.black87,
        title: Text('Meet ${widget.dog.name}'),
      ),
      body: dogProfile,
    );
  }
}

Add the Routing mechanism:

Bây giờ bạn đã thêm DogDetailPagenhưng bạn không thể truy cập vào nó. Hãy thêm một số định tuyến để có thể làm điều đó.

Trên main page, mỗi thẻ sẽ là một button mà khi nhấn vào sẽ hiển thị trang chi tiết của con chó đó.

Import DogDetailPagevào dog_card.dart:

// dog_card.dart
import 'package:flutter/material.dart';
import 'dog_detail_page.dart';
import 'dog_model.dart';

Trong _DogCardState class của bạn:

// dog_card.dart
@override
Widget build(BuildContext context) {
  // InkWell is a special Material widget that makes its children tappable
  // and adds Material Design ink ripple when tapped.
  return InkWell(
    // onTap is a callback that will be triggered when tapped.
    onTap: showDogDetailPage,
    child: Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
      child: Container(
        height: 115.0,
        child: Stack(
          children: <Widget>[
            Positioned(
              left: 50.0,
              child: dogCard,
            ),
            Positioned(top: 7.5, child: dogImage),
          ],
        ),
      ),
    ),
  );
}
// This is the builder method that creates a new page.
showDogDetailPage() {
  // Navigator.of(context) accesses the current app's navigator.
  // Navigators can 'push' new routes onto the stack,
  // as well as pop routes off the stack.
  //
  // This is the easiest way to build a new page on the fly
  // and pass that page some state from the current page.
  Navigator.of(context).push(
    MaterialPageRoute(
      // builder methods always take context!
      builder: (context) {
        return DogDetailPage(dog);
      },
    ),
  );
}

Ứng dụng của bạn hiện có các trang dành cho từng chú chó.

Và bạn có thể nhận thấy rằng có một button back trên trang chi tiết về chó, nhưng chúng ta hoàn toàn không code cho nó.

Flutter tự động thêm một leading button vào AppBar. Bạn có thể ghi đè nó trong AppBar widget nếu bạn cần.

You may also like

Leave a Comment