In my opinion, learning a new language (fast and efficient learning) must be through practice, and the best way is to do projects. I will simply write a jingdong Demo here.
Scalfold Widget is used to describe the main structure of a page. A MaterialApp consists of multiple Scalfold pages, and the general results of each Scalfold are as follows:
- AppBar: Top navigation bar
- Body: Intermediate content body
- BottomNavigationBar: BottomNavigationBar
On the first day, I set up the project framework and realized the functions of the home page.
Knowledge points used
BottomNavigationBar
Bottom navigation bar basic properties
-
Named Routes: For more information see the Detailed description of the Flutter navigation and Routing stack
-
Screen adaptation: The flutter_screenUtil plugin is used, which has the following properties
Pass in the size of the design, px, px, px! // ScreenUtil().setwidth (540) // ScreenUtil().setheight (200) // ScreenUtil().setsp (24) // ScreenUtil().setwidth (540) // ScreenUtil().setheight (200) // ScreenUtil().setsp (24 ScreenUtil().setSp(24, allowFontScalingSelf: ScreenUtil().setsp (24, allowFontScalingSelf: ScreenUtil().setsp (24, allowFontScalingSelf: ScreenUtil().pixelRatio // Pixel density of the device ScreenUtil().screenWidth // Device width ScreenUtil().screenheight // device height ScreenUtil(). StatusBarHeight // statusBarHeight bangs are higher unit dp ScreenUtil(). TextScaleFactor ScreenUtil().scaleWidth // ScreenUtil().scaleheight // ScreenUtil().scaleHeight // ScreenUtil()Copy the code
- Network request usage
dio
Plug-in implementation, detailed explanation can see the official website:Github.com/flutterchin…
import 'package:dio/dio.dart';
void main() async {
var dio = Dio();
final response = await dio.get('https://google.com');
print(response.data);
}
Copy the code
- Use of the rotation chart
swiper
A plugin
SwiperPagination
BottomCenter The distance between the page indicator and the container border margin EdgeInsets. All (10.0) The style of the page indicator Fraction Custom style Builder swiperpagination.dotsCopy the code
- Page frame usage
ListView
Implement the list
- The list of goods is used
Wrap
, streaming layout, automatic wrapping
Direction: the direction of the mainAxis. The default is horizontal. Alignment: Alignment in the main axis direction. The default value is Start. Spacing: The spacing along the main axis. RunAlignment: Alignment of the run. Run can be interpreted as a new row or column, or as a new row if the layout is horizontal. RunSpacing: The spacing between runs. CrossAxisAlignment: Alignment in the direction of a crossAxis. TextDirection: indicates the textDirection. VerticalDirection: defines the order in which children are placed. The default value is down.Copy the code
Project construction
Dart and four bottom tabs (home.dart, category.dart, cart.dart, user.dart).
Just post the main code here:
bottomNavigationBar: BottomNavigationBar( currentIndex:_currentIndex , onTap: (index){ setState(() { _currentIndex=index; }); }, type:BottomNavigationBarType.fixed , fixedColor:Colors.red, items: [ BottomNavigationBarItem( icon: Icon(Icons. Home), label: "home"), BottomNavigationBarItem(Icon: Icon(Icons. Category), label: BottomNavigationBarItem(icon: icon (Icons. Shopping_cart), label: "cart"), BottomNavigationBarItem(icon: Icon(Icons. People), label: "my")],),Copy the code
Configuring named Routes
To facilitate unified management, create a Router folder and create a router.dart class in the folder to manage routes
Final Map<String,Function> routes = {'/': (context) => Tabs(),arguments,),}; Var onGenerateRoute = (RouteSettings Settings) {final String? name = settings.name; final Function? pageContentBuilder = routes[name]; if (pageContentBuilder ! = null) { if (settings.arguments ! = null) { final Route route = MaterialPageRoute( builder: (context) => pageContentBuilder(context, arguments: settings.arguments)); return route; } else { final Route route = MaterialPageRoute(builder: (context) => pageContentBuilder(context)); return route; }}};Copy the code
Screen adaptation
Here I choose Flutter_screenUtil for screen adaptation. Flutter_screenutil is added in Pubspec.yaml by default using 750*1334 designs as the standard
Flutter_screenutil: ^ 5.0.0 + 2Copy the code
Then click Pub get to pull. Create a Services folder and create the Screen_Adapter.dart class to implement common functions
import 'package:flutter_screenutil/flutter_screenutil.dart'; Static height(num value) {return ScreenUtil().setheight (value); } static width(num value) { return ScreenUtil().setWidth(value); } static size(num value) { return ScreenUtil().setSp(value); } static getScreenWidth() {return ScreenUtil().screenWidth; } static getScreenHeight() {return ScreenUtil().screenheight; } static double statusBarHeight = ScreenUtil().statusbarheight; Static double bottomBarHeight = ScreenUtil().bottombarheight; }Copy the code
The specific implementation
The overall framework of the page is realized using ListView, and the content is divided into the following three blocks:
- The Swiper plugin is used to display the banner area
- Guess your favorite horizontal scrolling list via ListView
- Vertical scrolling list of top recommendations, via Wrap
Implement the banner area of the broadcast map
Firstly, flutter_swiper_NULl_safety: ^1.0.2 was introduced. The rotation chart was the data obtained from the network. Dio: ^4.0.0 was also introduced for network request, and then the pub GET pull was performed.
Dart creates the focus_model.dart model for the cast map, and the code inside is implemented as
class FocusModel { List<FocusItemModel> result=[]; FocusModel({required this.result}); FocusModel.fromJson(Map<String, dynamic> json) { if (json['result'] ! = null) { json['result'].forEach((v) { result.add(new FocusItemModel.fromJson(v)); }); } } Map<String, dynamic> toJson() { final Map<String, dynamic> data = new Map<String, dynamic>(); data['result'] = this.result.map((v) => v.toJson()).toList(); return data; } } class FocusItemModel { String? sId; // Nullable type String? title; String? status; String? pic; String? url; FocusItemModel({this.sId, this.title, this.status, this.pic, this.url}); FocusItemModel.fromJson(Map<String, dynamic> json) { sId = json['_id']; title = json['title']; status = json['status']; pic = json['pic']; url = json['url']; } Map<String, dynamic> toJson() { final Map<String, dynamic> data = new Map<String, dynamic>(); data['_id'] = this.sId; data['title'] = this.title; data['status'] = this.status; data['pic'] = this.pic; data['url'] = this.url; return data; }}Copy the code
Get banner data
/ / get hot recommended data _getBestProductData () async {var API = 'https://jdmall.itying.com/api/plist?is_best=1'; var result = await Dio().get(api); var bestProductList = ProductModel.fromJson(result.data); setState(() { this._bestProductList = bestProductList.result; }); }Copy the code
Create a caroute diagram
Widget _swiperWidget() { if (this._focusData.length > 0) { return Container( child: AspectRatio( aspectRatio: 2 / 1, child: Swiper( itemBuilder: (BuildContext context, int index) { String pic = this._focusData[index].pic; pic = Config.domain + pic.replaceAll('\', '/'); return new Image.network( "${pic}", fit: BoxFit.fill, ); }, itemCount: this._focusData.length, pagination: new SwiperPagination(), autoplay: true), ), ); } else {return Text(' Loading... '); }}Copy the code
The specific code is as follows:
List _focusData = [];
@override
void initState() {
super.initState();
_getFocusData();
}
@override
Widget build(BuildContext context) {
return ListView(
children: <Widget>[
_swiperWidget(),
],
);
}
Copy the code
Then run the project to achieve this effect, the rotation map function is ready
Achieve the effect of guessing you like
Encapsulate a method and return a Widget
Widget _titleWidget(value) {
return Container(
height: ScreenAdapter.height(32),
margin: EdgeInsets.only(left: ScreenAdapter.width(20)),
padding: EdgeInsets.only(left: ScreenAdapter.width(20)),
decoration: BoxDecoration(
border: Border(
left: BorderSide(
color: Colors.red,
width: ScreenAdapter.width(10),
))),
child: Text(
value,
style: TextStyle(color: Colors.black54),
),
);
}
Copy the code
Get guess what you like about web data
_getHotProductData() async {var API = '${config.domain} API /plist? is_hot=1'; var result = await Dio().get(api); var hotProductList = ProductModel.fromJson(result.data); setState(() { this._hotProductList = hotProductList.result; }); }Copy the code
Create a horizontal list of guesses you like
// If (_hotproductList.length > 0) {return Container(height: ScreenAdapter.height(234), padding: EdgeInsets.all(ScreenAdapter.width(20)), child: Listview. builder(// Set scrollDirection: Axis. Horizontal, itemBuilder: SPic = _hotProductList[index].spic; contxt = _hotProductList[index].spic; SPic = config. domain + spic. replaceAll('\', '/'); return Column( children: <Widget>[ Container( height: ScreenAdapter.height(140), width: ScreenAdapter.width(140), margin: EdgeInsets.only(right: ScreenAdapter.width(21)), child: Image.network(sPic, fit: BoxFit.cover), ), Container( padding: EdgeInsets.only(top: ScreenAdapter.height(10)), height: Screenadapter.height (44), child: Text("¥${_hotProductList[index]. Price}", style: TextStyle(color: red) Colors.red), ), ) ], ); }, itemCount: _hotProductList.length, ), ); } else { return Text(""); }}Copy the code
Implementation effect
Implement popular recommendation features
Get data on popular recommendations
_getBestProductData() async { var api = '${Config.domain}api/plist? is_best=1'; var result = await Dio().get(api); var bestProductList = ProductModel.fromJson(result.data); setState(() { this._bestProductList = bestProductList.result; }); }Copy the code
Creating an item list
Widget _recProductListWidget() { var itemWidth = (ScreenAdapter.getScreenWidth() - 30) / 2; return Container( padding: EdgeInsets.all(10), child: Wrap( runSpacing: 10, spacing: 10, children: This._bestproductlist.map ((value) {String sPic = value.spic == null? '' : value.sPic; sPic = Config.domain+sPic.replaceAll('\', '/'); return Container( padding: EdgeInsets.all(10), width: itemWidth, decoration: BoxDecoration( border: Border.all( color: Color.fromrgbo (233, 233, 233, 0.9), width: 1)), child: Column(children: <Widget>[Container(width: Double. Infinity, child: AspectRatio(AspectRatio: 1/1) Image.network( "${sPic}", fit: BoxFit.cover, ), ), ), Padding( padding: EdgeInsets.only(top: ScreenAdapter.height(20)), child: Text( "${value.title}", maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle(color: Colors.black54), ), ), Padding( padding: EdgeInsets.only(top: ScreenAdapter.height(20)), child: Stack(children: <Widget>[Align: Align. CenterLeft, child: Text("¥${value.price}", style: TextStyle(color: Colors.red, fontSize: 16), ), ), Align( alignment: Alignment.centerRight, child: Text("¥${value.oldprice}", style: TextStyle(color: color.black54, fontSize: 14, decoration: color: color. TextDecoration.lineThrough)), ) ], ), ) ], ), ); }).toList(), ), ); }Copy the code