This is the 11th day of my participation in the Gwen Challenge in November. Check out the details: The last Gwen Challenge in 2021.

  • Preface: We realize the discovery page of wechat



So let’s first observe that this is aListViewDivided into several groups, eachrowSimilar, but one on the shopping rightcellWith state,Activities thatandLittle red dot, as well asThe cell line. It’s basically a classic iOStableview, where cell isStatic page cell.

1. Customize the cell

Let’s analyze the cell first. It can be said that the cell has six elements, including icon, title, activity description, red dot, arrow of the cell and dividing line. We can customize the constructor to be mandatory, where each cell has an arrow > we don’t need to define, we can also use the index to determine the dividing line.

class DiscoverCell extends StatelessWidget {

   String? iconImageName;
   String? title;
   String? desTitle;
   String? desIconImageName;

   DiscoverCell({
   required this.title,
   required this.iconImageName,
   this.desIconImageName,
   this.desTitle
}):assert(title ! =null.'Title cannot be empty'),
   assert(iconImageName ! =null.'Icon cannot be empty');


  @override
  Widget build(BuildContext context) {
    returnContainer( ); }}Copy the code

For cell, we use spaceBetween, the evenly divided layout in time row layout. The effect is that the two sides of the components are arranged in the middle, and the gaps in the middle are equal, which meets our requirements.

child: Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,// The cell is divided into two parts
  children: [
    / / the left
   Container(
     child: Row(children: [
       Image.asset(iconImageName!,width: 20,), Text(title!) ,,),),/ / right
    Container(
      child: Row(
        children: [
          desTitle != null? Text(desTitle!) :Container(), desIconImageName ! =null ? Image.asset(desIconImageName!) :Container(),
          Image.asset('images/icon_right.png'.)/ / arrow[, (,)], (Copy the code

Let’s first define the cell. In the Container on the right, we will display the image according to the title and the red dot. Then we will display the two states we need to display in the ListView

child: ListView(

  children: [
    DiscoverCell(title: 'Moments of Friends', iconImageName: 'Images/Friends.png'),
    DiscoverCell(title: 'shopping',iconImageName: 'images/shopping. PNG',desTitle: '618 Limited Time Special ',desIconImageName:'images/badge.png',),),Copy the code

We didn’t set the images or the spacing, but the elements were displayed

Widget build(BuildContext context) {
  return Container(
    height: 44,
    child: Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,// The cell is divided into two parts
      children: [
        / / the left
       Container(
         padding: EdgeInsets.all(10),
         child: Row(children: [
           Image.asset(iconImageName!,width: 20,),
           SizedBox(width: 10,), Text(title!) ,,),),/ / right
        Container(
          child: Row(
            children: [
              desTitle != null? Text(desTitle!) :Container(), desIconImageName ! =null? Image.asset(desIconImageName! ,width:20,) :Container(),
              Image.asset('images/icon_right.png',width: 15,),/ / arrow
              SizedBox(width: 15() [() [() [() [() [()Copy the code

Set the line height and spacing, and the image size.

2. Dividing line of the cell

We have two ideas. One is to put the splitter as a row component in the Children of the listView

children: [
  DiscoverCell(title: 'Moments of Friends', iconImageName: 'Images/Friends.png'),
  Row(children: <Widget>[Container(width: 50, height: 1, color: Colors.white),
      Container(height: 1, color: Colors.grey)
    ],
  ),
  DiscoverCell(title: 'shopping',iconImageName: 'images/shopping. PNG',desTitle: '618 Limited Time Special ',desIconImageName:'images/badge.png')],Copy the code

Is equivalent toThe cell lineDivided into2Color it so you can tell it apart.

We can also use the stack, align the bottom to the left, we put the line at the bottom to set the background color, set the bottom to the left spacing.

We can also use dividers in other ways, such as dividers

Divider(height: 0.5,color: Colors.grey,indent: 50,),
Copy the code

Indent is the start indent and endIndent is the endIndent

If I indent the background color, let’s say I set the beginning and the end to be 50 and the color to be red

  • DecoratedBox
DecoratedBox(decoration: BoxDecoration(
  
  border: Border.all(color: Colors.grey,width: 0.5))),Copy the code

Create a new decorative container without the Child Widget, using only the border parameter, equivalent to a blank box with no height.

3. Page jump and click effect

The other cells are similar, we add the title and picture

Effect:

Let’s take a look at the click-through implementation of the Cell through the widget of the GestureDetector gesture which has a lot of state implementation callbacks in it

Here we useontapTo implement the

I need to pass onerouting

We define a child page

class DiscoverChildPage extends StatelessWidget {

  final String? title;
  DiscoverChildPage(this.title);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title??""), ), body: Container(), ); }}Copy the code

Realize the jump

Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => DiscoverChildPage(title)));
Copy the code

How do you make it look like what we’ve selected in iOS?

Because you want to change the selection background of the cell, change it to StatefulWidget

We use widgets to use properties

Color _currentColor = Colors.white;

@override
Widget build(BuildContext context) {
  returnGestureDetector( onTap: () { Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => DiscoverChildPage(widget.title))); setState(() { _currentColor = Colors.white; }); }, onTapDown: (TapDownDetails details) { setState(() { _currentColor = Colors.grey; }); }, onTapCancel: () { setState(() { _currentColor = Colors.white; }); }},Copy the code