In this post we are going to design the Simple Layout with Flutter-Basic Components

1.1 Preparation-Data Type
Based on the contents of the above card, we can define some fields. In order to standardize the development process, we first define a data type class for the card, so that the data can be better mocked and managed in the subsequent development process:
|
class BookViewModel {
final String coverUrl;
final String authorImgUrl;
final String authorName;
final String description;
final String topic;
final String publishTime;
final String publishContent;
final int replies;
final int likes;
final int shares;
const BookViewModel({
this.coverUrl,
this.authorImgUrl,
this.authorName,
this.description,
this.topic,
this.publishTime,
this.publishContent,
this.replies,
this.likes,
this.shares,
});
}
|
1.2 Build the skeleton and split the layout
Based on above Figure, we can split the whole, is divided into a total of four parts: Cover, AuthorInfo, PublishContent and InteractionArea. To do this, we can build the basic skeleton of the code:
|
class BookView extends StatelessWidget {
final BookViewModel data;
const BookView({
Key key,
this.data,
}) : super(key: key);
Widget renderCover() {
}
Widget renderAuthorInfo() {
}
Widget renderPublishContent() {
}
Widget renderInteractionArea() {
}
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
blurRadius: 6,
spreadRadius: 4,
color: Color.fromARGB(20, 0, 0, 0),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
renderCover(),
renderAuthorInfo(),
renderPublishContent(),
renderInteractionArea(),
],
),
);
}
}
|
1.3 Cover area
In order to better highlight the effect of the picture, a mask layer is added here, so it can be used here Stack/ Positioned layout and LinearGradientgradient.
|
Widget renderCover() {
return Stack(
fit: StackFit.passthrough,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(8),
topRight: Radius.circular(8),
),
child: Image.network(
data.coverUrl,
height: 200,
fit: BoxFit.fitWidth,
),
),
Positioned(
left: 0,
top: 100,
right: 0,
bottom: 0,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color.fromARGB(0, 0, 0, 0),
Color.fromARGB(80, 0, 0, 0),
],
),
),
),
),
],
);
}
|
1.4 Author Information Area
The Author information area is very suitable for layout using components Row and Column components.
|
Widget renderUserInfo() {
return Container(
margin: EdgeInsets.only(top: 16),
padding: EdgeInsets.symmetric(horizontal: 16),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
CircleAvatar(
radius: 20,
backgroundColor: Color(0xFFCCCCCC),
backgroundImage: NetworkImage(data.authorImgUrl),
),
Padding(padding: EdgeInsets.only(left: 8)),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
data.userName,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Color(0xFF333333),
),
),
Padding(padding: EdgeInsets.only(top: 2)),
Text(
data.description,
style: TextStyle(
fontSize: 12,
color: Color(0xFF999999),
),
),
],
),
],
),
Text(
data.publishTime,
style: TextStyle(
fontSize: 13,
color: Color(0xFF999999),
),
),
],
),
);
}
|
1.5 Publishing Content Area
|
Through the UI exercises in this area, we can practice Container different component settings borderRadius and Text truncation processing when the component text content is exceeded.
Widget renderPublishContent() {
return Container(
margin: EdgeInsets.only(top: 16),
padding: EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: EdgeInsets.only(bottom: 14),
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 2),
decoration: BoxDecoration(
color: Color(0xFFFFC600),
borderRadius: BorderRadius.only(
topRight: Radius.circular(8),
bottomLeft: Radius.circular(8),
bottomRight: Radius.circular(8),
),
),
child: Text(
'# ${data.topic}',
style: TextStyle(
fontSize: 12,
color: Colors.white,
),
),
),
Text(
data.publishContent,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Color(0xFF333333),
),
),
],
),
);
}
|
1.6 Interactive Area
In this module, we will use the Icon component, which can control its size and color and other attributes
|
Widget renderInteractionArea() {
return Container(
margin: EdgeInsets.symmetric(vertical: 16),
padding: EdgeInsets.symmetric(horizontal: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
Icon(
Icons.message,
size: 16,
color: Color(0xFF999999),
),
Padding(padding: EdgeInsets.only(left: 6)),
Text(
data.replies.toString(),
style: TextStyle(
fontSize: 15,
color: Color(0xFF999999),
),
),
],
),
Row(
children: <Widget>[
Icon(
Icons.favorite,
size: 16,
color: Color(0xFFFFC600),
),
Padding(padding: EdgeInsets.only(left: 6)),
Text(
data.likes.toString(),
style: TextStyle(
fontSize: 15,
color: Color(0xFF999999),
),
),
],
),
Row(
children: <Widget>[
Icon(
Icons.share,
size: 16,
color: Color(0xFF999999),
),
Padding(padding: EdgeInsets.only(left: 6)),
Text(
data.shares.toString(),
style: TextStyle(
fontSize: 15,
color: Color(0xFF999999),
),
),
],
),
],
),
);
}
|
1.7 Summary
Through the above example, we successfully dismantled a seemingly complex UI interface step by step