├── xmlyfm ├── android │ ├── gradle.properties │ ├── key.properties │ ├── app │ │ ├── src │ │ │ └── main │ │ │ │ ├── res │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values │ │ │ │ │ └── styles.xml │ │ │ │ └── drawable │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── linxunfeng │ │ │ │ │ └── xmlyfm │ │ │ │ │ └── MainActivity.java │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── settings.gradle │ └── build.gradle ├── images │ ├── tabbar │ │ ├── host_find_tab_01.png │ │ ├── host_find_tab_15.png │ │ ├── host_mine_tab_01.png │ │ ├── host_mine_tab_15.png │ │ ├── host_home_page_tab_01.png │ │ ├── host_home_page_tab_15.png │ │ ├── host_my_listen_tab_01.png │ │ ├── host_my_listen_tab_15.png │ │ └── host_theme_global_play_default.png │ └── me │ │ ├── host_default_avatar_88.png │ │ ├── host_theme_ic_title_bar_message.png │ │ ├── host_theme_ic_title_bar_setting.png │ │ └── host_theme_ic_title_bar_message_pressed.png ├── ios │ ├── Flutter │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── AppFrameworkInfo.plist │ ├── Runner │ │ ├── AppDelegate.h │ │ ├── Assets.xcassets │ │ │ ├── LaunchImage.imageset │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ ├── README.md │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ │ └── Contents.json │ │ ├── main.m │ │ ├── AppDelegate.m │ │ ├── Info.plist │ │ └── Base.lproj │ │ │ ├── Main.storyboard │ │ │ └── LaunchScreen.storyboard │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── xcschemes │ │ │ │ └── Runner.xcscheme │ │ └── project.pbxproj │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── WorkspaceSettings.xcsettings │ └── Podfile ├── lib │ ├── Configs │ │ ├── configs.dart │ │ ├── xmly_api.dart │ │ └── Router │ │ │ ├── xmly_router_home.dart │ │ │ └── xmly_router.dart │ ├── Modules │ │ ├── Find │ │ │ └── find_route.dart │ │ ├── Home │ │ │ ├── Views │ │ │ │ ├── detail_bottom_line.dart │ │ │ │ ├── detail_title_more.dart │ │ │ │ ├── detail_refresh.dart │ │ │ │ ├── detail_square.dart │ │ │ │ ├── detail_oneKeyListen.dart │ │ │ │ ├── home_search.dart │ │ │ │ ├── detail_focus.dart │ │ │ │ ├── detail_topBuzz.dart │ │ │ │ ├── detail_playlist.dart │ │ │ │ ├── detail_guessYouLike.dart │ │ │ │ ├── detail_microLesson.dart │ │ │ │ ├── detail_paidCategory.dart │ │ │ │ ├── detail_live.dart │ │ │ │ ├── detail_categoriesForShort.dart │ │ │ │ ├── detail_recommendAlbum.dart │ │ │ │ └── detail_categoriesForLong.dart │ │ │ ├── DetailList │ │ │ │ ├── Model │ │ │ │ │ ├── album_track.dart │ │ │ │ │ ├── album_user.dart │ │ │ │ │ ├── album_track.g.dart │ │ │ │ │ ├── album_user.g.dart │ │ │ │ │ ├── album_track_item.dart │ │ │ │ │ ├── album.dart │ │ │ │ │ ├── album_track_item.g.dart │ │ │ │ │ └── album.g.dart │ │ │ │ └── home_detail_list_route.dart │ │ │ ├── Model │ │ │ │ ├── home_category.dart │ │ │ │ ├── home_detail_keyword.dart │ │ │ │ ├── home_category.g.dart │ │ │ │ ├── home_recommend.dart │ │ │ │ ├── home_detail_keyword.g.dart │ │ │ │ ├── home_category_item.dart │ │ │ │ ├── home_recommend.g.dart │ │ │ │ ├── home_detail.g.dart │ │ │ │ ├── home_category_item.g.dart │ │ │ │ ├── home_detail.dart │ │ │ │ ├── home_detail_list.dart │ │ │ │ └── home_detail_list.g.dart │ │ │ ├── home_detail_route.dart │ │ │ └── home_route.dart │ │ ├── Basic │ │ │ ├── vertical_button.dart │ │ │ ├── ft_collection_view.dart │ │ │ └── tab_bar.dart │ │ ├── Listen │ │ │ ├── Header │ │ │ │ └── listen_header.dart │ │ │ └── listen_route.dart │ │ └── Me │ │ │ ├── Cell │ │ │ └── me_cell.dart │ │ │ ├── me_route.dart │ │ │ └── Header │ │ │ └── me_header.dart │ └── main.dart ├── .metadata ├── README.md ├── test │ └── widget_test.dart ├── .gitignore └── pubspec.yaml ├── Screenshots ├── Me │ └── me.png └── Home │ └── 1.gif ├── README.md ├── .gitignore └── LICENSE /xmlyfm/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /Screenshots/Me/me.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/Screenshots/Me/me.png -------------------------------------------------------------------------------- /Screenshots/Home/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/Screenshots/Home/1.gif -------------------------------------------------------------------------------- /xmlyfm/android/key.properties: -------------------------------------------------------------------------------- 1 | storePassword=123456 2 | keyPassword=123456 3 | keyAlias=key 4 | storeFile=/Users/lxf/key.jks -------------------------------------------------------------------------------- /xmlyfm/images/tabbar/host_find_tab_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/images/tabbar/host_find_tab_01.png -------------------------------------------------------------------------------- /xmlyfm/images/tabbar/host_find_tab_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/images/tabbar/host_find_tab_15.png -------------------------------------------------------------------------------- /xmlyfm/images/tabbar/host_mine_tab_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/images/tabbar/host_mine_tab_01.png -------------------------------------------------------------------------------- /xmlyfm/images/tabbar/host_mine_tab_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/images/tabbar/host_mine_tab_15.png -------------------------------------------------------------------------------- /xmlyfm/images/me/host_default_avatar_88.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/images/me/host_default_avatar_88.png -------------------------------------------------------------------------------- /xmlyfm/images/tabbar/host_home_page_tab_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/images/tabbar/host_home_page_tab_01.png -------------------------------------------------------------------------------- /xmlyfm/images/tabbar/host_home_page_tab_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/images/tabbar/host_home_page_tab_15.png -------------------------------------------------------------------------------- /xmlyfm/images/tabbar/host_my_listen_tab_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/images/tabbar/host_my_listen_tab_01.png -------------------------------------------------------------------------------- /xmlyfm/images/tabbar/host_my_listen_tab_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/images/tabbar/host_my_listen_tab_15.png -------------------------------------------------------------------------------- /xmlyfm/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /xmlyfm/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /xmlyfm/images/me/host_theme_ic_title_bar_message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/images/me/host_theme_ic_title_bar_message.png -------------------------------------------------------------------------------- /xmlyfm/images/me/host_theme_ic_title_bar_setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/images/me/host_theme_ic_title_bar_setting.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /xmlyfm/images/tabbar/host_theme_global_play_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/images/tabbar/host_theme_global_play_default.png -------------------------------------------------------------------------------- /xmlyfm/lib/Configs/configs.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | // 颜色 4 | final themeColor = Color(0xFFFF7152); 5 | final bgColor = Color(0xFFF3F4F5); -------------------------------------------------------------------------------- /xmlyfm/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /xmlyfm/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /xmlyfm/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /xmlyfm/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /xmlyfm/images/me/host_theme_ic_title_bar_message_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/images/me/host_theme_ic_title_bar_message_pressed.png -------------------------------------------------------------------------------- /xmlyfm/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XMLYFM 2 | Flutter版 喜马拉雅FM 3 | 4 | 5 | 6 | ## Exhibition 7 | 8 | 9 | 10 | ![首页](./Screenshots/Home/1.gif) 11 | 12 | -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterX/XMLYFM/HEAD/xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /xmlyfm/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /xmlyfm/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip 7 | -------------------------------------------------------------------------------- /xmlyfm/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /xmlyfm/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildSystemType 6 | Original 7 | 8 | 9 | -------------------------------------------------------------------------------- /xmlyfm/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 3cca1a2ec35604ca50f9c656b8e761b07a00a9ed 8 | channel: dev 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Find/find_route.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class FindRoute extends StatefulWidget { 4 | @override 5 | _FindRouteState createState() => _FindRouteState(); 6 | } 7 | 8 | class _FindRouteState extends State { 9 | @override 10 | Widget build(BuildContext context) { 11 | return Text("发现"); 12 | } 13 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Views/detail_bottom_line.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Configs/configs.dart'; 3 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 4 | 5 | class DetailBottomLine extends StatelessWidget { 6 | @override 7 | Widget build(BuildContext context) { 8 | return Container(height: fs>10.0, color: bgColor); 9 | } 10 | } -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://www.dartlang.org/guides/libraries/private-files 2 | 3 | # Files and directories created by pub 4 | .dart_tool/ 5 | .packages 6 | .pub/ 7 | build/ 8 | # If you're building an application, you may want to check-in your pubspec.lock 9 | pubspec.lock 10 | 11 | # Directory created by dartdoc 12 | # If you don't generate documentation locally you can remove this line. 13 | doc/api/ 14 | -------------------------------------------------------------------------------- /xmlyfm/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /xmlyfm/android/app/src/main/java/com/linxunfeng/xmlyfm/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.linxunfeng.xmlyfm; 2 | 3 | import android.os.Bundle; 4 | import io.flutter.app.FlutterActivity; 5 | import io.flutter.plugins.GeneratedPluginRegistrant; 6 | 7 | public class MainActivity extends FlutterActivity { 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | GeneratedPluginRegistrant.registerWith(this); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #include "AppDelegate.h" 2 | #include "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /xmlyfm/lib/Configs/xmly_api.dart: -------------------------------------------------------------------------------- 1 | 2 | final httpScheme = "http://"; 3 | final httpsScheme = "https://"; 4 | 5 | // 网络 6 | final xmlyDomain = "mobwsa.ximalaya.com/"; 7 | 8 | // 首页 9 | final home_category = httpScheme + xmlyDomain + "discovery-category/customCategories/1545621060064"; 10 | // 首页详情 11 | final home_detail = httpScheme + xmlyDomain + "discovery-firstpage/v2/explore/ts-1545621064936"; 12 | // 首页推荐 13 | final home_recommend = httpScheme + xmlyDomain + "subscribe/v2/subscribe/home/recommend"; 14 | -------------------------------------------------------------------------------- /xmlyfm/lib/Configs/Router/xmly_router_home.dart: -------------------------------------------------------------------------------- 1 | import 'package:fluro/fluro.dart'; 2 | import 'package:xmlyfm/Configs/Router/xmly_router.dart'; 3 | import 'package:xmlyfm/Modules/Home/DetailList/home_detail_list_route.dart'; 4 | 5 | class XMLYRouterHome { 6 | 7 | XMLYRouterHome.register(Router router) { 8 | router.define(XMLYRouterHandler.fetchRoute('home_detail_list'), 9 | handler: Handler(handlerFunc: (context, Map params) { 10 | return HomeDetailListRoute(); 11 | })); 12 | } 13 | } -------------------------------------------------------------------------------- /xmlyfm/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /xmlyfm/lib/Configs/Router/xmly_router.dart: -------------------------------------------------------------------------------- 1 | import 'package:fluro/fluro.dart'; 2 | import 'package:xmlyfm/Configs/Router/xmly_router_home.dart'; 3 | 4 | class XMLYRouterHandler { 5 | static final scheme = 'xmlyapp'; 6 | static final router = Router(); 7 | 8 | XMLYRouterHandler.init() { 9 | _register(); 10 | } 11 | 12 | void _register() { 13 | // Home 14 | XMLYRouterHome.register(router); 15 | } 16 | 17 | static String fetchRoute(String path) { 18 | return XMLYRouterHandler.scheme + '://' + path; 19 | } 20 | } -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /xmlyfm/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /xmlyfm/README.md: -------------------------------------------------------------------------------- 1 | # xmlyfm 2 | 3 | A Flutter XMLYFM App 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.io/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/DetailList/Model/album_track.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | import 'album_track_item.dart'; 3 | 4 | part 'album_track.g.dart'; 5 | 6 | @JsonSerializable() 7 | class AlbumTrack { 8 | AlbumTrack(this.maxPageId, this.pageId, this.pageSize, this.totalCount, this.list); 9 | 10 | int maxPageId; 11 | int pageId; 12 | int pageSize; 13 | int totalCount; 14 | List list; 15 | 16 | factory AlbumTrack.fromJson(Map json) => _$AlbumTrackFromJson(json); 17 | Map toJson() => _$AlbumTrackToJson(this); 18 | } -------------------------------------------------------------------------------- /xmlyfm/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.2.1' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Model/home_category.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | import 'home_category_item.dart'; 3 | 4 | part 'home_category.g.dart'; 5 | 6 | @JsonSerializable() 7 | class HomeCategory { 8 | HomeCategory( 9 | this.groupName, 10 | this.itemList, 11 | this.hideInModify, 12 | ); 13 | 14 | String groupName; // 推荐 15 | List itemList; 16 | bool hideInModify; // true 17 | 18 | 19 | factory HomeCategory.fromJson(Map json) => _$HomeCategoryFromJson(json); 20 | Map toJson() => _$HomeCategoryToJson(this); 21 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Model/home_detail_keyword.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'home_detail_keyword.g.dart'; 4 | 5 | @JsonSerializable() 6 | class HomeDetailKeyword { 7 | HomeDetailKeyword( 8 | this.categoryId, 9 | this.categoryTitle, 10 | this.keywordId, 11 | this.keywordName, 12 | this.keywordType, 13 | this.materialType, 14 | this.realCategoryId, 15 | ); 16 | 17 | int categoryId; // 4 18 | String categoryTitle; // 娱乐 19 | int keywordId; 20 | String keywordName; 21 | int keywordType; 22 | String materialType; 23 | int realCategoryId; 24 | 25 | factory HomeDetailKeyword.fromJson(Map json) => _$HomeDetailKeywordFromJson(json); 26 | Map toJson() => _$HomeDetailKeywordToJson(this); 27 | } -------------------------------------------------------------------------------- /xmlyfm/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/DetailList/Model/album_user.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'album_user.g.dart'; 4 | 5 | @JsonSerializable() 6 | class AlbumUser { 7 | 8 | int albums; 9 | int anchorGrade; 10 | int followers; 11 | int followings; 12 | int liveRoomId; 13 | int liveStatus; 14 | int tracks; 15 | int uid; 16 | int verifyType; 17 | bool isVerified; 18 | String nickname; 19 | String personDescribe; 20 | String personalSignature; 21 | String smallLogo; 22 | 23 | AlbumUser(this.albums, this.anchorGrade, this.followers, this.followings, this.liveRoomId, this.liveStatus, this.tracks, this.uid, this.verifyType, this.isVerified, this.nickname, this.personDescribe, this.personalSignature, this.smallLogo); 24 | 25 | factory AlbumUser.fromJson(Map json) => _$AlbumUserFromJson(json); 26 | Map toJson() => _$AlbumUserToJson(this); 27 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Model/home_category.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'home_category.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | HomeCategory _$HomeCategoryFromJson(Map json) { 10 | return HomeCategory( 11 | json['groupName'] as String, 12 | (json['itemList'] as List) 13 | ?.map((e) => e == null 14 | ? null 15 | : HomeCategoryItem.fromJson(e as Map)) 16 | ?.toList(), 17 | json['hideInModify'] as bool); 18 | } 19 | 20 | Map _$HomeCategoryToJson(HomeCategory instance) => 21 | { 22 | 'groupName': instance.groupName, 23 | 'itemList': instance.itemList, 24 | 'hideInModify': instance.hideInModify 25 | }; 26 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Basic/vertical_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class VerticalButton extends StatelessWidget { 4 | VerticalButton({ 5 | Key key, 6 | @required this.onPressed, 7 | this.title, 8 | this.icon, 9 | this.space = 0, 10 | this.backgroundColor = Colors.transparent 11 | }); 12 | /// 标题 13 | final Widget title; 14 | /// 背景颜色 15 | final Color backgroundColor; 16 | /// 点击回调 17 | final VoidCallback onPressed; 18 | /// 间距 19 | final double space; 20 | /// 图标 21 | final Widget icon; 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | return FlatButton( 26 | color: backgroundColor, 27 | child: Column( 28 | mainAxisAlignment: MainAxisAlignment.center, 29 | children: [ 30 | icon, 31 | Container(height: space,), 32 | title, 33 | ], 34 | ), 35 | onPressed: onPressed, 36 | ); 37 | } 38 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Views/detail_title_more.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 3 | 4 | class DetailTitleMore extends StatelessWidget { 5 | DetailTitleMore(this.title) : assert(title != null); 6 | final String title; 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return Container( 11 | height: fs>50.0, 12 | child: Padding( 13 | padding: EdgeInsets.symmetric(horizontal: fs>10.0), 14 | child: Row( 15 | children: [ 16 | Expanded( child: Text(title, style: TextStyle(fontSize: fs>18.0, fontWeight: FontWeight.w900),)), 17 | InkWell( 18 | child: Text('更多', style: TextStyle(fontSize: fs>15.0),), 19 | ), 20 | Icon(Icons.arrow_right, size: fs>24.0,) 21 | ], 22 | ), 23 | ), 24 | ); 25 | } 26 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Model/home_recommend.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | import 'home_category_item.dart'; 3 | 4 | part 'home_recommend.g.dart'; 5 | 6 | @JsonSerializable() 7 | class HomeRecommend { 8 | HomeRecommend( 9 | this.albumId, this.isFinished, this.lastUpdateAt, this.refundSupportType, this.isDraft, this.isPaid, this.albumLabel, this.cornerMark, this.coverMiddle, this.coverSmall, this.nickname, this.recReason, this.recSrc, this.recTrack, this.title 10 | ); 11 | 12 | int albumId; 13 | int isFinished; 14 | int lastUpdateAt; 15 | int refundSupportType; 16 | bool isDraft; 17 | bool isPaid; 18 | String albumLabel; 19 | String cornerMark; 20 | String coverMiddle; 21 | String coverSmall; 22 | String nickname; 23 | String recReason; 24 | String recSrc; 25 | String recTrack; 26 | String title; 27 | 28 | 29 | factory HomeRecommend.fromJson(Map json) => _$HomeRecommendFromJson(json); 30 | Map toJson() => _$HomeRecommendToJson(this); 31 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/DetailList/Model/album_track.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'album_track.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | AlbumTrack _$AlbumTrackFromJson(Map json) { 10 | return AlbumTrack( 11 | json['maxPageId'] as int, 12 | json['pageId'] as int, 13 | json['pageSize'] as int, 14 | json['totalCount'] as int, 15 | (json['list'] as List) 16 | ?.map((e) => e == null 17 | ? null 18 | : AlbumTrackItem.fromJson(e as Map)) 19 | ?.toList()); 20 | } 21 | 22 | Map _$AlbumTrackToJson(AlbumTrack instance) => 23 | { 24 | 'maxPageId': instance.maxPageId, 25 | 'pageId': instance.pageId, 26 | 'pageSize': instance.pageSize, 27 | 'totalCount': instance.totalCount, 28 | 'list': instance.list 29 | }; 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /xmlyfm/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:xmlyfm/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Model/home_detail_keyword.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'home_detail_keyword.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | HomeDetailKeyword _$HomeDetailKeywordFromJson(Map json) { 10 | return HomeDetailKeyword( 11 | json['categoryId'] as int, 12 | json['categoryTitle'] as String, 13 | json['keywordId'] as int, 14 | json['keywordName'] as String, 15 | json['keywordType'] as int, 16 | json['materialType'] as String, 17 | json['realCategoryId'] as int); 18 | } 19 | 20 | Map _$HomeDetailKeywordToJson(HomeDetailKeyword instance) => 21 | { 22 | 'categoryId': instance.categoryId, 23 | 'categoryTitle': instance.categoryTitle, 24 | 'keywordId': instance.keywordId, 25 | 'keywordName': instance.keywordName, 26 | 'keywordType': instance.keywordType, 27 | 'materialType': instance.materialType, 28 | 'realCategoryId': instance.realCategoryId 29 | }; 30 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Views/detail_refresh.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Configs/configs.dart'; 3 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 4 | 5 | class DetailRefresh extends StatelessWidget { 6 | @override 7 | Widget build(BuildContext context) { 8 | return Container( 9 | height: fs>70.0, 10 | child: Center( 11 | child: Container( 12 | width: fs>90.0, 13 | height: fs>30.0, 14 | decoration: BoxDecoration( 15 | color: Colors.white, 16 | boxShadow: [ 17 | BoxShadow(color: Colors.black54) 18 | ], 19 | borderRadius: BorderRadius.circular(fs>15.0) 20 | ), 21 | child: Row( 22 | mainAxisAlignment: MainAxisAlignment.center, 23 | children: [ 24 | Icon(Icons.refresh, color: themeColor,), 25 | Container(width: fs>5.0,), 26 | Text('换一批', style: TextStyle(fontSize: fs>15.0, fontWeight: FontWeight.bold),) 27 | ], 28 | ), 29 | ), 30 | ), 31 | ); 32 | } 33 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Model/home_category_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'home_category_item.g.dart'; 4 | 5 | @JsonSerializable() 6 | class HomeCategoryItem { 7 | HomeCategoryItem( 8 | this.id, 9 | this.title, 10 | this.itemType, 11 | this.categoryId, 12 | this.categoryType, 13 | this.moduleType, 14 | this.isDisplayCornerMark, 15 | this.cornerMark, 16 | this.coverPath, 17 | this.unactiveCoverPath, 18 | this.activeCoverPath, 19 | this.recommendType, 20 | this.url, 21 | this.defaultSelected, 22 | this.audioStreamId, 23 | this.hideInReview, 24 | ); 25 | 26 | String id; // single_category-49 27 | String title; // 小说 28 | String itemType; // single_category 29 | int categoryId; // 49 30 | String categoryType; 31 | String moduleType; 32 | bool isDisplayCornerMark; 33 | String cornerMark; 34 | String coverPath; 35 | String unactiveCoverPath; 36 | String activeCoverPath; 37 | String recommendType; // normal 38 | String url; 39 | bool defaultSelected; // false 40 | String audioStreamId; 41 | bool hideInReview; // true 42 | 43 | 44 | factory HomeCategoryItem.fromJson(Map json) => _$HomeCategoryItemFromJson(json); 45 | Map toJson() => _$HomeCategoryItemToJson(this); 46 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Listen/Header/listen_header.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Modules/Basic/vertical_button.dart'; 3 | import 'package:xmlyfm/Configs/configs.dart'; 4 | 5 | class ListenHeader extends StatelessWidget { 6 | final Map funcMap = { 7 | '下载' : Icon(Icons.file_download, color: themeColor,), 8 | '历史' : Icon(Icons.history, color: themeColor), 9 | '已购' : Icon(Icons.shopping_cart, color: themeColor), 10 | '听单' : Icon(Icons.receipt, color: themeColor), 11 | }; 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return DecoratedBox( 16 | decoration: BoxDecoration( 17 | color: Colors.white, 18 | borderRadius: BorderRadius.circular(4.0), 19 | boxShadow: [ 20 | BoxShadow( 21 | color: Color(0xFFF8F8F8), 22 | blurRadius: 5.0, 23 | offset: Offset(0, 5.0)) 24 | ]), 25 | child: Row( 26 | children: funcMap.map((title, icon){ 27 | return MapEntry(title, Expanded(child: VerticalButton( 28 | title: Text(title), 29 | icon: icon, 30 | space: 5.0, 31 | onPressed: (){ 32 | print(title); 33 | }, 34 | ),)); 35 | }).values.toList(), 36 | ), 37 | ); 38 | } 39 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/DetailList/home_detail_list_route.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Configs/xmly_api.dart'; 3 | import 'dart:convert'; 4 | import 'package:dio/dio.dart'; 5 | import 'Model/album.dart'; 6 | import 'Model/album_user.dart'; 7 | import 'Model/album_track.dart'; 8 | 9 | class HomeDetailListRoute extends StatefulWidget { 10 | @override 11 | _HomeDetailListRouteState createState() => _HomeDetailListRouteState(); 12 | } 13 | 14 | class _HomeDetailListRouteState extends State { 15 | 16 | @override 17 | void initState() { 18 | super.initState(); 19 | 20 | _fetchList(); 21 | } 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | return Scaffold( 26 | appBar: AppBar( 27 | title: Text("萌宠"), 28 | backgroundColor: Colors.yellow, 29 | ), 30 | body: Text('HomeDetailListRoute'), 31 | ); 32 | } 33 | 34 | void _fetchList() async { 35 | print('_fetchList'); 36 | final dio = Dio(); 37 | final response = await dio.get(home_detail_list, data: { 38 | "albumId" : 13395123, 39 | "device" : "android", 40 | "isAsc" : true, 41 | "isQueryInvitationBrand" : true, 42 | "pageId" : 1, 43 | "pageSize" : 20, 44 | "pre_page" : 0 45 | }); 46 | final data = json.decode(response.data); 47 | final album = Album.fromJson(data['data']['album']); 48 | final albumUser = AlbumUser.fromJson(data['data']['user']); 49 | final albumTrack = AlbumTrack.fromJson(data['data']['tracks']); 50 | } 51 | } -------------------------------------------------------------------------------- /xmlyfm/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.lock 4 | *.log 5 | *.pyc 6 | *.swp 7 | .DS_Store 8 | .atom/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # Visual Studio Code related 20 | .vscode/ 21 | 22 | # Flutter/Dart/Pub related 23 | **/doc/api/ 24 | .dart_tool/ 25 | .flutter-plugins 26 | .packages 27 | .pub-cache/ 28 | .pub/ 29 | build/ 30 | 31 | # Android related 32 | **/android/**/gradle-wrapper.jar 33 | **/android/.gradle 34 | **/android/captures/ 35 | **/android/gradlew 36 | **/android/gradlew.bat 37 | **/android/local.properties 38 | **/android/**/GeneratedPluginRegistrant.java 39 | 40 | # iOS/XCode related 41 | **/ios/**/*.mode1v3 42 | **/ios/**/*.mode2v3 43 | **/ios/**/*.moved-aside 44 | **/ios/**/*.pbxuser 45 | **/ios/**/*.perspectivev3 46 | **/ios/**/*sync/ 47 | **/ios/**/.sconsign.dblite 48 | **/ios/**/.tags* 49 | **/ios/**/.vagrant/ 50 | **/ios/**/DerivedData/ 51 | **/ios/**/Icon? 52 | **/ios/**/Pods/ 53 | **/ios/**/.symlinks/ 54 | **/ios/**/profile 55 | **/ios/**/xcuserdata 56 | **/ios/.generated/ 57 | **/ios/Flutter/App.framework 58 | **/ios/Flutter/Flutter.framework 59 | **/ios/Flutter/Generated.xcconfig 60 | **/ios/Flutter/app.flx 61 | **/ios/Flutter/app.zip 62 | **/ios/Flutter/flutter_assets/ 63 | **/ios/ServiceDefinitions.json 64 | **/ios/Runner/GeneratedPluginRegistrant.* 65 | 66 | # Exceptions to above rules. 67 | !**/ios/**/default.mode1v3 68 | !**/ios/**/default.mode2v3 69 | !**/ios/**/default.pbxuser 70 | !**/ios/**/default.perspectivev3 71 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 72 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Views/detail_square.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Modules/Home/Model/home_detail_list.dart'; 3 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 4 | 5 | class DetailSquare extends StatelessWidget { 6 | DetailSquare(this.models) : assert(models != null); 7 | 8 | final List models; 9 | 10 | @override 11 | Widget build(BuildContext context) { 12 | return SliverPadding( 13 | padding: EdgeInsets.all(15.0), 14 | sliver: SliverGrid( 15 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( 16 | crossAxisCount: 5, // Grid按五列显示 17 | mainAxisSpacing: fs>10.0, 18 | crossAxisSpacing: fs>10.0, 19 | childAspectRatio: 1.0, 20 | ), 21 | delegate: SliverChildBuilderDelegate((context, index) { 22 | // 创建子widget 23 | return Column( 24 | mainAxisAlignment: MainAxisAlignment.center, 25 | children: [ 26 | Image.network(models[index].coverPath, width: fs>>40.0), 27 | Padding( 28 | padding: EdgeInsets.only(top: 5.0), 29 | child: Text( 30 | models[index].title, 31 | style: TextStyle( 32 | color: Colors.black54, 33 | fontWeight: FontWeight.bold, 34 | fontSize: fs>>10.0), 35 | ), 36 | ) 37 | ], 38 | ); 39 | }, childCount: models.length), 40 | ), 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/DetailList/Model/album_user.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'album_user.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | AlbumUser _$AlbumUserFromJson(Map json) { 10 | return AlbumUser( 11 | json['albums'] as int, 12 | json['anchorGrade'] as int, 13 | json['followers'] as int, 14 | json['followings'] as int, 15 | json['liveRoomId'] as int, 16 | json['liveStatus'] as int, 17 | json['tracks'] as int, 18 | json['uid'] as int, 19 | json['verifyType'] as int, 20 | json['isVerified'] as bool, 21 | json['nickname'] as String, 22 | json['personDescribe'] as String, 23 | json['personalSignature'] as String, 24 | json['smallLogo'] as String); 25 | } 26 | 27 | Map _$AlbumUserToJson(AlbumUser instance) => { 28 | 'albums': instance.albums, 29 | 'anchorGrade': instance.anchorGrade, 30 | 'followers': instance.followers, 31 | 'followings': instance.followings, 32 | 'liveRoomId': instance.liveRoomId, 33 | 'liveStatus': instance.liveStatus, 34 | 'tracks': instance.tracks, 35 | 'uid': instance.uid, 36 | 'verifyType': instance.verifyType, 37 | 'isVerified': instance.isVerified, 38 | 'nickname': instance.nickname, 39 | 'personDescribe': instance.personDescribe, 40 | 'personalSignature': instance.personalSignature, 41 | 'smallLogo': instance.smallLogo 42 | }; 43 | -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | xmlyfm 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Views/detail_oneKeyListen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Modules/Home/Model/home_detail.dart'; 3 | import 'detail_title_more.dart'; 4 | import 'detail_refresh.dart'; 5 | import 'detail_bottom_line.dart'; 6 | import 'package:xmlyfm/Modules/Basic/ft_collection_view.dart'; 7 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 8 | 9 | class DetailOneKeyListen extends StatelessWidget { 10 | DetailOneKeyListen(this.model) : assert(model != null); 11 | 12 | final HomeDetail model; 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return Container( 17 | color: Colors.white, 18 | child: Column( 19 | crossAxisAlignment: CrossAxisAlignment.start, 20 | children: [ 21 | DetailTitleMore(model.title), 22 | // keywords 23 | // x宫格 24 | FTCollectionView( 25 | itemCount: model.list.length, 26 | columnNum: 3, 27 | builder: (context, index) { 28 | final item = model.list[index]; 29 | return Center(child: Column( 30 | crossAxisAlignment: CrossAxisAlignment.center, 31 | children: [ 32 | Image.network(item.coverRound ?? "", width: fs>80.0,), 33 | Container(height: fs>5.0,), 34 | Text(item.channelName ?? "", style: TextStyle(color: Color(0xFF9F9F9F), fontSize: fs>13.0, fontWeight: FontWeight.bold)), 35 | ], 36 | ),); 37 | }, 38 | ), 39 | DetailRefresh(), 40 | DetailBottomLine() 41 | ], 42 | ), 43 | ); 44 | } 45 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Model/home_recommend.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'home_recommend.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | HomeRecommend _$HomeRecommendFromJson(Map json) { 10 | return HomeRecommend( 11 | json['albumId'] as int, 12 | json['isFinished'] as int, 13 | json['lastUpdateAt'] as int, 14 | json['refundSupportType'] as int, 15 | json['isDraft'] as bool, 16 | json['isPaid'] as bool, 17 | json['albumLabel'] as String, 18 | json['cornerMark'] as String, 19 | json['coverMiddle'] as String, 20 | json['coverSmall'] as String, 21 | json['nickname'] as String, 22 | json['recReason'] as String, 23 | json['recSrc'] as String, 24 | json['recTrack'] as String, 25 | json['title'] as String); 26 | } 27 | 28 | Map _$HomeRecommendToJson(HomeRecommend instance) => 29 | { 30 | 'albumId': instance.albumId, 31 | 'isFinished': instance.isFinished, 32 | 'lastUpdateAt': instance.lastUpdateAt, 33 | 'refundSupportType': instance.refundSupportType, 34 | 'isDraft': instance.isDraft, 35 | 'isPaid': instance.isPaid, 36 | 'albumLabel': instance.albumLabel, 37 | 'cornerMark': instance.cornerMark, 38 | 'coverMiddle': instance.coverMiddle, 39 | 'coverSmall': instance.coverSmall, 40 | 'nickname': instance.nickname, 41 | 'recReason': instance.recReason, 42 | 'recSrc': instance.recSrc, 43 | 'recTrack': instance.recTrack, 44 | 'title': instance.title 45 | }; 46 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/DetailList/Model/album_track_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'album_track_item.g.dart'; 4 | 5 | @JsonSerializable() 6 | class AlbumTrackItem { 7 | int albumId; 8 | int categoryId; 9 | int comments; 10 | int createdAt; 11 | int duration; 12 | int likes; 13 | int opType; 14 | int orderNo; 15 | int playtimes; 16 | int processState; 17 | int relatedId; 18 | int sampleDuration; 19 | int shares; 20 | int status; 21 | int trackId; 22 | int trackRecordId; 23 | int type; 24 | int uid; 25 | int userSource; 26 | bool isDraft; 27 | bool isHoldCopyright; 28 | bool isPaid; 29 | bool isPublic; 30 | bool isRichAudio; 31 | bool isVideo; 32 | String commentId; 33 | String coverLarge; 34 | String coverMiddle; 35 | String coverSmall; 36 | String nickname; 37 | String playPathAacv164; 38 | String playPathAacv224; 39 | String playPathHq; 40 | String playUrl32; 41 | String playUrl64; 42 | String smallLogo; 43 | String title; 44 | 45 | AlbumTrackItem(this.albumId, this.categoryId, this.comments, this.createdAt, this.duration, this.likes, this.opType, this.orderNo, this.playtimes, this.processState, this.relatedId, this.sampleDuration, this.shares, this.status, this.trackId, this.trackRecordId, this.type, this.uid, this.userSource, this.isDraft, this.isHoldCopyright, this.isPaid, this.isPublic, this.isRichAudio, this.isVideo, this.commentId, this.coverLarge, this.coverMiddle, this.coverSmall, this.nickname, this.playPathAacv164, this.playPathAacv224, this.playPathHq, this.playUrl32, this.playUrl64, this.smallLogo, this.title); 46 | 47 | factory AlbumTrackItem.fromJson(Map json) => _$AlbumTrackItemFromJson(json); 48 | Map toJson() => _$AlbumTrackItemToJson(this); 49 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Model/home_detail.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'home_detail.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | HomeDetail _$HomeDetailFromJson(Map json) { 10 | return HomeDetail( 11 | json['bottomHasMore'] as bool, 12 | json['hasMore'] as bool, 13 | (json['list'] as List) 14 | ?.map((e) => e == null 15 | ? null 16 | : HomeDetailList.fromJson(e as Map)) 17 | ?.toList(), 18 | json['isNewUser'] as bool, 19 | json['loopCount'] as int, 20 | json['moduleId'] as int, 21 | json['moduleType'] as String, 22 | json['showInterestCard'] as bool, 23 | json['title'] as String, 24 | json['targetId'] as int, 25 | json['direction'] as String, 26 | (json['keywords'] as List) 27 | ?.map((e) => e == null 28 | ? null 29 | : HomeDetailKeyword.fromJson(e as Map)) 30 | ?.toList()); 31 | } 32 | 33 | Map _$HomeDetailToJson(HomeDetail instance) => 34 | { 35 | 'bottomHasMore': instance.bottomHasMore, 36 | 'hasMore': instance.hasMore, 37 | 'list': instance.list, 38 | 'isNewUser': instance.isNewUser, 39 | 'loopCount': instance.loopCount, 40 | 'moduleId': instance.moduleId, 41 | 'moduleType': instance.moduleType, 42 | 'showInterestCard': instance.showInterestCard, 43 | 'title': instance.title, 44 | 'targetId': instance.targetId, 45 | 'direction': instance.direction, 46 | 'keywords': instance.keywords 47 | }; 48 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Views/home_search.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 3 | 4 | class HomeSearch extends StatefulWidget { 5 | bool isTabBarOverAlpha; 6 | 7 | HomeSearch({Key key, @required this.isTabBarOverAlpha}) : super(key: key); 8 | @override 9 | _HomeSearchState createState() => _HomeSearchState(); 10 | } 11 | 12 | class _HomeSearchState extends State { 13 | @override 14 | Widget build(BuildContext context) { 15 | return Padding( 16 | padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0), 17 | child: Row( 18 | children: [ 19 | Expanded( 20 | child: Container( 21 | decoration: BoxDecoration( 22 | color: widget.isTabBarOverAlpha ? Colors.black.withAlpha(20) : Colors.white.withAlpha(100),//.withBlue(255), 23 | borderRadius: BorderRadius.all(Radius.circular(fs>20.0)) 24 | ), 25 | height: fs>35.0, 26 | child: Row( 27 | children: [ 28 | Padding( 29 | padding: EdgeInsets.only(left: 8.0, right: 4.0), 30 | child: Icon(Icons.search, color: widget.isTabBarOverAlpha ? Colors.grey : Colors.white), 31 | ), 32 | Expanded(child: Text('三字经', style: TextStyle(color: widget.isTabBarOverAlpha ? Colors.grey : Colors.white, fontSize: fs>15.0),),) 33 | ], 34 | ), 35 | ),), 36 | Padding(padding: EdgeInsets.only(left: 10.0), child: Icon(Icons.history, color: widget.isTabBarOverAlpha ? Colors.black : Colors.white, size: fs>30.0,),), 37 | Padding(padding: EdgeInsets.only(left: 8.0), child: Icon(Icons.add, color: widget.isTabBarOverAlpha ? Colors.black : Colors.white, size: fs>30.0,),) 38 | ], 39 | ), 40 | ); 41 | } 42 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Model/home_category_item.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'home_category_item.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | HomeCategoryItem _$HomeCategoryItemFromJson(Map json) { 10 | return HomeCategoryItem( 11 | json['id'] as String, 12 | json['title'] as String, 13 | json['itemType'] as String, 14 | json['categoryId'] as int, 15 | json['categoryType'] as String, 16 | json['moduleType'] as String, 17 | json['isDisplayCornerMark'] as bool, 18 | json['cornerMark'] as String, 19 | json['coverPath'] as String, 20 | json['unactiveCoverPath'] as String, 21 | json['activeCoverPath'] as String, 22 | json['recommendType'] as String, 23 | json['url'] as String, 24 | json['defaultSelected'] as bool, 25 | json['audioStreamId'] as String, 26 | json['hideInReview'] as bool); 27 | } 28 | 29 | Map _$HomeCategoryItemToJson(HomeCategoryItem instance) => 30 | { 31 | 'id': instance.id, 32 | 'title': instance.title, 33 | 'itemType': instance.itemType, 34 | 'categoryId': instance.categoryId, 35 | 'categoryType': instance.categoryType, 36 | 'moduleType': instance.moduleType, 37 | 'isDisplayCornerMark': instance.isDisplayCornerMark, 38 | 'cornerMark': instance.cornerMark, 39 | 'coverPath': instance.coverPath, 40 | 'unactiveCoverPath': instance.unactiveCoverPath, 41 | 'activeCoverPath': instance.activeCoverPath, 42 | 'recommendType': instance.recommendType, 43 | 'url': instance.url, 44 | 'defaultSelected': instance.defaultSelected, 45 | 'audioStreamId': instance.audioStreamId, 46 | 'hideInReview': instance.hideInReview 47 | }; 48 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Views/detail_focus.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_swiper/flutter_swiper.dart'; 3 | import 'package:xmlyfm/Modules/Home/Model/home_detail_list.dart'; 4 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 5 | 6 | class DetailFocus extends StatelessWidget { 7 | DetailFocus(this.models) : assert(models != null); 8 | 9 | final List models; 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return ConstrainedBox( 14 | constraints: 15 | BoxConstraints.loose(Size(MediaQuery.of(context).size.width, fs>>160.0)), 16 | child: Swiper( 17 | autoplay: true, 18 | itemCount: models.length, 19 | // pagination: SwiperPagination(), 20 | pagination: SwiperCustomPagination( 21 | builder: (BuildContext context, SwiperPluginConfig config) { 22 | return Align( 23 | alignment: Alignment.bottomCenter, 24 | child: Padding( 25 | padding: EdgeInsets.only(bottom: 15.0), 26 | child: Container( 27 | decoration: BoxDecoration( 28 | color: Colors.black.withAlpha(15), 29 | borderRadius: BorderRadius.circular(5.0)), 30 | child: DotSwiperPaginationBuilder( 31 | size: fs(5.0), 32 | activeSize: fs(7.0), 33 | color: Colors.grey, 34 | activeColor: Colors.white) 35 | .build(context, config), 36 | ), 37 | ), 38 | ); 39 | }), 40 | itemBuilder: (ctx, index) { 41 | return Padding( 42 | padding: EdgeInsets.all(10.0), 43 | child: ClipRRect( 44 | borderRadius: BorderRadius.circular(6.0), 45 | child: Image.network(models[index].cover, fit: BoxFit.fill), 46 | ), 47 | ); 48 | }, 49 | ), 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /xmlyfm/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 15 | 19 | 26 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Listen/listen_route.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Configs/configs.dart'; 3 | import 'package:xmlyfm/Modules/Listen/Header/listen_header.dart'; 4 | 5 | class ListenRoute extends StatefulWidget { 6 | @override 7 | _ListenRouteState createState() => _ListenRouteState(); 8 | } 9 | 10 | class _ListenRouteState extends State { 11 | double elevation = 0.0; // 0 | 0.6 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return Scaffold( 16 | appBar: AppBar( 17 | elevation: elevation, 18 | backgroundColor: Colors.white, 19 | centerTitle: true, 20 | title: Text('我听', style: TextStyle(color: Colors.black),), 21 | actions: [ 22 | Padding( 23 | padding: EdgeInsets.only(right: 15.0), 24 | child: 25 | InkWell( 26 | onTap: () { 27 | print('搜索'); 28 | }, 29 | child: Icon(Icons.save_alt, size: 30.0, color: Colors.black,), 30 | ), 31 | ), 32 | Padding( 33 | padding: EdgeInsets.only(right: 15.0), 34 | child: 35 | InkWell( 36 | onTap: () { 37 | print('搜索'); 38 | }, 39 | child: Icon(Icons.history, size: 30.0, color: Colors.black,), 40 | ), 41 | ), 42 | Padding( 43 | padding: EdgeInsets.only(right: 15.0), 44 | child: 45 | InkWell( 46 | onTap: () { 47 | print('搜索'); 48 | }, 49 | child: Icon(Icons.search, size: 30.0, color: Colors.black,), 50 | ), 51 | ), 52 | ], 53 | ), 54 | body: CustomScrollView( 55 | slivers: [ 56 | SliverToBoxAdapter( 57 | child: Padding( 58 | padding: EdgeInsets.all(15.0), 59 | child: Container(height: 80, child: ListenHeader(),), 60 | ), 61 | ), 62 | // SliverToBoxAdapter( 63 | // child: TabBarView(), 64 | // ) 65 | ], 66 | ), 67 | ); 68 | } 69 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Basic/ft_collection_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | typedef FTIndexedWidgetBuilder = Widget Function( 4 | BuildContext context, int index); 5 | 6 | class FTCollectionView extends StatelessWidget { 7 | FTCollectionView({ 8 | Key key, 9 | @required this.itemCount, 10 | @required this.builder, 11 | this.columnNum = 1, 12 | this.itemSpacing = 0, 13 | this.lineSpacing = 0, 14 | this.padding = EdgeInsets.zero 15 | }) : super(key: key); 16 | 17 | /// 子控件总数 18 | final int itemCount; 19 | /// 列数 20 | final int columnNum; 21 | /// 构建item闭包 22 | final FTIndexedWidgetBuilder builder; 23 | /// 单元格间的横向间距 24 | final double itemSpacing; 25 | /// 纵向的行间距 26 | final double lineSpacing; 27 | /// 视图内边距 28 | final EdgeInsets padding; 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | final screenWidth = MediaQuery.of(context).size.width; 33 | final viewWidth = screenWidth - padding.horizontal; 34 | final itemWidth = (viewWidth - (columnNum - 1) * itemSpacing) / columnNum; 35 | // print('padding.horizontal -- ${padding.horizontal}'); 36 | // print('screenWidth -- $screenWidth'); 37 | // print('viewWidth -- $viewWidth'); 38 | // print('itemWidth -- $itemWidth'); 39 | 40 | List widgets = []; 41 | int curIndex = 0; 42 | for (var i = 0; i < itemCount; i++) { 43 | curIndex = i % columnNum; 44 | widgets.add(Padding( 45 | padding: EdgeInsets.only(left: curIndex != 0 ? itemSpacing : 0), 46 | child: Container(width: itemWidth, child: builder(context, i)), 47 | )); 48 | } 49 | 50 | List rows = []; 51 | final row = (itemCount / columnNum).ceil(); 52 | // print("row : $row"); 53 | for (var i = 0; i < row; i++) { 54 | final curMaxCount = (i + 1) * columnNum; 55 | // print("curMaxCount : $curMaxCount"); 56 | rows.add(Row( 57 | crossAxisAlignment: CrossAxisAlignment.start, 58 | children: curMaxCount >= widgets.length 59 | ? widgets.sublist(i * columnNum) 60 | : widgets.sublist(i * columnNum, curMaxCount))); 61 | if ((i + 1) < row) { 62 | rows.add(Container(height: lineSpacing)); 63 | } 64 | } 65 | 66 | return Padding(padding: padding, child: Column(children: rows),); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Me/Cell/me_cell.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 3 | 4 | enum MeCellType { 5 | Switch, 6 | Url, 7 | } 8 | 9 | class MeCellConfig { 10 | MeCellConfig({ 11 | @required this.type, 12 | this.urlTitle, 13 | this.switchValue = false, 14 | }) : assert((type == MeCellType.Url && urlTitle.length != 0) || 15 | type == MeCellType.Switch); 16 | 17 | final String urlTitle; 18 | final MeCellType type; 19 | final bool switchValue; 20 | } 21 | 22 | class MeCell extends StatelessWidget { 23 | MeCell({ 24 | Key key, 25 | @required this.title, 26 | this.config, 27 | }); 28 | 29 | final String title; 30 | final MeCellConfig config; 31 | 32 | @override 33 | Widget build(BuildContext context) { 34 | return Column( 35 | children: [ 36 | Expanded( 37 | child: Row( 38 | children: [ 39 | Padding( 40 | padding: EdgeInsets.only(left: 10.0), 41 | child: Text( 42 | title, 43 | style: TextStyle(fontSize: fs>15.0, fontWeight: FontWeight.bold), 44 | ), 45 | ), 46 | Expanded( 47 | child: Container(), 48 | ), 49 | createWidget(), 50 | ], 51 | ), 52 | ), 53 | // 底部横线 54 | Container( 55 | color: Color(0xFFEAEAE6), 56 | height: 1.0, 57 | ) 58 | ], 59 | ); 60 | } 61 | 62 | Widget createWidget() { 63 | final Widget arrow = Padding( 64 | child: Icon(Icons.arrow_right), 65 | padding: EdgeInsets.only(right: 10.0), 66 | ); 67 | if (config == null) return arrow; 68 | switch (config.type) { 69 | case MeCellType.Switch: 70 | return Switch( 71 | value: config.switchValue, 72 | onChanged: (isTrue) {}, 73 | ); 74 | case MeCellType.Url: 75 | return Row( 76 | textDirection: TextDirection.rtl, 77 | children: [ 78 | arrow, 79 | Text(config.urlTitle, style: TextStyle(color: Color(0xFFFF5731), fontWeight: FontWeight.bold, fontSize: fs>13.0),) 80 | ] 81 | ); 82 | default: 83 | return arrow; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /xmlyfm/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def parse_KV_file(file, separator='=') 14 | file_abs_path = File.expand_path(file) 15 | if !File.exists? file_abs_path 16 | return []; 17 | end 18 | pods_ary = [] 19 | skip_line_start_symbols = ["#", "/"] 20 | File.foreach(file_abs_path) { |line| 21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } 22 | plugin = line.split(pattern=separator) 23 | if plugin.length == 2 24 | podname = plugin[0].strip() 25 | path = plugin[1].strip() 26 | podpath = File.expand_path("#{path}", file_abs_path) 27 | pods_ary.push({:name => podname, :path => podpath}); 28 | else 29 | puts "Invalid plugin specification: #{line}" 30 | end 31 | } 32 | return pods_ary 33 | end 34 | 35 | target 'Runner' do 36 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock 37 | # referring to absolute paths on developers' machines. 38 | system('rm -rf .symlinks') 39 | system('mkdir -p .symlinks/plugins') 40 | 41 | # Flutter Pods 42 | generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') 43 | if generated_xcode_build_settings.empty? 44 | puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first." 45 | end 46 | generated_xcode_build_settings.map { |p| 47 | if p[:name] == 'FLUTTER_FRAMEWORK_DIR' 48 | symlink = File.join('.symlinks', 'flutter') 49 | File.symlink(File.dirname(p[:path]), symlink) 50 | pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) 51 | end 52 | } 53 | 54 | # Plugin Pods 55 | plugin_pods = parse_KV_file('../.flutter-plugins') 56 | plugin_pods.map { |p| 57 | symlink = File.join('.symlinks', 'plugins', p[:name]) 58 | File.symlink(p[:path], symlink) 59 | pod p[:name], :path => File.join(symlink, 'ios') 60 | } 61 | end 62 | 63 | post_install do |installer| 64 | installer.pods_project.targets.each do |target| 65 | target.build_configurations.each do |config| 66 | config.build_settings['ENABLE_BITCODE'] = 'NO' 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /xmlyfm/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | def keystorePropertiesFile = rootProject.file("key.properties") 28 | def keystoreProperties = new Properties() 29 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 30 | 31 | android { 32 | compileSdkVersion 27 33 | 34 | lintOptions { 35 | disable 'InvalidPackage' 36 | } 37 | 38 | defaultConfig { 39 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 40 | applicationId "com.linxunfeng.xmlyfm" 41 | minSdkVersion 16 42 | targetSdkVersion 27 43 | versionCode flutterVersionCode.toInteger() 44 | versionName flutterVersionName 45 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 46 | } 47 | 48 | signingConfigs { 49 | release { 50 | keyAlias keystoreProperties['keyAlias'] 51 | keyPassword keystoreProperties['keyPassword'] 52 | storeFile file(keystoreProperties['storeFile']) 53 | storePassword keystoreProperties['storePassword'] 54 | } 55 | } 56 | 57 | buildTypes { 58 | release { 59 | // TODO: Add your own signing config for the release build. 60 | // Signing with the debug keys for now, so `flutter run --release` works. 61 | signingConfig signingConfigs.debug 62 | // signingConfig signingConfigs.release 63 | } 64 | } 65 | } 66 | 67 | flutter { 68 | source '../..' 69 | } 70 | 71 | dependencies { 72 | testImplementation 'junit:junit:4.12' 73 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 74 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 75 | } 76 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Model/home_detail.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | import 'home_detail_list.dart'; 3 | import 'home_detail_keyword.dart'; 4 | 5 | part 'home_detail.g.dart'; 6 | 7 | enum HomeDetailType { 8 | Focus, 9 | Square, 10 | TopBuzz, 11 | GuessYouLike, 12 | PaidCategory, 13 | CategoriesForShort, 14 | Playlist, 15 | OneKeyListen, 16 | CategoriesForLong, 17 | MicroLesson, 18 | Live, 19 | CategoriesForExplore, 20 | Ad, 21 | RecommendAlbum 22 | } 23 | 24 | enum DetailCategoriesDirection { 25 | Column, 26 | Row 27 | } 28 | 29 | @JsonSerializable() 30 | class HomeDetail { 31 | HomeDetail( 32 | this.bottomHasMore, 33 | this.hasMore, 34 | this.list, 35 | this.isNewUser, 36 | this.loopCount, 37 | this.moduleId, 38 | this.moduleType, 39 | this.showInterestCard, 40 | this.title, 41 | this.targetId, 42 | this.direction, 43 | this.keywords, 44 | ); 45 | 46 | bool bottomHasMore; // true 47 | bool hasMore; // true 48 | List list; 49 | bool isNewUser; 50 | int loopCount; 51 | int moduleId; // 1 52 | String moduleType; // forcus 53 | bool showInterestCard; 54 | String title; 55 | int targetId; 56 | String direction; 57 | List keywords; 58 | 59 | factory HomeDetail.fromJson(Map json) => _$HomeDetailFromJson(json); 60 | Map toJson() => _$HomeDetailToJson(this); 61 | 62 | HomeDetailType fetchDetailType() { 63 | switch (moduleType) { 64 | case "focus": return HomeDetailType.Focus; 65 | case "square": return HomeDetailType.Square; 66 | case "topBuzz": return HomeDetailType.TopBuzz; 67 | case "guessYouLike": return HomeDetailType.GuessYouLike; 68 | case "paidCategory": return HomeDetailType.PaidCategory; 69 | case "categoriesForShort": return HomeDetailType.CategoriesForShort; 70 | case "playlist": return HomeDetailType.Playlist; 71 | case "oneKeyListen": return HomeDetailType.OneKeyListen; 72 | case "categoriesForLong": return HomeDetailType.CategoriesForLong; 73 | case "microLesson": return HomeDetailType.MicroLesson; 74 | case "live": return HomeDetailType.Live; 75 | case "categoriesForExplore": return HomeDetailType.CategoriesForExplore; 76 | case "ad": return HomeDetailType.Ad; 77 | case "recommendAlbum": return HomeDetailType.RecommendAlbum; 78 | default: return HomeDetailType.RecommendAlbum; 79 | } 80 | } 81 | DetailCategoriesDirection fetchCategoriesDirection() { 82 | switch (direction) { 83 | case "column" : return DetailCategoriesDirection.Column; 84 | case "row" : return DetailCategoriesDirection.Row; 85 | default: return DetailCategoriesDirection.Column; 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Views/detail_topBuzz.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Modules/Home/Model/home_detail.dart'; 3 | import 'package:flutter_swiper/flutter_swiper.dart'; 4 | import 'detail_bottom_line.dart'; 5 | import 'package:xmlyfm/Configs/configs.dart'; 6 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 7 | 8 | class DetailTopBuzz extends StatelessWidget { 9 | DetailTopBuzz(this.model) : assert(model != null); 10 | 11 | final HomeDetail model; 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return DecoratedBox( 16 | decoration: BoxDecoration(color: Colors.white), 17 | child: Column( 18 | children: [ 19 | Padding( 20 | padding: EdgeInsets.symmetric(horizontal: 10.0), 21 | child: Container( 22 | height: fs>40.0, 23 | child: Row( 24 | children: [ 25 | Text( 26 | model.title, 27 | style: TextStyle( 28 | color: themeColor, 29 | fontSize: fs>15.0, 30 | fontWeight: FontWeight.bold), 31 | ), 32 | Expanded( 33 | child: Swiper( 34 | autoplayDelay: 3000, 35 | autoplay: true, 36 | scrollDirection: Axis.vertical, 37 | itemCount: model.list.length, 38 | itemBuilder: (ctx, index) { 39 | return Padding( 40 | padding: EdgeInsets.symmetric(horizontal: 10.0), 41 | child: Container( 42 | height: fs>40, 43 | child: Column( 44 | mainAxisAlignment: MainAxisAlignment.center, 45 | crossAxisAlignment: CrossAxisAlignment.start, 46 | children: [ 47 | Text( 48 | model.list[index].title, 49 | overflow: TextOverflow.ellipsis, 50 | maxLines: 1, 51 | style: TextStyle(fontSize: fs>15.0), 52 | ) 53 | ], 54 | ), 55 | ), 56 | ); 57 | }, 58 | ), 59 | ), 60 | Padding( 61 | padding: 62 | EdgeInsets.symmetric(horizontal: 10.0, vertical: 11.0), 63 | child: Container( 64 | width: 1, 65 | color: Colors.grey.withAlpha(100), 66 | ), 67 | ), 68 | InkWell( 69 | child: Text('更多', style: TextStyle(fontSize: fs>14.0),), 70 | ), 71 | ], 72 | ), 73 | ), 74 | ), 75 | DetailBottomLine() 76 | ], 77 | ), 78 | ); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /xmlyfm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Views/detail_playlist.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Modules/Home/Model/home_detail.dart'; 3 | import 'detail_title_more.dart'; 4 | import 'detail_bottom_line.dart'; 5 | import 'package:xmlyfm/Modules/Basic/ft_collection_view.dart'; 6 | import 'package:xmlyfm/Configs/configs.dart'; 7 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 8 | 9 | class DetailPlaylist extends StatelessWidget { 10 | DetailPlaylist(this.model) : assert(model != null); 11 | 12 | final HomeDetail model; 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | final imgHeight = fs>80.0; 17 | 18 | return Container( 19 | color: Colors.white, 20 | child: Column( 21 | crossAxisAlignment: CrossAxisAlignment.start, 22 | children: [ 23 | DetailTitleMore(model.title), 24 | // keywords 25 | // x宫格 26 | FTCollectionView( 27 | itemCount: model.list.length, 28 | itemSpacing: 10.0, 29 | lineSpacing: 10.0, 30 | padding: EdgeInsets.symmetric(horizontal: fs>10.0), 31 | builder: (context, index) { 32 | final item = model.list[index]; 33 | return Row( 34 | mainAxisAlignment: MainAxisAlignment.start, 35 | crossAxisAlignment: CrossAxisAlignment.start, 36 | children: [ 37 | ClipRRect( 38 | borderRadius: BorderRadius.circular(3.0), 39 | child: Image.network(model.list[index].coverPath ?? "", width: imgHeight,) 40 | ), 41 | Expanded(child: Padding( 42 | padding: EdgeInsets.symmetric(horizontal: fs>10.0), 43 | child: Column( 44 | crossAxisAlignment: CrossAxisAlignment.start, 45 | children: [ 46 | Padding(padding: EdgeInsets.only(bottom: 5.0), child: Text(item.title, maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle(color: Colors.black, fontSize: fs>18.0, fontWeight: FontWeight.bold,)),), 47 | Padding(padding: EdgeInsets.only(bottom: 5.0), child: Text(item.subtitle, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(color: Color(0xFF9F9F9F), fontSize: fs>15.0),),), 48 | Padding(padding: EdgeInsets.only(bottom: 5.0), child: Row(children: [ 49 | Icon(Icons.adjust, color: Color(0xFF9C9C9C), size: fs>20.0), 50 | Text(item.footnote ?? "", style: TextStyle(color: Color(0xFF9F9F9F), fontSize: fs>13.0, fontWeight: FontWeight.bold)), 51 | ],)), 52 | Padding( 53 | padding: EdgeInsets.only(top: fs>5.0, left: .0), 54 | child: Container(height: 1, color: bgColor,), 55 | ) 56 | ], 57 | ), 58 | ),) 59 | ],); 60 | }, 61 | ), 62 | DetailBottomLine() 63 | ], 64 | ), 65 | ); 66 | } 67 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Views/detail_guessYouLike.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Modules/Home/Model/home_detail.dart'; 3 | import 'detail_title_more.dart'; 4 | import 'detail_refresh.dart'; 5 | import 'detail_bottom_line.dart'; 6 | import 'package:xmlyfm/Modules/Basic/ft_collection_view.dart'; 7 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 8 | 9 | class DetailGuessYouLike extends StatelessWidget { 10 | DetailGuessYouLike(this.model) : assert(model != null); 11 | 12 | final HomeDetail model; 13 | final itemSpacing = 10.0; 14 | final columnNum = 3; 15 | final padding = EdgeInsets.symmetric(horizontal: 10.0); 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | final itemImageWH = (MediaQuery.of(context).size.width - padding.horizontal - (columnNum-1) * itemSpacing) / columnNum; 20 | return Container( 21 | color: Colors.white, 22 | child: Column( 23 | children: [ 24 | DetailTitleMore('猜你喜欢'), 25 | // x宫格 26 | FTCollectionView( 27 | itemCount: model.list.length, 28 | columnNum: columnNum, 29 | itemSpacing: itemSpacing, 30 | lineSpacing: 10.0, 31 | padding: EdgeInsets.symmetric(horizontal: 10.0), 32 | builder: (context, index) { 33 | return Column( 34 | crossAxisAlignment: CrossAxisAlignment.start, 35 | children: [ 36 | ClipRRect( 37 | borderRadius: BorderRadius.circular(4.0), 38 | child: Stack( 39 | children: [ 40 | Image.network(model.list[index].pic, fit: BoxFit.fill, width: itemImageWH, height: itemImageWH,), 41 | Positioned(bottom: 0, right: 0, left: 0, 42 | child: DecoratedBox( 43 | decoration: BoxDecoration( 44 | gradient: LinearGradient( 45 | colors: [Colors.black54, Colors.transparent], 46 | begin: Alignment.bottomCenter, 47 | end: Alignment.topCenter)), 48 | child: Row( 49 | children: [ 50 | Icon(Icons.play_arrow, color: Colors.white, size: fs>17,), 51 | Text( 52 | "${model.list[index].playsCount ?? 0}", 53 | style: TextStyle(color: Colors.white, fontSize: fs>13.0,) 54 | ) 55 | ], 56 | ), 57 | ), 58 | ) 59 | ], 60 | ), 61 | ), 62 | Text(model.list[index].title, maxLines: 2, style: TextStyle(fontSize: fs>15.0),) 63 | ], 64 | ); 65 | }, 66 | ), 67 | DetailRefresh(), 68 | DetailBottomLine() 69 | ], 70 | ), 71 | ); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/DetailList/Model/album.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'album.g.dart'; 4 | 5 | @JsonSerializable() 6 | class Album { 7 | Album(this.ageLevel, this.albumId, this.authorizedExpireTime, this.authorizedTypeId, this.categoryId, this.contractStatus, this.createdAt, this.freeToPaidStatus, this.freeToPaidTime, this.lastUptrackAt, this.lastUptrackId, this.offlineReason, this.offlineType, this.originalStatus, this.playTimes, this.playTrackId, this.refundSupportType, this.saleScope, this.serialState, this.serializeStatus, this.shareSupportType, this.shares, this.status, this.subscribeCount, this.tracks, this.type, this.uid, this.unReadAlbumCommentCount, this.updatedAt, this.vipFreeType, this.autoStart, this.canInviteListen, this.canShareAndStealListen, this.hasNew, this.hasRecs, this.isAuthorized, this.isDefault, this.isDraft, this.isFavorite, this.isNoCopyright, this.isPaid, this.isPublic, this.isRecordDesc, this.isVerified, this.isVipFree, this.is_default, this.avatarPath, this.categoryName, this.coverLarge, this.coverLargePop, this.coverMiddle, this.coverOrigin, this.coverSmall, this.coverWebLarge, this.customSubTitle, this.customTitle, this.detailCoverPath, this.intro, this.introRich, this.lastUptrackCoverPath, this.lastUptrackTitle, this.nickname, this.other_title, this.recommendReason, this.salePoint, this.salePointPopup, this.shortIntro, this.shortIntroRich, this.tags, this.title); 8 | 9 | int ageLevel; 10 | int albumId; 11 | int authorizedExpireTime; 12 | int authorizedTypeId; 13 | int categoryId; 14 | int contractStatus; 15 | int createdAt; 16 | int freeToPaidStatus; 17 | int freeToPaidTime; 18 | int lastUptrackAt; 19 | int lastUptrackId; 20 | int offlineReason; 21 | int offlineType; 22 | int originalStatus; 23 | int playTimes; 24 | int playTrackId; 25 | int refundSupportType; 26 | int saleScope; 27 | int serialState; 28 | int serializeStatus; 29 | int shareSupportType; 30 | int shares; 31 | int status; 32 | int subscribeCount; 33 | int tracks; 34 | int type; 35 | int uid; 36 | int unReadAlbumCommentCount; 37 | int updatedAt; 38 | int vipFreeType; 39 | bool autoStart; 40 | bool canInviteListen; 41 | bool canShareAndStealListen; 42 | bool hasNew; 43 | bool hasRecs; 44 | bool isAuthorized; 45 | bool isDefault; 46 | bool isDraft; 47 | bool isFavorite; 48 | bool isNoCopyright; 49 | bool isPaid; 50 | bool isPublic; 51 | bool isRecordDesc; 52 | bool isVerified; 53 | bool isVipFree; 54 | bool is_default; 55 | String avatarPath; 56 | String categoryName; 57 | String coverLarge; 58 | String coverLargePop; 59 | String coverMiddle; 60 | String coverOrigin; 61 | String coverSmall; 62 | String coverWebLarge; 63 | String customSubTitle; 64 | String customTitle; 65 | String detailCoverPath; 66 | String intro; 67 | String introRich; 68 | String lastUptrackCoverPath; 69 | String lastUptrackTitle; 70 | String nickname; 71 | String other_title; 72 | String recommendReason; 73 | String salePoint; 74 | String salePointPopup; 75 | String shortIntro; 76 | String shortIntroRich; 77 | String tags; 78 | String title; 79 | 80 | factory Album.fromJson(Map json) => _$AlbumFromJson(json); 81 | Map toJson() => _$AlbumToJson(this); 82 | } -------------------------------------------------------------------------------- /xmlyfm/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: xmlyfm 2 | description: A Flutter XMLYFM App 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # Read more about versioning at semver.org. 10 | version: 1.0.0+1 11 | 12 | environment: 13 | sdk: ">=2.0.0-dev.68.0 <3.0.0" 14 | 15 | dependencies: 16 | flutter: 17 | sdk: flutter 18 | 19 | # The following adds the Cupertino Icons font to your application. 20 | # Use with the CupertinoIcons class for iOS style icons. 21 | cupertino_icons: ^0.1.2 22 | fluro: ^1.3.7 23 | dio: ^1.0.12 24 | flutter_webview_plugin: ^0.3.0+2 25 | flutter_swiper: ^1.1.4 26 | flutter_fitsize: ^0.0.1 27 | 28 | dev_dependencies: 29 | flutter_test: 30 | sdk: flutter 31 | build_runner: ^1.0.0 32 | json_serializable: ^2.0.1 33 | 34 | 35 | # For information on the generic Dart part of this file, see the 36 | # following page: https://www.dartlang.org/tools/pub/pubspec 37 | 38 | # The following section is specific to Flutter. 39 | flutter: 40 | 41 | # The following line ensures that the Material Icons font is 42 | # included with your application, so that you can use the icons in 43 | # the material Icons class. 44 | uses-material-design: true 45 | 46 | # To add assets to your application, add an assets section, like this: 47 | # assets: 48 | # - images/a_dot_burr.jpeg 49 | # - images/a_dot_ham.jpeg 50 | assets: 51 | - images/tabbar/host_home_page_tab_01.png 52 | - images/tabbar/host_home_page_tab_15.png 53 | - images/tabbar/host_my_listen_tab_01.png 54 | - images/tabbar/host_my_listen_tab_15.png 55 | - images/tabbar/host_find_tab_01.png 56 | - images/tabbar/host_find_tab_15.png 57 | - images/tabbar/host_mine_tab_01.png 58 | - images/tabbar/host_mine_tab_15.png 59 | - images/tabbar/host_theme_global_play_default.png 60 | - images/me/host_theme_ic_title_bar_message.png 61 | - images/me/host_theme_ic_title_bar_message_pressed.png 62 | - images/me/host_theme_ic_title_bar_setting.png 63 | - images/me/host_default_avatar_88.png 64 | 65 | # An image asset can refer to one or more resolution-specific "variants", see 66 | # https://flutter.io/assets-and-images/#resolution-aware. 67 | 68 | # For details regarding adding assets from package dependencies, see 69 | # https://flutter.io/assets-and-images/#from-packages 70 | 71 | # To add custom fonts to your application, add a fonts section here, 72 | # in this "flutter" section. Each entry in this list should have a 73 | # "family" key with the font family name, and a "fonts" key with a 74 | # list giving the asset and other descriptors for the font. For 75 | # example: 76 | # fonts: 77 | # - family: Schyler 78 | # fonts: 79 | # - asset: fonts/Schyler-Regular.ttf 80 | # - asset: fonts/Schyler-Italic.ttf 81 | # style: italic 82 | # - family: Trajan Pro 83 | # fonts: 84 | # - asset: fonts/TrajanPro.ttf 85 | # - asset: fonts/TrajanPro_Bold.ttf 86 | # weight: 700 87 | # 88 | # For details regarding fonts from package dependencies, 89 | # see https://flutter.io/custom-fonts/#from-packages 90 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/DetailList/Model/album_track_item.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'album_track_item.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | AlbumTrackItem _$AlbumTrackItemFromJson(Map json) { 10 | return AlbumTrackItem( 11 | json['albumId'] as int, 12 | json['categoryId'] as int, 13 | json['comments'] as int, 14 | json['createdAt'] as int, 15 | json['duration'] as int, 16 | json['likes'] as int, 17 | json['opType'] as int, 18 | json['orderNo'] as int, 19 | json['playtimes'] as int, 20 | json['processState'] as int, 21 | json['relatedId'] as int, 22 | json['sampleDuration'] as int, 23 | json['shares'] as int, 24 | json['status'] as int, 25 | json['trackId'] as int, 26 | json['trackRecordId'] as int, 27 | json['type'] as int, 28 | json['uid'] as int, 29 | json['userSource'] as int, 30 | json['isDraft'] as bool, 31 | json['isHoldCopyright'] as bool, 32 | json['isPaid'] as bool, 33 | json['isPublic'] as bool, 34 | json['isRichAudio'] as bool, 35 | json['isVideo'] as bool, 36 | json['commentId'] as String, 37 | json['coverLarge'] as String, 38 | json['coverMiddle'] as String, 39 | json['coverSmall'] as String, 40 | json['nickname'] as String, 41 | json['playPathAacv164'] as String, 42 | json['playPathAacv224'] as String, 43 | json['playPathHq'] as String, 44 | json['playUrl32'] as String, 45 | json['playUrl64'] as String, 46 | json['smallLogo'] as String, 47 | json['title'] as String); 48 | } 49 | 50 | Map _$AlbumTrackItemToJson(AlbumTrackItem instance) => 51 | { 52 | 'albumId': instance.albumId, 53 | 'categoryId': instance.categoryId, 54 | 'comments': instance.comments, 55 | 'createdAt': instance.createdAt, 56 | 'duration': instance.duration, 57 | 'likes': instance.likes, 58 | 'opType': instance.opType, 59 | 'orderNo': instance.orderNo, 60 | 'playtimes': instance.playtimes, 61 | 'processState': instance.processState, 62 | 'relatedId': instance.relatedId, 63 | 'sampleDuration': instance.sampleDuration, 64 | 'shares': instance.shares, 65 | 'status': instance.status, 66 | 'trackId': instance.trackId, 67 | 'trackRecordId': instance.trackRecordId, 68 | 'type': instance.type, 69 | 'uid': instance.uid, 70 | 'userSource': instance.userSource, 71 | 'isDraft': instance.isDraft, 72 | 'isHoldCopyright': instance.isHoldCopyright, 73 | 'isPaid': instance.isPaid, 74 | 'isPublic': instance.isPublic, 75 | 'isRichAudio': instance.isRichAudio, 76 | 'isVideo': instance.isVideo, 77 | 'commentId': instance.commentId, 78 | 'coverLarge': instance.coverLarge, 79 | 'coverMiddle': instance.coverMiddle, 80 | 'coverSmall': instance.coverSmall, 81 | 'nickname': instance.nickname, 82 | 'playPathAacv164': instance.playPathAacv164, 83 | 'playPathAacv224': instance.playPathAacv224, 84 | 'playPathHq': instance.playPathHq, 85 | 'playUrl32': instance.playUrl32, 86 | 'playUrl64': instance.playUrl64, 87 | 'smallLogo': instance.smallLogo, 88 | 'title': instance.title 89 | }; 90 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Views/detail_microLesson.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Modules/Home/Model/home_detail.dart'; 3 | import 'detail_title_more.dart'; 4 | import 'detail_refresh.dart'; 5 | import 'detail_bottom_line.dart'; 6 | import 'package:xmlyfm/Modules/Basic/ft_collection_view.dart'; 7 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 8 | 9 | class DetailMicroLesson extends StatelessWidget { 10 | DetailMicroLesson(this.model) : assert(model != null); 11 | 12 | final HomeDetail model; 13 | final itemSpacing = 10.0; 14 | final columnNum = 3; 15 | final padding = EdgeInsets.symmetric(horizontal: 10.0); 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | final itemImageWH = (MediaQuery.of(context).size.width - padding.horizontal - (columnNum-1) * itemSpacing) / columnNum; 20 | 21 | return Container( 22 | color: Colors.white, 23 | child: Column( 24 | children: [ 25 | DetailTitleMore(model.title), 26 | // x宫格 27 | FTCollectionView( 28 | itemCount: model.list.length, 29 | columnNum: columnNum, 30 | itemSpacing: itemSpacing, 31 | lineSpacing: 10.0, 32 | padding: padding, 33 | builder: (context, index) { 34 | return Column( 35 | crossAxisAlignment: CrossAxisAlignment.start, 36 | children: [ 37 | ClipRRect( 38 | borderRadius: BorderRadius.circular(4.0), 39 | child: Stack( 40 | children: [ 41 | Image.network(model.list[index].cover ?? "", fit: BoxFit.fill, width: itemImageWH, height: itemImageWH,), 42 | Positioned(bottom: 0, right: 0, left: 0, 43 | child: DecoratedBox( 44 | decoration: BoxDecoration( 45 | gradient: LinearGradient( 46 | colors: [Colors.black54, Colors.transparent], 47 | begin: Alignment.bottomCenter, 48 | end: Alignment.topCenter)), 49 | child: Row( 50 | children: [ 51 | Icon(Icons.headset, color: Colors.white, size: fs>17,), 52 | Text( 53 | "${model.list[index].participationCount}", 54 | style: TextStyle(color: Colors.white, fontSize: fs>13.0,) 55 | ) 56 | ], 57 | ), 58 | ), 59 | ) 60 | ], 61 | ), 62 | ), 63 | Container(height: fs>8.0,), 64 | Text(model.list[index].title ?? "", maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle(color: Colors.black, fontSize: fs>17.0, fontWeight: FontWeight.bold,)), 65 | Text(model.list[index].nickName ?? "", maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(color: Color(0xFF9F9F9F), fontSize: fs>13.0)) 66 | ], 67 | ); 68 | }, 69 | ), 70 | DetailRefresh(), 71 | DetailBottomLine() 72 | ], 73 | ), 74 | ); 75 | } 76 | } -------------------------------------------------------------------------------- /xmlyfm/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /xmlyfm/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Modules/Home/home_route.dart'; 3 | import 'package:xmlyfm/Modules/Listen/listen_route.dart'; 4 | import 'package:xmlyfm/Modules/Find/find_route.dart'; 5 | import 'package:xmlyfm/Modules/Me/me_route.dart'; 6 | import 'Modules/Basic/tab_bar.dart'; 7 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 8 | import 'Configs/Router/xmly_router.dart'; 9 | 10 | void main() => runApp(MainApp()); 11 | 12 | class MainApp extends StatefulWidget { 13 | @override 14 | _MainAppState createState() => _MainAppState(); 15 | } 16 | 17 | class _MainAppState extends State with SingleTickerProviderStateMixin { 18 | int _tabIndex = 0; 19 | List _tabImages; 20 | List _tabHighlightImages; 21 | var _tabTitels = ['首页', '我听', "", '发现', '我的']; 22 | var _bodys = [ 23 | HomeRoute(), 24 | ListenRoute(), 25 | ListenRoute(), 26 | FindRoute(), 27 | MeRoute() 28 | ]; 29 | 30 | @override 31 | void initState() { 32 | super.initState(); 33 | 34 | XMLYRouterHandler.init(); 35 | fs.setup(padFitMultiple: 0.5); 36 | 37 | _tabImages = [ 38 | fetchTabImage('host_home_page_tab_01.png'), 39 | fetchTabImage('host_my_listen_tab_01.png'), 40 | fetchTabImage('host_theme_global_play_default.png', onlyIcon: true), 41 | fetchTabImage('host_find_tab_01.png'), 42 | fetchTabImage('host_mine_tab_01.png') 43 | ]; 44 | _tabHighlightImages = [ 45 | fetchTabImage('host_home_page_tab_15.png'), 46 | fetchTabImage('host_my_listen_tab_15.png'), 47 | fetchTabImage('host_theme_global_play_default.png', onlyIcon: true), 48 | fetchTabImage('host_find_tab_15.png'), 49 | fetchTabImage('host_mine_tab_15.png'), 50 | ]; 51 | } 52 | 53 | @override 54 | Widget build(BuildContext context) { 55 | return MaterialApp( 56 | title: '喜马拉雅FM APP', 57 | theme: ThemeData( 58 | // primarySwatch: Colors.red, 59 | primaryColor: Colors.white, 60 | // brightness: Brightness.light 61 | ), 62 | home: Scaffold( 63 | body: IndexedStack( 64 | children: _bodys, 65 | index: _tabIndex, 66 | ), 67 | bottomNavigationBar: LXFTabBar( 68 | currentIndex: _tabIndex, 69 | items: _tabImages 70 | .asMap() 71 | .map((index, _) => MapEntry( 72 | index, 73 | BottomNavigationBarItem( 74 | icon: fetchTabIcon(index), 75 | title: fetchTabTitle(index), 76 | activeIcon: fetchTabIcon(index, isHighlight: true)))) 77 | .values 78 | .toList(), 79 | onTap: (index) { 80 | if (index == 2) return; 81 | setState(() { 82 | _tabIndex = index; 83 | }); 84 | }, 85 | )), 86 | ); 87 | } 88 | 89 | Image fetchTabImage(String path, {bool onlyIcon = false}) { 90 | // BottomNavigationBar 91 | double iconWH = onlyIcon ? 45.0 : 35.0; 92 | return Image.asset("images/tabbar/" + path, width: iconWH, height: iconWH); 93 | } 94 | 95 | Image fetchTabIcon(int index, {bool isHighlight = false}) { 96 | return isHighlight ? _tabHighlightImages[index] : _tabImages[index]; 97 | } 98 | 99 | Text fetchTabTitle(int index) { 100 | if (_tabTitels[index] == "") return null; 101 | return Text( 102 | _tabTitels[index], 103 | style: TextStyle( 104 | color: Color(index == _tabIndex ? 0xFFFF5731 : 0xFFCCCCCC), 105 | fontSize: 11.0), 106 | ); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Basic/tab_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | const double _kBottomMargin = 8.0; 4 | 5 | class LXFTabBar extends StatefulWidget { 6 | LXFTabBar({ 7 | Key key, 8 | @required this.currentIndex, 9 | @required this.items, 10 | this.separatorColor = Colors.transparent, 11 | this.separatorHeight = 1.0, 12 | this.backgroundColor = Colors.white, 13 | this.itemSpacing = .0, 14 | this.onTap, 15 | }): 16 | assert(0 <= currentIndex && currentIndex < items.length), 17 | super(key: key); 18 | 19 | /// 当前选中的下标 20 | final int currentIndex; 21 | 22 | /// item数组 23 | final List items; 24 | 25 | /// 分割线颜色 26 | final Color separatorColor; 27 | 28 | /// 分割线高度 29 | final double separatorHeight; 30 | 31 | /// 背景颜色 32 | final Color backgroundColor; 33 | 34 | /// item 中 Icon 与 Text 的间距 35 | final double itemSpacing; 36 | 37 | /// item 点击回调 38 | final ValueChanged onTap; 39 | 40 | @override 41 | _LXFTabBarState createState() => _LXFTabBarState(); 42 | } 43 | 44 | class _LXFTabBarState extends State { 45 | int _curIndex; 46 | 47 | @override 48 | void initState() { 49 | super.initState(); 50 | } 51 | 52 | @override 53 | Widget build(BuildContext context) { 54 | final double additionalBottomPadding = 55 | MediaQuery.of(context).padding.bottom; 56 | 57 | _curIndex = widget.currentIndex; 58 | 59 | return Container( 60 | height: kBottomNavigationBarHeight + additionalBottomPadding, 61 | // height: kBottomNavigationBarHeight + additionalBottomPadding, 62 | decoration: BoxDecoration( 63 | color: widget.backgroundColor, 64 | boxShadow: [BoxShadow(color: Color(0xFFCCCCCC), offset: Offset(0, 0), blurRadius: 1.0)] 65 | ), 66 | child: Container( 67 | height: kBottomNavigationBarHeight, 68 | child: Column( 69 | children: [ 70 | // separator 71 | Container( 72 | decoration: BoxDecoration(color: widget.separatorColor), 73 | height: widget.separatorHeight, 74 | ), 75 | Container( 76 | // items View 77 | height: kBottomNavigationBarHeight - widget.separatorHeight, 78 | constraints: 79 | BoxConstraints(maxHeight: kBottomNavigationBarHeight), 80 | child: Row( 81 | children: widget.items 82 | .asMap() 83 | .map((index, item) { 84 | Widget child; 85 | if (item.title == null) { // 仅图标 86 | child = item.icon; 87 | } else { // 图标 + 文字 88 | child = Column( 89 | mainAxisAlignment: MainAxisAlignment.center, 90 | children: [ 91 | (_curIndex == index && item.activeIcon != null) 92 | ? item.activeIcon 93 | : item.icon, 94 | Container( 95 | height: widget.itemSpacing, 96 | ), 97 | item.title 98 | ], 99 | ); 100 | } 101 | 102 | return MapEntry( 103 | index, 104 | Expanded( 105 | child: InkResponse( 106 | onTap: () => widget.onTap(index), 107 | child: child, 108 | ), 109 | )); 110 | }) 111 | .values 112 | .toList(), 113 | ), 114 | ) 115 | ], 116 | ), 117 | ), 118 | ); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Views/detail_paidCategory.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Modules/Home/Model/home_detail.dart'; 3 | import 'detail_title_more.dart'; 4 | import 'detail_refresh.dart'; 5 | import 'detail_bottom_line.dart'; 6 | import 'package:xmlyfm/Modules/Basic/ft_collection_view.dart'; 7 | import 'package:xmlyfm/Configs/configs.dart'; 8 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 9 | 10 | class DetailPaidCategory extends StatelessWidget { 11 | DetailPaidCategory(this.model) : assert(model != null); 12 | 13 | final HomeDetail model; 14 | final itemSpacing = 10.0; 15 | final columnNum = 3; 16 | final padding = EdgeInsets.symmetric(horizontal: 10.0); 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | final itemImageWH = (MediaQuery.of(context).size.width - padding.horizontal - (columnNum-1) * itemSpacing) / columnNum; 21 | 22 | return Container( 23 | color: Colors.white, 24 | child: Column( 25 | crossAxisAlignment: CrossAxisAlignment.start, 26 | children: [ 27 | DetailTitleMore(model.title), 28 | // x宫格 29 | FTCollectionView( 30 | itemCount: model.list.length, 31 | columnNum: columnNum, 32 | itemSpacing: itemSpacing, 33 | lineSpacing: 10.0, 34 | padding: padding, 35 | builder: (context, index) { 36 | return Column( 37 | crossAxisAlignment: CrossAxisAlignment.start, 38 | children: [ 39 | ClipRRect( 40 | borderRadius: BorderRadius.circular(4.0), 41 | child: Stack( 42 | children: [ 43 | Image.network(model.list[index].pic, fit: BoxFit.fill, width: itemImageWH, height: itemImageWH,), 44 | Positioned(left: 0, top: 0, 45 | child: ClipRRect( 46 | borderRadius: BorderRadius.only(bottomRight: Radius.circular(4.0)), 47 | child: Container(width: 30.0, height: 16, color: themeColor, 48 | child: Center(child: Text('精品', style: TextStyle(color: Colors.white, fontSize: fs>10.0),),), 49 | ), 50 | ), 51 | ), 52 | Positioned(bottom: 0, right: 0, left: 0, 53 | child: DecoratedBox( 54 | decoration: BoxDecoration( 55 | gradient: LinearGradient( 56 | colors: [Colors.black54, Colors.transparent], 57 | begin: Alignment.bottomCenter, 58 | end: Alignment.topCenter)), 59 | child: Padding( 60 | padding: EdgeInsets.only(bottom: 3.0), 61 | child: Row( 62 | mainAxisAlignment: MainAxisAlignment.start, 63 | children: [ 64 | Icon(Icons.star, color: Colors.white, size: fs>15,), 65 | Text( 66 | "${model.list[index].commentScore}", 67 | style: TextStyle(color: Colors.white, fontSize: fs>13.0), 68 | ) 69 | ], 70 | ), 71 | ), 72 | ), 73 | ) 74 | ], 75 | ), 76 | ), 77 | Text(model.list[index].title, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold, fontSize: fs>15.0),), 78 | Text(model.list[index].title, maxLines: 2, style: TextStyle(color: Colors.black38, fontSize: fs>13.0),) 79 | ], 80 | ); 81 | }, 82 | ), 83 | DetailRefresh(), 84 | DetailBottomLine() 85 | ], 86 | ), 87 | ); 88 | } 89 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Views/detail_live.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Modules/Home/Model/home_detail.dart'; 3 | import 'detail_title_more.dart'; 4 | import 'detail_refresh.dart'; 5 | import 'detail_bottom_line.dart'; 6 | import 'package:xmlyfm/Modules/Basic/ft_collection_view.dart'; 7 | import 'package:xmlyfm/Configs/configs.dart'; 8 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 9 | 10 | class DetailLive extends StatelessWidget { 11 | DetailLive(this.model) : assert(model != null); 12 | 13 | final HomeDetail model; 14 | final itemSpacing = 10.0; 15 | final columnNum = 3; 16 | final padding = EdgeInsets.symmetric(horizontal: 10.0); 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | final itemImageWH = (MediaQuery.of(context).size.width - padding.horizontal - (columnNum-1) * itemSpacing) / columnNum; 21 | 22 | return Container( 23 | color: Colors.white, 24 | child: Column( 25 | children: [ 26 | DetailTitleMore(model.title), 27 | // x宫格 28 | FTCollectionView( 29 | itemCount: model.list.length, 30 | columnNum: columnNum, 31 | itemSpacing: itemSpacing, 32 | lineSpacing: 10.0, 33 | padding: padding, 34 | builder: (context, index) { 35 | return Column( 36 | crossAxisAlignment: CrossAxisAlignment.start, 37 | children: [ 38 | ClipRRect( 39 | borderRadius: BorderRadius.circular(4.0), 40 | child: Stack( 41 | children: [ 42 | Image.network(model.list[index].coverMiddle ?? "", fit: BoxFit.fill, width: itemImageWH, height: itemImageWH,), 43 | Positioned(bottom: 0, right: 0, left: 0, 44 | child: DecoratedBox( 45 | decoration: BoxDecoration( 46 | gradient: LinearGradient( 47 | colors: [Colors.black54, Colors.transparent], 48 | begin: Alignment.bottomCenter, 49 | end: Alignment.topCenter)), 50 | child: Row( 51 | children: [ 52 | Icon(Icons.play_arrow, color: Colors.white, size: fs>17,), 53 | Expanded(child: Text( 54 | "${model.list[index].playCount ?? 0}", 55 | style: TextStyle(color: Colors.white, fontSize: fs>13.0,) 56 | ),), 57 | Padding( 58 | padding: EdgeInsets.only(right: fs>3.0, bottom: fs>3.0), 59 | child: ClipRRect( 60 | borderRadius: BorderRadius.all(Radius.circular(4.0)), 61 | child: DecoratedBox( 62 | decoration: BoxDecoration(color: themeColor), 63 | child: Padding( 64 | padding: EdgeInsets.symmetric(horizontal: fs>3.0, vertical: fs>1.0), 65 | child: Text(model.list[index].categoryName ?? "", style: TextStyle(color: Colors.white, fontSize: fs>13.0)), 66 | ), 67 | ), 68 | ), 69 | ) 70 | ], 71 | ), 72 | ), 73 | ) 74 | ], 75 | ), 76 | ), 77 | Container(height: 8.0,), 78 | Text(model.list[index].name ?? "", maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle(color: Colors.black, fontSize: fs>17.0, fontWeight: FontWeight.bold,)), 79 | Text(model.list[index].nickname ?? "", maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(color: Color(0xFF9F9F9F), fontSize: fs>13.0)) 80 | ], 81 | ); 82 | }, 83 | ), 84 | DetailRefresh(), 85 | DetailBottomLine() 86 | ], 87 | ), 88 | ); 89 | } 90 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Me/me_route.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'Header/me_header.dart'; 3 | import 'Cell/me_cell.dart'; 4 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 5 | 6 | class MeRoute extends StatefulWidget { 7 | @override 8 | _MeRouteState createState() => _MeRouteState(); 9 | } 10 | 11 | class _MeRouteState extends State { 12 | ScrollController _scrollController; 13 | double elevation = 0.0; // 0 | 0.6 14 | // list 15 | final Map listTitles1 = { 16 | "我的积分": null, 17 | "知识大使": 18 | MeCellConfig(type: MeCellType.Url, urlTitle: "分享赚钱"), //Text("分享赚钱"), 19 | "我的收听偏好": null, 20 | }; 21 | final Map listTitles2 = { 22 | "扫一扫": null, 23 | "知识大使": MeCellConfig(type: MeCellType.Switch), 24 | }; 25 | final Map listTitles3 = { 26 | "金融专区": MeCellConfig(type: MeCellType.Url, urlTitle: "各种权益免费领"), 27 | "运营商服务": null, 28 | "商城": null, 29 | "推荐喜马拉雅给好友": MeCellConfig(type: MeCellType.Url, urlTitle: "领20元优惠券"), 30 | "帮助与反馈": null, 31 | }; 32 | 33 | @override 34 | void initState() { 35 | super.initState(); 36 | _scrollController = ScrollController(); 37 | _scrollController.addListener(() { 38 | // 控制AppBar底部横线是否显示 39 | setState(() { 40 | elevation = _scrollController.offset <= 0 ? 0 : 0.6; 41 | }); 42 | }); 43 | } 44 | 45 | @override 46 | Widget build(BuildContext context) { 47 | return Scaffold( 48 | appBar: AppBar( 49 | brightness: Brightness.light, 50 | elevation: elevation, // 底部阴影 51 | backgroundColor: Color(0xFFFAFAFA), 52 | actions: [ 53 | Padding( 54 | padding: const EdgeInsets.only(right: 15.0), 55 | child: Row( 56 | children: [ 57 | InkWell( 58 | onTap: () { 59 | print('邮箱'); 60 | }, 61 | child: Image.asset( 62 | 'images/me/host_theme_ic_title_bar_message.png', 63 | width: 30.0, 64 | ), 65 | ), 66 | Container( 67 | width: 10.0, 68 | ), 69 | InkWell( 70 | onTap: () { 71 | print('邮箱'); 72 | }, 73 | child: Image.asset( 74 | 'images/me/host_theme_ic_title_bar_setting.png', 75 | width: 25.0, 76 | ), 77 | ), 78 | ], 79 | ), 80 | ) 81 | ], 82 | ), 83 | body: CustomScrollView( 84 | controller: _scrollController, 85 | slivers: [ 86 | SliverPadding( 87 | padding: EdgeInsets.symmetric(vertical: 10.0), 88 | sliver: SliverToBoxAdapter( 89 | child: Container( 90 | // decoration: BoxDecoration(color: Colors.yellow), 91 | child: MeHeader(), 92 | ), 93 | ), 94 | ), 95 | createSliverList(listTitles1), 96 | createLineBlock(), 97 | createSliverList(listTitles2), 98 | createLineBlock(), 99 | createSliverList(listTitles3), 100 | ], 101 | ), 102 | ); 103 | } 104 | 105 | // 创建list 106 | Widget createSliverList(Map datas) { 107 | return SliverFixedExtentList( 108 | itemExtent: fs>50.0, // 行高 109 | delegate: SliverChildBuilderDelegate((context, index) { 110 | return Container( 111 | // color: Colors.redAccent, 112 | child: Padding( 113 | padding: const EdgeInsets.only(left: 10.0), 114 | child: Column( 115 | children: [ 116 | Expanded( 117 | child: MeCell( 118 | title: datas.keys.toList()[index], 119 | config: datas.values.toList()[index], 120 | ), 121 | ), 122 | ], 123 | ), 124 | ), 125 | ); 126 | }, childCount: datas.values.length), 127 | ); 128 | } 129 | 130 | // 创建list的底部行块 131 | Widget createLineBlock() { 132 | return SliverToBoxAdapter( 133 | child: Container( 134 | decoration: BoxDecoration(color: Color(0xFFF3F4F5)), 135 | child: Container( 136 | height: fs>8.0, 137 | ), 138 | ), 139 | ); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Views/detail_categoriesForShort.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Modules/Home/Model/home_detail.dart'; 3 | import 'detail_title_more.dart'; 4 | import 'detail_refresh.dart'; 5 | import 'detail_bottom_line.dart'; 6 | import 'package:xmlyfm/Modules/Basic/ft_collection_view.dart'; 7 | import 'package:xmlyfm/Configs/configs.dart'; 8 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 9 | 10 | class DetailCategoriesForShort extends StatelessWidget { 11 | DetailCategoriesForShort(this.model) : assert(model != null); 12 | 13 | final HomeDetail model; 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | final imgHeight = fs>80.0; 18 | final keywords = model.keywords.length > 4 ? model.keywords.sublist(0, 4): model.keywords.sublist(0); 19 | 20 | return Container( 21 | color: Colors.white, 22 | child: Column( 23 | crossAxisAlignment: CrossAxisAlignment.start, 24 | children: [ 25 | DetailTitleMore(model.title), 26 | // keywords 27 | Padding( 28 | padding: EdgeInsets.only(left: 10.0, right: 10.0, bottom: 30.0), 29 | child: Wrap( 30 | spacing: 10.0, // 主轴方向间距 31 | runSpacing: 4.0, // 纵轴方向间距 32 | children: keywords.map((item){ 33 | return DecoratedBox( 34 | decoration: BoxDecoration( 35 | border: Border.all(color: Colors.grey), 36 | borderRadius: BorderRadius.circular(fs>20.0), 37 | color: Colors.white 38 | ), 39 | child: Padding( 40 | padding: EdgeInsets.symmetric(vertical: fs>8.0, horizontal: fs>15.0), 41 | child: Text(item.keywordName, style: TextStyle(fontSize: fs>14.0),), 42 | ), 43 | ); 44 | }).toList() 45 | ), 46 | ), 47 | // x宫格 48 | FTCollectionView( 49 | itemCount: model.list.length, 50 | itemSpacing: 10.0, 51 | lineSpacing: 10.0, 52 | padding: EdgeInsets.symmetric(horizontal: 10.0), 53 | builder: (context, index) { 54 | final item = model.list[index]; 55 | return Row( 56 | mainAxisAlignment: MainAxisAlignment.start, 57 | crossAxisAlignment: CrossAxisAlignment.start, 58 | children: [ 59 | ClipRRect( 60 | borderRadius: BorderRadius.circular(3.0), 61 | child: Image.network(model.list[index].pic ?? "", width: imgHeight,) 62 | ), 63 | Expanded(child: Padding( 64 | padding: EdgeInsets.symmetric(horizontal: 10.0), 65 | child: Column( 66 | crossAxisAlignment: CrossAxisAlignment.start, 67 | children: [ 68 | Padding(padding: EdgeInsets.only(bottom: 5.0), child: Text(item.title, maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle(color: Colors.black, fontSize: fs>18.0, fontWeight: FontWeight.bold,)),), 69 | Padding(padding: EdgeInsets.only(bottom: 5.0), child: Text(item.subtitle, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(color: Color(0xFF9F9F9F), fontSize: fs>15.0),),), 70 | Padding(padding: EdgeInsets.only(bottom: 5.0), child: Row( 71 | children: [ 72 | Icon(Icons.play_arrow, color: Color(0xFF9C9C9C), size: fs>20.0), 73 | Text('${item.playsCount ?? 0}', style: TextStyle(color: Color(0xFF9F9F9F), fontSize: fs>13.0, fontWeight: FontWeight.bold),), 74 | Container(width: 15.0,), 75 | Icon(Icons.graphic_eq, color: Color(0xFF9C9C9C), size: fs>18.0), 76 | Text('${item.tracksCount ?? 0}集', style: TextStyle(color: Color(0xFF9F9F9F), fontSize: fs>13.0, fontWeight: FontWeight.bold),), 77 | ], 78 | )), 79 | Padding( 80 | padding: EdgeInsets.only(top: 10.0, bottom: 10.0), 81 | child: Container(height: 1, color: bgColor,), 82 | ) 83 | ],), 84 | ),) 85 | ],); 86 | }, 87 | ), 88 | DetailRefresh(), 89 | DetailBottomLine() 90 | ], 91 | ), 92 | ); 93 | } 94 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Views/detail_recommendAlbum.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Modules/Home/Model/home_detail.dart'; 3 | import 'detail_title_more.dart'; 4 | import 'detail_refresh.dart'; 5 | import 'detail_bottom_line.dart'; 6 | import 'package:xmlyfm/Modules/Basic/ft_collection_view.dart'; 7 | import 'package:xmlyfm/Configs/configs.dart'; 8 | import 'package:xmlyfm/Configs/xmly_api.dart'; 9 | import 'package:dio/dio.dart'; 10 | import 'package:xmlyfm/Modules/Home/Model/home_recommend.dart'; 11 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 12 | 13 | class DetailRecommendAlbum extends StatefulWidget { 14 | DetailRecommendAlbum(this.model) : assert(model != null); 15 | 16 | final HomeDetail model; 17 | 18 | @override 19 | _DetailRecommendAlbum createState() => _DetailRecommendAlbum(); 20 | } 21 | 22 | class _DetailRecommendAlbum extends State { 23 | 24 | List models = []; 25 | 26 | @override 27 | void initState() { 28 | super.initState(); 29 | _fetchRecommend(); 30 | } 31 | 32 | @override 33 | Widget build(BuildContext context) { 34 | final imgHeight = fs>80.0; 35 | 36 | return Container( 37 | color: Colors.white, 38 | child: Column( 39 | crossAxisAlignment: CrossAxisAlignment.start, 40 | children: [ 41 | DetailTitleMore("为你推荐"), 42 | // x宫格 43 | FTCollectionView( 44 | itemCount: models.length ?? 0, 45 | itemSpacing: 10.0, 46 | lineSpacing: 10.0, 47 | padding: EdgeInsets.symmetric(horizontal: fs>10.0), 48 | builder: (context, index) { 49 | final item = models[index]; 50 | return Row( 51 | mainAxisAlignment: MainAxisAlignment.start, 52 | crossAxisAlignment: CrossAxisAlignment.start, 53 | children: [ 54 | ClipRRect( 55 | borderRadius: BorderRadius.circular(3.0), 56 | child: Image.network(models[index].coverMiddle ?? "", width: imgHeight,) 57 | ), 58 | Expanded(child: Padding( 59 | padding: EdgeInsets.symmetric(horizontal: fs>10.0), 60 | child: Column( 61 | crossAxisAlignment: CrossAxisAlignment.start, 62 | children: [ 63 | Padding(padding: EdgeInsets.only(bottom: 5.0), child: Text(item.title ?? "", maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle(color: Colors.black, fontSize: fs>18.0, fontWeight: FontWeight.bold,)),), 64 | Padding(padding: EdgeInsets.only(bottom: 5.0), child: Text(item.recReason ?? "", maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(color: Color(0xFF9F9F9F), fontSize: fs>15.0),),), 65 | Padding(padding: EdgeInsets.only(bottom: 5.0), child: Text(item.albumLabel ?? "", maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(color: Color(0xFF9F9F9F), fontSize: fs>15.0),),), 66 | // Padding(padding: EdgeInsets.only(bottom: 5.0), child: Row( 67 | // children: [ 68 | // Icon(Icons.play_arrow, color: Color(0xFF9C9C9C), size: 20.0), 69 | // Text('${item.playsCount ?? 0}', style: TextStyle(color: Color(0xFF9F9F9F), fontSize: 13.0, fontWeight: FontWeight.bold),), 70 | // Container(width: 15.0,), 71 | // Icon(Icons.graphic_eq, color: Color(0xFF9C9C9C), size: 18.0), 72 | // Text('${item.tracksCount ?? 0}集', style: TextStyle(color: Color(0xFF9F9F9F), fontSize: 13.0, fontWeight: FontWeight.bold),), 73 | // ], 74 | // )), 75 | Padding( 76 | padding: EdgeInsets.only(top: 10.0, bottom: 10.0), 77 | child: Container(height: 1, color: bgColor,), 78 | ) 79 | ],), 80 | ),) 81 | ],); 82 | }, 83 | ), 84 | DetailRefresh(), 85 | DetailBottomLine() 86 | ], 87 | ), 88 | ); 89 | } 90 | 91 | _fetchRecommend() async { 92 | final dio = Dio(); 93 | final response = await dio.get(home_recommend); 94 | List jsonArr = response.data['data']['albums']; 95 | List models = jsonArr.map((json)=>HomeRecommend.fromJson(json)).toList(); 96 | setState(() { 97 | this.models = models; 98 | }); 99 | } 100 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Views/detail_categoriesForLong.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Modules/Home/Model/home_detail.dart'; 3 | import 'detail_title_more.dart'; 4 | import 'detail_refresh.dart'; 5 | import 'detail_bottom_line.dart'; 6 | import 'package:xmlyfm/Modules/Basic/ft_collection_view.dart'; 7 | import 'detail_categoriesForShort.dart'; 8 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 9 | 10 | class DetailCategoriesForLong extends StatelessWidget { 11 | DetailCategoriesForLong(this.model) : assert(model != null); 12 | 13 | final HomeDetail model; 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | switch (model.fetchCategoriesDirection()) { 18 | case DetailCategoriesDirection.Column: return DetailCategoriesForShort(model); 19 | default: 20 | final itemSpacing = 10.0; 21 | final columnNum = 3; 22 | final padding = EdgeInsets.symmetric(horizontal: 10.0); 23 | final itemImageWH = (MediaQuery.of(context).size.width - padding.horizontal - (columnNum-1) * itemSpacing) / columnNum; 24 | 25 | final keywords = model.keywords.length > 4 ? model.keywords.sublist(0, 4): model.keywords.sublist(0); 26 | return Container( 27 | color: Colors.white, 28 | child: Column( 29 | crossAxisAlignment: CrossAxisAlignment.start, 30 | children: [ 31 | DetailTitleMore(model.title), 32 | // keywords 33 | Padding( 34 | padding: EdgeInsets.only(left: 10.0, right: 10.0, bottom: 10.0), 35 | child: Wrap( 36 | spacing: 10.0, // 主轴方向间距 37 | runSpacing: 4.0, // 纵轴方向间距 38 | children: keywords.map((item){ 39 | return DecoratedBox( 40 | decoration: BoxDecoration( 41 | border: Border.all(color: Colors.grey), 42 | borderRadius: BorderRadius.circular(fs>20.0), 43 | color: Colors.white 44 | ), 45 | child: Padding( 46 | padding: EdgeInsets.symmetric(vertical: fs>8.0, horizontal: fs>15.0), 47 | child: Text(item.keywordName, style: TextStyle(fontSize: fs>14.0)), 48 | ), 49 | ); 50 | }).toList() 51 | ), 52 | ), 53 | // x宫格 54 | FTCollectionView( 55 | itemCount: model.list.length, 56 | columnNum: columnNum, 57 | itemSpacing: itemSpacing, 58 | lineSpacing: 10.0, 59 | padding: padding, 60 | builder: (context, index) { 61 | return Column( 62 | crossAxisAlignment: CrossAxisAlignment.start, 63 | children: [ 64 | ClipRRect( 65 | borderRadius: BorderRadius.circular(4.0), 66 | child: Stack( 67 | children: [ 68 | Image.network(model.list[index].pic, fit: BoxFit.fill, width: itemImageWH, height: itemImageWH,), 69 | Positioned(bottom: 0, right: 0, left: 0, 70 | child: DecoratedBox( 71 | decoration: BoxDecoration( 72 | gradient: LinearGradient( 73 | colors: [Colors.black54, Colors.transparent], 74 | begin: Alignment.bottomCenter, 75 | end: Alignment.topCenter)), 76 | child: Row( 77 | children: [ 78 | Icon(Icons.play_arrow, color: Colors.white, size: fs>17,), 79 | Text( 80 | "${model.list[index].playsCount}", 81 | style: TextStyle(color: Colors.white, fontSize: fs>13.0,) 82 | ) 83 | ], 84 | ), 85 | ), 86 | ) 87 | ], 88 | ), 89 | ), 90 | Container(height: fs>8.0,), 91 | Text(model.list[index].title, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(color: Colors.black, fontSize: fs>18.0, fontWeight: FontWeight.bold,)), 92 | Text(model.list[index].subtitle, maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle(color: Color(0xFF9F9F9F), fontSize: fs>13.0)) 93 | ], 94 | ); 95 | }, 96 | ), 97 | DetailRefresh(), 98 | DetailBottomLine() 99 | ], 100 | ), 101 | );; 102 | } 103 | } 104 | } -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/home_detail_route.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:dio/dio.dart'; 3 | import 'package:xmlyfm/Configs/xmly_api.dart'; 4 | import 'Model/home_detail.dart'; 5 | import 'Model/home_detail_list.dart'; 6 | import 'Views/detail_square.dart'; 7 | import 'Views/detail_focus.dart'; 8 | import 'Views/detail_topBuzz.dart'; 9 | import 'Views/detail_guessYouLike.dart'; 10 | import 'Views/detail_paidCategory.dart'; 11 | import 'Views/detail_categoriesForShort.dart'; 12 | import 'Views/detail_playlist.dart'; 13 | import 'Views/detail_oneKeyListen.dart'; 14 | import 'Views/detail_categoriesForLong.dart'; 15 | import 'Views/detail_microLesson.dart'; 16 | import 'Views/detail_live.dart'; 17 | import 'Views/detail_recommendAlbum.dart'; 18 | 19 | class HomeDetailRoute extends StatefulWidget { 20 | HomeDetailRoute({ 21 | @required this.categoryId, 22 | this.bgAlphaBolck 23 | }): assert(categoryId != null); 24 | 25 | final int categoryId; 26 | final ValueChanged bgAlphaBolck; 27 | 28 | @override 29 | _HomeDetailRouteState createState() => _HomeDetailRouteState(); 30 | } 31 | 32 | class _HomeDetailRouteState extends State { 33 | List detailList = []; 34 | ScrollController _scrollController; 35 | 36 | @override 37 | void initState() { 38 | super.initState(); 39 | _scrollController = ScrollController(); 40 | _scrollController.addListener((){ 41 | if (widget.bgAlphaBolck == null) return; 42 | if (_scrollController.offset <= 0) { 43 | widget.bgAlphaBolck(255); 44 | } else { 45 | final delta = 10.0 - _scrollController.offset; 46 | delta <=0 ? widget.bgAlphaBolck(0) : widget.bgAlphaBolck((255 * delta / 10.0).floor()); 47 | } 48 | // print("offset -- ${_scrollController.offset}"); 49 | }); 50 | _fetchDetail(); 51 | } 52 | 53 | @override 54 | Widget build(BuildContext context) { 55 | return CustomScrollView( 56 | controller: _scrollController, 57 | slivers: createWidgets(), 58 | ); 59 | } 60 | 61 | List createWidgets() { 62 | if (detailList.isEmpty) return []; 63 | return detailList.map((model) { 64 | switch (model.fetchDetailType()) { 65 | case HomeDetailType.Focus: 66 | return SliverToBoxAdapter(child: DetailFocus(model.list)); 67 | case HomeDetailType.Square: 68 | return DetailSquare(model.list); 69 | case HomeDetailType.TopBuzz: 70 | return SliverToBoxAdapter(child: DetailTopBuzz(model)); 71 | case HomeDetailType.GuessYouLike: 72 | return SliverToBoxAdapter(child: DetailGuessYouLike(model)); 73 | case HomeDetailType.PaidCategory: 74 | return SliverToBoxAdapter(child: DetailPaidCategory(model)); 75 | case HomeDetailType.CategoriesForShort: 76 | return SliverToBoxAdapter(child: DetailCategoriesForShort(model)); 77 | case HomeDetailType.Playlist: 78 | return SliverToBoxAdapter(child: DetailPlaylist(model)); 79 | case HomeDetailType.OneKeyListen: 80 | return SliverToBoxAdapter(child: DetailOneKeyListen(model)); 81 | case HomeDetailType.CategoriesForLong: 82 | return SliverToBoxAdapter(child: DetailCategoriesForLong(model)); 83 | case HomeDetailType.MicroLesson: 84 | return SliverToBoxAdapter(child: DetailMicroLesson(model)); 85 | case HomeDetailType.Live: 86 | return SliverToBoxAdapter(child: DetailLive(model)); 87 | case HomeDetailType.CategoriesForExplore: 88 | return SliverToBoxAdapter(child: DetailCategoriesForShort(model)); 89 | case HomeDetailType.Ad: 90 | return SliverToBoxAdapter(child: Container()); 91 | // return SliverToBoxAdapter(child: Text('Ad')); 92 | case HomeDetailType.RecommendAlbum: 93 | return SliverToBoxAdapter(child: DetailRecommendAlbum(model)); 94 | default: return SliverToBoxAdapter(); 95 | } 96 | }).toList(); 97 | } 98 | 99 | void _fetchDetail() async { 100 | final dio = Dio(); 101 | final response = await dio.get(home_detail, data: { 102 | 'categoryId': widget.categoryId, // '-2' 103 | 'device': 'android', 104 | 'deviceId': 'android', 105 | 'includeActivity': true, 106 | 'includeSpecial': true, 107 | 'pullToRefresh': false, 108 | 'version': '6.5.39' 109 | }); 110 | List list = response.data['list']; 111 | List detailList = []; 112 | for (var i = 0; i < list.length; i++) { 113 | final detail = HomeDetail.fromJson(list[i]); 114 | // banner需要特殊处理 115 | if (detail.fetchDetailType() == HomeDetailType.Focus) { 116 | final List bannerList = response.data['list'][i]['list'][0]['data']; 117 | detail.list = bannerList.map((json) => HomeDetailList.fromJson(json)).toList(); 118 | } 119 | detailList.add(detail); 120 | } 121 | setState(() { 122 | this.detailList = detailList; 123 | }); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Model/home_detail_list.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'home_detail_list.g.dart'; 4 | 5 | @JsonSerializable() 6 | class HomeDetailList { 7 | HomeDetailList( 8 | this.albumId, 9 | this.albumTitle, 10 | this.commentsCounts, 11 | this.coverSmall, 12 | this.createdAt, 13 | this.duration, 14 | this.favoritesCounts, 15 | this.id, 16 | this.isAuthorized, 17 | this.isFree, 18 | this.isPaid, 19 | this.nickname, 20 | this.playPath32, 21 | this.playPath64, 22 | this.playPathAacv164, 23 | this.playPathAacv224, 24 | this.playsCounts, 25 | this.priceTypeId, 26 | this.sampleDuration, 27 | this.sharesCounts, 28 | this.tags, 29 | this.title, 30 | this.trackId, 31 | this.uid, 32 | this.updatedAt, 33 | this.userSource, 34 | this.contentUpdatedAt, 35 | this.enableShare, 36 | this.isExternalUrl, 37 | this.bubbleText, 38 | this.contentType, 39 | this.coverPath, 40 | this.displayClass, 41 | this.sharePic, 42 | this.subtitle, 43 | this.url, 44 | this.adId, 45 | this.adType, 46 | this.buttonShowed, 47 | this.clickAction, 48 | this.clickType, 49 | this.cover, 50 | this.description, 51 | this.displayType, 52 | this.isAd, 53 | this.isInternal, 54 | this.isLandScape, 55 | this.isShareFlag, 56 | this.link, 57 | this.name, 58 | this.openlinkType, 59 | this.realLink, 60 | this.targetId, 61 | this.categoryId, 62 | this.commentsCount, 63 | this.contractStatus, 64 | this.isFinished, 65 | this.lastUptrackAt, 66 | this.originalStatus, 67 | this.playsCount, 68 | this.priceTypeEnum, 69 | this.refundSupportType, 70 | this.tracksCount, 71 | this.vipFreeType, 72 | this.isDraft, 73 | this.isFollowing, 74 | this.isVipFree, 75 | this.subscribeStatus, 76 | this.infoType, 77 | this.materialType, 78 | this.pic, 79 | this.recSrc, 80 | this.recTrack, 81 | this.discountedPrice, 82 | this.price, 83 | this.commentScore, 84 | this.vipPrice, 85 | this.displayDiscountedPrice, 86 | this.displayPrice, 87 | this.displayVipPrice, 88 | this.priceUnit, 89 | this.columnType, 90 | this.specialId, 91 | this.footnote, 92 | this.channelId, 93 | this.onLineNum, 94 | this.channelName, 95 | this.coverRound, 96 | this.liveStatus, 97 | this.liveType, 98 | this.openType, 99 | this.participationCount, 100 | this.planLessonCount, 101 | this.nickName, 102 | this.actualStartAt, 103 | this.chatId, 104 | this.endAt, 105 | this.playCount, 106 | this.roomId, 107 | this.startAt, 108 | this.status, 109 | this.categoryName, 110 | this.coverLarge, 111 | this.coverMiddle 112 | ); 113 | 114 | // 通用 115 | int id; 116 | String title; 117 | 118 | int albumId; // 9604235 119 | String albumTitle; // 半月谈晚报 120 | int commentsCounts; 121 | String coverSmall; 122 | int createdAt; 123 | int duration; 124 | int favoritesCounts; 125 | bool isAuthorized; 126 | bool isFree; 127 | bool isPaid; 128 | String nickname; 129 | String playPath32; 130 | String playPath64; 131 | String playPathAacv164; 132 | String playPathAacv224; 133 | int playsCounts; 134 | int priceTypeId; 135 | int sampleDuration; 136 | int sharesCounts; 137 | String tags; 138 | int trackId; 139 | int uid; 140 | int updatedAt; 141 | int userSource; 142 | 143 | // Focus 144 | int adId; // 182708 145 | int adType; // 0 146 | bool buttonShowed; 147 | int clickAction; 148 | int clickType; 149 | String cover; // 封面 150 | String description; 151 | int displayType; 152 | bool isAd; 153 | int isInternal; 154 | bool isLandScape; 155 | bool isShareFlag; 156 | String link; 157 | String name; 158 | int openlinkType; 159 | String realLink; 160 | int targetId; 161 | 162 | // Square 163 | int contentUpdatedAt; 164 | bool enableShare; 165 | bool isExternalUrl; 166 | String bubbleText; 167 | String contentType; 168 | String coverPath; 169 | String displayClass; 170 | String sharePic; 171 | String subtitle; 172 | String url; 173 | 174 | // guessYouLike 175 | int categoryId; 176 | int commentsCount; 177 | int contractStatus; 178 | int isFinished; 179 | int lastUptrackAt; 180 | int originalStatus; 181 | int playsCount; 182 | int priceTypeEnum; 183 | int refundSupportType; 184 | int tracksCount; 185 | int vipFreeType; 186 | bool isDraft; 187 | bool isFollowing; 188 | bool isVipFree; 189 | bool subscribeStatus; 190 | String infoType; 191 | String materialType; 192 | String pic; 193 | String recSrc; 194 | String recTrack; 195 | 196 | // paidCategory 197 | double discountedPrice; 198 | double price; 199 | double commentScore; 200 | double vipPrice; 201 | String displayDiscountedPrice; 202 | String displayPrice; 203 | String displayVipPrice; 204 | String priceUnit; 205 | 206 | // playlist 207 | int columnType; 208 | int specialId; 209 | String footnote; 210 | 211 | // oneKeyListen 212 | int channelId; 213 | int onLineNum; 214 | String channelName; 215 | String coverRound; 216 | 217 | // microLesson 218 | int liveStatus; 219 | int liveType; 220 | int openType; 221 | int participationCount; 222 | int planLessonCount; 223 | String nickName; 224 | 225 | // live 226 | int actualStartAt; 227 | int chatId; 228 | int endAt; 229 | int playCount; 230 | int roomId; 231 | int startAt; 232 | int status; 233 | String categoryName; 234 | String coverLarge; 235 | String coverMiddle; 236 | 237 | factory HomeDetailList.fromJson(Map json) => 238 | _$HomeDetailListFromJson(json); 239 | Map toJson() => _$HomeDetailListToJson(this); 240 | } 241 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/home_route.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Configs/xmly_api.dart'; 3 | import 'package:dio/dio.dart'; 4 | import 'Model/home_category_item.dart'; 5 | import 'Views/home_search.dart'; 6 | import 'package:flutter_webview_plugin/flutter_webview_plugin.dart'; 7 | import 'home_detail_route.dart'; 8 | import 'package:xmlyfm/Configs/configs.dart'; 9 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 10 | 11 | class HomeRoute extends StatefulWidget { 12 | @override 13 | _HomeRouteState createState() => _HomeRouteState(); 14 | } 15 | 16 | class _HomeRouteState extends State 17 | with SingleTickerProviderStateMixin { 18 | List categoryModelList = []; 19 | TabController _tabController; 20 | int _tabBarBgAlpha = 255; 21 | bool _isTabBarOverAlpha = false; 22 | 23 | @override 24 | void initState() { 25 | super.initState(); 26 | _fetchCategory(); 27 | } 28 | 29 | @override 30 | void dispose() { 31 | _tabController.dispose(); 32 | super.dispose(); 33 | } 34 | 35 | @override 36 | Widget build(BuildContext context) { 37 | final statusBarHeight = MediaQuery.of(context).padding.top; 38 | return Scaffold( 39 | body: Stack( fit: StackFit.expand, 40 | children: [ 41 | Positioned( 42 | left: .0, 43 | right: .0, 44 | // height: 100.0, 45 | child: Container( 46 | // color: Colors.red, 47 | color: Colors.white, 48 | height: fs(260.0) + statusBarHeight, 49 | )), 50 | Positioned( 51 | left: .0, 52 | right: .0, 53 | height: statusBarHeight + fs(200.0), 54 | child: Container( 55 | // color: Colors.blue, 56 | color: Color(0xFFB1A383).withAlpha(_tabBarBgAlpha), 57 | ), 58 | ), 59 | Positioned( 60 | child: Column( 61 | children: [ 62 | Padding( 63 | padding: EdgeInsets.only(top: statusBarHeight), 64 | child: Container( 65 | height: fs>50.0, 66 | decoration: BoxDecoration(color: Colors.transparent), 67 | child: Row( 68 | children: _tabController == null 69 | ? [] 70 | : [ 71 | Expanded( 72 | child: TabBar( 73 | controller: _tabController, 74 | isScrollable: true, 75 | indicatorColor: _isTabBarOverAlpha ? themeColor : Colors.white, 76 | indicatorSize: TabBarIndicatorSize.label, 77 | labelColor: _isTabBarOverAlpha ? Colors.black : Colors.white, 78 | unselectedLabelColor: _isTabBarOverAlpha ? Colors.black : Color(0xFFF9F9F9), 79 | labelStyle: TextStyle(fontSize: fs>20.0, fontWeight: FontWeight.bold), 80 | unselectedLabelStyle: TextStyle(fontSize: fs>15.0), // Color(0xFFF9F9F9) 81 | tabs: categoryModelList.map((model) { 82 | return Tab( 83 | text: model.title, 84 | ); 85 | }).toList(), 86 | ), 87 | ), 88 | Center(child: Padding( 89 | padding: EdgeInsets.symmetric(horizontal: 10.0), 90 | child: Icon(Icons.table_chart, color: _isTabBarOverAlpha ? themeColor : Colors.white,), 91 | )), 92 | ], 93 | ), 94 | ), 95 | ), 96 | HomeSearch(isTabBarOverAlpha: _isTabBarOverAlpha,), 97 | _tabController == null 98 | ? Container() 99 | : Expanded( 100 | child: TabBarView( 101 | controller: _tabController, 102 | children: _createTabBarList(), 103 | ), 104 | ), 105 | ], 106 | ), 107 | ) 108 | ], 109 | )); 110 | } 111 | 112 | // 获取分类 113 | void _fetchCategory() async { 114 | final Dio dio = Dio(); 115 | final response = await dio.get(home_category, data: { 116 | 'channel': 'and-gdt1-20', 117 | "device": "android", 118 | 'version': '6.5.39' 119 | }); 120 | // print(response.data.toString()); 121 | List categoryList = response.data['customCategoryList']; 122 | List models = []; 123 | for (var i = 0; i < categoryList.length; i++) { 124 | models.add(HomeCategoryItem.fromJson(categoryList[i])); 125 | } 126 | setState(() { 127 | categoryModelList = models; 128 | _tabController = TabController(length: models.length, vsync: this); 129 | }); 130 | } 131 | 132 | List _createTabBarList() { 133 | return categoryModelList.map((model) { 134 | switch (model.itemType) { 135 | case "h5": 136 | print(model.url); 137 | return Container(child: WebviewScaffold( 138 | url: 'www.qq.com', //model.url, 139 | withJavascript: true, 140 | appBar: AppBar( 141 | title: Text('WebView'), 142 | ), 143 | ), 144 | height: 100.0,); 145 | default: return HomeDetailRoute(categoryId: model.categoryId ?? -2, bgAlphaBolck: (alpha){ 146 | setState(() { 147 | _tabBarBgAlpha = alpha; 148 | _isTabBarOverAlpha = alpha < 50.0; 149 | }); 150 | },); 151 | } 152 | }).toList(); 153 | } 154 | } 155 | 156 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/DetailList/Model/album.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'album.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | Album _$AlbumFromJson(Map json) { 10 | return Album( 11 | json['ageLevel'] as int, 12 | json['albumId'] as int, 13 | json['authorizedExpireTime'] as int, 14 | json['authorizedTypeId'] as int, 15 | json['categoryId'] as int, 16 | json['contractStatus'] as int, 17 | json['createdAt'] as int, 18 | json['freeToPaidStatus'] as int, 19 | json['freeToPaidTime'] as int, 20 | json['lastUptrackAt'] as int, 21 | json['lastUptrackId'] as int, 22 | json['offlineReason'] as int, 23 | json['offlineType'] as int, 24 | json['originalStatus'] as int, 25 | json['playTimes'] as int, 26 | json['playTrackId'] as int, 27 | json['refundSupportType'] as int, 28 | json['saleScope'] as int, 29 | json['serialState'] as int, 30 | json['serializeStatus'] as int, 31 | json['shareSupportType'] as int, 32 | json['shares'] as int, 33 | json['status'] as int, 34 | json['subscribeCount'] as int, 35 | json['tracks'] as int, 36 | json['type'] as int, 37 | json['uid'] as int, 38 | json['unReadAlbumCommentCount'] as int, 39 | json['updatedAt'] as int, 40 | json['vipFreeType'] as int, 41 | json['autoStart'] as bool, 42 | json['canInviteListen'] as bool, 43 | json['canShareAndStealListen'] as bool, 44 | json['hasNew'] as bool, 45 | json['hasRecs'] as bool, 46 | json['isAuthorized'] as bool, 47 | json['isDefault'] as bool, 48 | json['isDraft'] as bool, 49 | json['isFavorite'] as bool, 50 | json['isNoCopyright'] as bool, 51 | json['isPaid'] as bool, 52 | json['isPublic'] as bool, 53 | json['isRecordDesc'] as bool, 54 | json['isVerified'] as bool, 55 | json['isVipFree'] as bool, 56 | json['is_default'] as bool, 57 | json['avatarPath'] as String, 58 | json['categoryName'] as String, 59 | json['coverLarge'] as String, 60 | json['coverLargePop'] as String, 61 | json['coverMiddle'] as String, 62 | json['coverOrigin'] as String, 63 | json['coverSmall'] as String, 64 | json['coverWebLarge'] as String, 65 | json['customSubTitle'] as String, 66 | json['customTitle'] as String, 67 | json['detailCoverPath'] as String, 68 | json['intro'] as String, 69 | json['introRich'] as String, 70 | json['lastUptrackCoverPath'] as String, 71 | json['lastUptrackTitle'] as String, 72 | json['nickname'] as String, 73 | json['other_title'] as String, 74 | json['recommendReason'] as String, 75 | json['salePoint'] as String, 76 | json['salePointPopup'] as String, 77 | json['shortIntro'] as String, 78 | json['shortIntroRich'] as String, 79 | json['tags'] as String, 80 | json['title'] as String); 81 | } 82 | 83 | Map _$AlbumToJson(Album instance) => { 84 | 'ageLevel': instance.ageLevel, 85 | 'albumId': instance.albumId, 86 | 'authorizedExpireTime': instance.authorizedExpireTime, 87 | 'authorizedTypeId': instance.authorizedTypeId, 88 | 'categoryId': instance.categoryId, 89 | 'contractStatus': instance.contractStatus, 90 | 'createdAt': instance.createdAt, 91 | 'freeToPaidStatus': instance.freeToPaidStatus, 92 | 'freeToPaidTime': instance.freeToPaidTime, 93 | 'lastUptrackAt': instance.lastUptrackAt, 94 | 'lastUptrackId': instance.lastUptrackId, 95 | 'offlineReason': instance.offlineReason, 96 | 'offlineType': instance.offlineType, 97 | 'originalStatus': instance.originalStatus, 98 | 'playTimes': instance.playTimes, 99 | 'playTrackId': instance.playTrackId, 100 | 'refundSupportType': instance.refundSupportType, 101 | 'saleScope': instance.saleScope, 102 | 'serialState': instance.serialState, 103 | 'serializeStatus': instance.serializeStatus, 104 | 'shareSupportType': instance.shareSupportType, 105 | 'shares': instance.shares, 106 | 'status': instance.status, 107 | 'subscribeCount': instance.subscribeCount, 108 | 'tracks': instance.tracks, 109 | 'type': instance.type, 110 | 'uid': instance.uid, 111 | 'unReadAlbumCommentCount': instance.unReadAlbumCommentCount, 112 | 'updatedAt': instance.updatedAt, 113 | 'vipFreeType': instance.vipFreeType, 114 | 'autoStart': instance.autoStart, 115 | 'canInviteListen': instance.canInviteListen, 116 | 'canShareAndStealListen': instance.canShareAndStealListen, 117 | 'hasNew': instance.hasNew, 118 | 'hasRecs': instance.hasRecs, 119 | 'isAuthorized': instance.isAuthorized, 120 | 'isDefault': instance.isDefault, 121 | 'isDraft': instance.isDraft, 122 | 'isFavorite': instance.isFavorite, 123 | 'isNoCopyright': instance.isNoCopyright, 124 | 'isPaid': instance.isPaid, 125 | 'isPublic': instance.isPublic, 126 | 'isRecordDesc': instance.isRecordDesc, 127 | 'isVerified': instance.isVerified, 128 | 'isVipFree': instance.isVipFree, 129 | 'is_default': instance.is_default, 130 | 'avatarPath': instance.avatarPath, 131 | 'categoryName': instance.categoryName, 132 | 'coverLarge': instance.coverLarge, 133 | 'coverLargePop': instance.coverLargePop, 134 | 'coverMiddle': instance.coverMiddle, 135 | 'coverOrigin': instance.coverOrigin, 136 | 'coverSmall': instance.coverSmall, 137 | 'coverWebLarge': instance.coverWebLarge, 138 | 'customSubTitle': instance.customSubTitle, 139 | 'customTitle': instance.customTitle, 140 | 'detailCoverPath': instance.detailCoverPath, 141 | 'intro': instance.intro, 142 | 'introRich': instance.introRich, 143 | 'lastUptrackCoverPath': instance.lastUptrackCoverPath, 144 | 'lastUptrackTitle': instance.lastUptrackTitle, 145 | 'nickname': instance.nickname, 146 | 'other_title': instance.other_title, 147 | 'recommendReason': instance.recommendReason, 148 | 'salePoint': instance.salePoint, 149 | 'salePointPopup': instance.salePointPopup, 150 | 'shortIntro': instance.shortIntro, 151 | 'shortIntroRich': instance.shortIntroRich, 152 | 'tags': instance.tags, 153 | 'title': instance.title 154 | }; 155 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Me/Header/me_header.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:xmlyfm/Modules/Basic/vertical_button.dart'; 3 | import 'package:xmlyfm/Configs/configs.dart'; 4 | import 'package:flutter_fitsize/flutter_fitsize.dart'; 5 | 6 | class MeHeader extends StatefulWidget { 7 | @override 8 | _MeHeaderState createState() => _MeHeaderState(); 9 | } 10 | 11 | class _MeHeaderState extends State { 12 | final Map ownMap = { 13 | '已购': Icon(Icons.shopping_cart, size: fs>24.0,), 14 | '优惠券': Icon(Icons.account_balance, size: fs>24.0,), 15 | '喜点': Icon(Icons.confirmation_number, size: fs>24.0,), 16 | '喜钻': Icon(Icons.whatshot, size: fs>24.0,), 17 | '钱包': Icon(Icons.account_balance_wallet, size: fs>24.0,), 18 | }; 19 | final Map funcMap = { 20 | '我要录音': Icon(Icons.keyboard_voice, size: fs>24.0,), 21 | '我要直播': Icon(Icons.ondemand_video, size: fs>24.0,), 22 | '我的作品': Icon(Icons.toll, size: fs>24.0,), // disc_full 23 | '主播工作台': Icon(Icons.personal_video, size: fs>24.0,), 24 | }; 25 | 26 | @override 27 | Widget build(BuildContext context) { 28 | return Column( 29 | children: [ 30 | // 用户信息 31 | Padding( 32 | padding: EdgeInsets.symmetric(vertical: 10.0), 33 | child: Row( 34 | children: [ 35 | Padding( 36 | padding: EdgeInsets.only(left: 15.0, right: 10.0), 37 | child: CircleAvatar( 38 | child: Image.asset('images/me/host_default_avatar_88.png'), 39 | radius: fs>30.0), 40 | ), 41 | Expanded( 42 | child: Column( 43 | crossAxisAlignment: CrossAxisAlignment.start, 44 | children: [ 45 | Text('点击登录',style: TextStyle(fontSize: fs>16.0, fontWeight: FontWeight.bold),), 46 | Container(height: fs>5.0,), 47 | Text( 48 | '登录后数据不丢失', 49 | style: TextStyle( 50 | color: Color(0xFFA0A0A0), 51 | fontSize: fs>13.0, 52 | fontWeight: FontWeight.bold), 53 | ) 54 | ], 55 | ), 56 | ), 57 | DecoratedBox( 58 | decoration: BoxDecoration( 59 | borderRadius: BorderRadius.only(topLeft: Radius.circular(fs>24.0), bottomLeft: Radius.circular(fs>24.0)), 60 | color: Color(0xFFFFEBE7) 61 | ), 62 | child: Container( 63 | height: fs>48.0, 64 | width: fs>135.0, 65 | child: Row( 66 | children: [ 67 | Padding( 68 | padding: EdgeInsets.only(left: 8.0), 69 | child: Icon(Icons.donut_small, size: fs>32.0, color: themeColor,), 70 | ), 71 | Expanded(child: Container(),), 72 | Padding( 73 | padding: EdgeInsets.only(right: 15.0), 74 | child: Column( 75 | mainAxisAlignment: MainAxisAlignment.center, 76 | children: [ 77 | Text('登录领取', style: TextStyle(color: Color(0xFF817C7C), fontSize: fs>14.0, fontWeight: FontWeight.bold),), 78 | Text('积分会员', style: TextStyle(color: themeColor, fontSize: fs>14.0, fontWeight: FontWeight.bold),), // 79 | ],), 80 | ) 81 | ], 82 | ), 83 | ), 84 | ) 85 | ], 86 | ), 87 | ), 88 | // VIP 89 | Padding( 90 | padding: EdgeInsets.only(left: 15.0, right: 15.0, bottom: 10.0), 91 | child: DecoratedBox( 92 | decoration: BoxDecoration( 93 | gradient: LinearGradient(colors: [Color(0xFFF1BC7F), Color(0xFFFFD39E)],), 94 | borderRadius: BorderRadius.circular(4.0), 95 | ), 96 | child: Container( 97 | height: 50.0, 98 | child: Row( 99 | children: [ 100 | Container(width: 10.0,), 101 | Icon(Icons.person, color: Color(0xFFAC6A2F)), 102 | Container(width: 10.0,), 103 | Expanded( 104 | child: Text( 105 | 'VIP会员', 106 | style:TextStyle(color: Color(0xFFB47238), fontSize: fs>15.0),), 107 | ), 108 | Text( 109 | '精品臻选免费畅听', 110 | style: TextStyle(color: Color(0xFFB47238), fontSize: fs>15.0), 111 | ), 112 | Icon(Icons.arrow_right, color: Color(0xFFAC6A2F), size: fs>24.0,), 113 | Container( 114 | width: fs>15.0, 115 | ) 116 | ], 117 | ), 118 | ), 119 | ), 120 | ), 121 | 122 | // 钱包 123 | Padding( 124 | padding: EdgeInsets.only(left: 15.0, right: 15.0, bottom: 10.0), 125 | child: DecoratedBox( 126 | decoration: BoxDecoration( 127 | color: Colors.white, 128 | borderRadius: BorderRadius.circular(4.0), 129 | boxShadow: [ 130 | BoxShadow( 131 | color: Color(0xFFF3F3F3), 132 | blurRadius: 15.0, 133 | offset: Offset(0, 8.0)) 134 | ]), 135 | child: Container( 136 | height: fs>80.0, 137 | child: Row( 138 | children: ownMap 139 | .map((title, icon) { 140 | return MapEntry( 141 | title, 142 | Expanded( 143 | child: VerticalButton( 144 | title: Text(title, maxLines: 1, style: TextStyle(color: Color(0xFFB5B5B5), fontSize: fs>12.0),), 145 | space: fs>3.0, 146 | icon: icon, 147 | onPressed: () {}, 148 | ), 149 | )); 150 | }) 151 | .values 152 | .toList(), 153 | ), 154 | ), 155 | ), 156 | ), 157 | // 功能 158 | Padding( 159 | padding: EdgeInsets.only(left: 15.0, right: 15.0, bottom: 10.0), 160 | child: DecoratedBox( 161 | decoration: BoxDecoration( 162 | color: Colors.white, 163 | borderRadius: BorderRadius.circular(4.0), 164 | boxShadow: [ 165 | BoxShadow( 166 | color: Color(0xFFF3F3F3), 167 | blurRadius: 15.0, 168 | offset: Offset(0, 8.0)) 169 | ]), 170 | child: Container( 171 | height: fs>80.0, 172 | child: Row( 173 | children: funcMap 174 | .map((title, icon) { 175 | return MapEntry( 176 | title, 177 | Expanded( 178 | child: VerticalButton( 179 | title: Text( 180 | title, maxLines: 1, 181 | style: TextStyle(color: Color(0xFFB5B5B5), fontSize: fs>12.0),), 182 | space: fs>3.0, 183 | icon: icon, 184 | onPressed: () {}, 185 | ), 186 | )); 187 | }) 188 | .values 189 | .toList(), 190 | ), 191 | ), 192 | ), 193 | ) 194 | ], 195 | ); 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /xmlyfm/lib/Modules/Home/Model/home_detail_list.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'home_detail_list.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | HomeDetailList _$HomeDetailListFromJson(Map json) { 10 | return HomeDetailList( 11 | json['albumId'] as int, 12 | json['albumTitle'] as String, 13 | json['commentsCounts'] as int, 14 | json['coverSmall'] as String, 15 | json['createdAt'] as int, 16 | json['duration'] as int, 17 | json['favoritesCounts'] as int, 18 | json['id'] as int, 19 | json['isAuthorized'] as bool, 20 | json['isFree'] as bool, 21 | json['isPaid'] as bool, 22 | json['nickname'] as String, 23 | json['playPath32'] as String, 24 | json['playPath64'] as String, 25 | json['playPathAacv164'] as String, 26 | json['playPathAacv224'] as String, 27 | json['playsCounts'] as int, 28 | json['priceTypeId'] as int, 29 | json['sampleDuration'] as int, 30 | json['sharesCounts'] as int, 31 | json['tags'] as String, 32 | json['title'] as String, 33 | json['trackId'] as int, 34 | json['uid'] as int, 35 | json['updatedAt'] as int, 36 | json['userSource'] as int, 37 | json['contentUpdatedAt'] as int, 38 | json['enableShare'] as bool, 39 | json['isExternalUrl'] as bool, 40 | json['bubbleText'] as String, 41 | json['contentType'] as String, 42 | json['coverPath'] as String, 43 | json['displayClass'] as String, 44 | json['sharePic'] as String, 45 | json['subtitle'] as String, 46 | json['url'] as String, 47 | json['adId'] as int, 48 | json['adType'] as int, 49 | json['buttonShowed'] as bool, 50 | json['clickAction'] as int, 51 | json['clickType'] as int, 52 | json['cover'] as String, 53 | json['description'] as String, 54 | json['displayType'] as int, 55 | json['isAd'] as bool, 56 | json['isInternal'] as int, 57 | json['isLandScape'] as bool, 58 | json['isShareFlag'] as bool, 59 | json['link'] as String, 60 | json['name'] as String, 61 | json['openlinkType'] as int, 62 | json['realLink'] as String, 63 | json['targetId'] as int, 64 | json['categoryId'] as int, 65 | json['commentsCount'] as int, 66 | json['contractStatus'] as int, 67 | json['isFinished'] as int, 68 | json['lastUptrackAt'] as int, 69 | json['originalStatus'] as int, 70 | json['playsCount'] as int, 71 | json['priceTypeEnum'] as int, 72 | json['refundSupportType'] as int, 73 | json['tracksCount'] as int, 74 | json['vipFreeType'] as int, 75 | json['isDraft'] as bool, 76 | json['isFollowing'] as bool, 77 | json['isVipFree'] as bool, 78 | json['subscribeStatus'] as bool, 79 | json['infoType'] as String, 80 | json['materialType'] as String, 81 | json['pic'] as String, 82 | json['recSrc'] as String, 83 | json['recTrack'] as String, 84 | (json['discountedPrice'] as num)?.toDouble(), 85 | (json['price'] as num)?.toDouble(), 86 | (json['commentScore'] as num)?.toDouble(), 87 | (json['vipPrice'] as num)?.toDouble(), 88 | json['displayDiscountedPrice'] as String, 89 | json['displayPrice'] as String, 90 | json['displayVipPrice'] as String, 91 | json['priceUnit'] as String, 92 | json['columnType'] as int, 93 | json['specialId'] as int, 94 | json['footnote'] as String, 95 | json['channelId'] as int, 96 | json['onLineNum'] as int, 97 | json['channelName'] as String, 98 | json['coverRound'] as String, 99 | json['liveStatus'] as int, 100 | json['liveType'] as int, 101 | json['openType'] as int, 102 | json['participationCount'] as int, 103 | json['planLessonCount'] as int, 104 | json['nickName'] as String, 105 | json['actualStartAt'] as int, 106 | json['chatId'] as int, 107 | json['endAt'] as int, 108 | json['playCount'] as int, 109 | json['roomId'] as int, 110 | json['startAt'] as int, 111 | json['status'] as int, 112 | json['categoryName'] as String, 113 | json['coverLarge'] as String, 114 | json['coverMiddle'] as String); 115 | } 116 | 117 | Map _$HomeDetailListToJson(HomeDetailList instance) => 118 | { 119 | 'id': instance.id, 120 | 'title': instance.title, 121 | 'albumId': instance.albumId, 122 | 'albumTitle': instance.albumTitle, 123 | 'commentsCounts': instance.commentsCounts, 124 | 'coverSmall': instance.coverSmall, 125 | 'createdAt': instance.createdAt, 126 | 'duration': instance.duration, 127 | 'favoritesCounts': instance.favoritesCounts, 128 | 'isAuthorized': instance.isAuthorized, 129 | 'isFree': instance.isFree, 130 | 'isPaid': instance.isPaid, 131 | 'nickname': instance.nickname, 132 | 'playPath32': instance.playPath32, 133 | 'playPath64': instance.playPath64, 134 | 'playPathAacv164': instance.playPathAacv164, 135 | 'playPathAacv224': instance.playPathAacv224, 136 | 'playsCounts': instance.playsCounts, 137 | 'priceTypeId': instance.priceTypeId, 138 | 'sampleDuration': instance.sampleDuration, 139 | 'sharesCounts': instance.sharesCounts, 140 | 'tags': instance.tags, 141 | 'trackId': instance.trackId, 142 | 'uid': instance.uid, 143 | 'updatedAt': instance.updatedAt, 144 | 'userSource': instance.userSource, 145 | 'adId': instance.adId, 146 | 'adType': instance.adType, 147 | 'buttonShowed': instance.buttonShowed, 148 | 'clickAction': instance.clickAction, 149 | 'clickType': instance.clickType, 150 | 'cover': instance.cover, 151 | 'description': instance.description, 152 | 'displayType': instance.displayType, 153 | 'isAd': instance.isAd, 154 | 'isInternal': instance.isInternal, 155 | 'isLandScape': instance.isLandScape, 156 | 'isShareFlag': instance.isShareFlag, 157 | 'link': instance.link, 158 | 'name': instance.name, 159 | 'openlinkType': instance.openlinkType, 160 | 'realLink': instance.realLink, 161 | 'targetId': instance.targetId, 162 | 'contentUpdatedAt': instance.contentUpdatedAt, 163 | 'enableShare': instance.enableShare, 164 | 'isExternalUrl': instance.isExternalUrl, 165 | 'bubbleText': instance.bubbleText, 166 | 'contentType': instance.contentType, 167 | 'coverPath': instance.coverPath, 168 | 'displayClass': instance.displayClass, 169 | 'sharePic': instance.sharePic, 170 | 'subtitle': instance.subtitle, 171 | 'url': instance.url, 172 | 'categoryId': instance.categoryId, 173 | 'commentsCount': instance.commentsCount, 174 | 'contractStatus': instance.contractStatus, 175 | 'isFinished': instance.isFinished, 176 | 'lastUptrackAt': instance.lastUptrackAt, 177 | 'originalStatus': instance.originalStatus, 178 | 'playsCount': instance.playsCount, 179 | 'priceTypeEnum': instance.priceTypeEnum, 180 | 'refundSupportType': instance.refundSupportType, 181 | 'tracksCount': instance.tracksCount, 182 | 'vipFreeType': instance.vipFreeType, 183 | 'isDraft': instance.isDraft, 184 | 'isFollowing': instance.isFollowing, 185 | 'isVipFree': instance.isVipFree, 186 | 'subscribeStatus': instance.subscribeStatus, 187 | 'infoType': instance.infoType, 188 | 'materialType': instance.materialType, 189 | 'pic': instance.pic, 190 | 'recSrc': instance.recSrc, 191 | 'recTrack': instance.recTrack, 192 | 'discountedPrice': instance.discountedPrice, 193 | 'price': instance.price, 194 | 'commentScore': instance.commentScore, 195 | 'vipPrice': instance.vipPrice, 196 | 'displayDiscountedPrice': instance.displayDiscountedPrice, 197 | 'displayPrice': instance.displayPrice, 198 | 'displayVipPrice': instance.displayVipPrice, 199 | 'priceUnit': instance.priceUnit, 200 | 'columnType': instance.columnType, 201 | 'specialId': instance.specialId, 202 | 'footnote': instance.footnote, 203 | 'channelId': instance.channelId, 204 | 'onLineNum': instance.onLineNum, 205 | 'channelName': instance.channelName, 206 | 'coverRound': instance.coverRound, 207 | 'liveStatus': instance.liveStatus, 208 | 'liveType': instance.liveType, 209 | 'openType': instance.openType, 210 | 'participationCount': instance.participationCount, 211 | 'planLessonCount': instance.planLessonCount, 212 | 'nickName': instance.nickName, 213 | 'actualStartAt': instance.actualStartAt, 214 | 'chatId': instance.chatId, 215 | 'endAt': instance.endAt, 216 | 'playCount': instance.playCount, 217 | 'roomId': instance.roomId, 218 | 'startAt': instance.startAt, 219 | 'status': instance.status, 220 | 'categoryName': instance.categoryName, 221 | 'coverLarge': instance.coverLarge, 222 | 'coverMiddle': instance.coverMiddle 223 | }; 224 | -------------------------------------------------------------------------------- /xmlyfm/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; }; 12 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 13 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 14 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 15 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 16 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 17 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 18 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 19 | 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 20 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 21 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 22 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 23 | AB2CE2080003C54C0566E61B /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F53C7456767B8A8D6269776 /* libPods-Runner.a */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXCopyFilesBuildPhase section */ 27 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 28 | isa = PBXCopyFilesBuildPhase; 29 | buildActionMask = 2147483647; 30 | dstPath = ""; 31 | dstSubfolderSpec = 10; 32 | files = ( 33 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, 34 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, 35 | ); 36 | name = "Embed Frameworks"; 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXCopyFilesBuildPhase section */ 40 | 41 | /* Begin PBXFileReference section */ 42 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 43 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 44 | 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; }; 45 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 46 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 47 | 44FD7DD48FE632E5B4C7D5D7 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 48 | 5F53C7456767B8A8D6269776 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | 6E64FBD07E3E40EBDFD59012 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 50 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 51 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 52 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 53 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 54 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 55 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 56 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 58 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 59 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 60 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 61 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 62 | D6A605807635990FBC73B595 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 63 | /* End PBXFileReference section */ 64 | 65 | /* Begin PBXFrameworksBuildPhase section */ 66 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 67 | isa = PBXFrameworksBuildPhase; 68 | buildActionMask = 2147483647; 69 | files = ( 70 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 71 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, 72 | AB2CE2080003C54C0566E61B /* libPods-Runner.a in Frameworks */, 73 | ); 74 | runOnlyForDeploymentPostprocessing = 0; 75 | }; 76 | /* End PBXFrameworksBuildPhase section */ 77 | 78 | /* Begin PBXGroup section */ 79 | 109A49AA81C415D2059D68ED /* Pods */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | D6A605807635990FBC73B595 /* Pods-Runner.debug.xcconfig */, 83 | 6E64FBD07E3E40EBDFD59012 /* Pods-Runner.release.xcconfig */, 84 | 44FD7DD48FE632E5B4C7D5D7 /* Pods-Runner.profile.xcconfig */, 85 | ); 86 | name = Pods; 87 | path = Pods; 88 | sourceTree = ""; 89 | }; 90 | 28A119A589EAE7EAD4B5A270 /* Frameworks */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 5F53C7456767B8A8D6269776 /* libPods-Runner.a */, 94 | ); 95 | name = Frameworks; 96 | sourceTree = ""; 97 | }; 98 | 9740EEB11CF90186004384FC /* Flutter */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | 2D5378251FAA1A9400D5DBA9 /* flutter_assets */, 102 | 3B80C3931E831B6300D905FE /* App.framework */, 103 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 104 | 9740EEBA1CF902C7004384FC /* Flutter.framework */, 105 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 106 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 107 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 108 | ); 109 | name = Flutter; 110 | sourceTree = ""; 111 | }; 112 | 97C146E51CF9000F007C117D = { 113 | isa = PBXGroup; 114 | children = ( 115 | 9740EEB11CF90186004384FC /* Flutter */, 116 | 97C146F01CF9000F007C117D /* Runner */, 117 | 97C146EF1CF9000F007C117D /* Products */, 118 | 109A49AA81C415D2059D68ED /* Pods */, 119 | 28A119A589EAE7EAD4B5A270 /* Frameworks */, 120 | ); 121 | sourceTree = ""; 122 | }; 123 | 97C146EF1CF9000F007C117D /* Products */ = { 124 | isa = PBXGroup; 125 | children = ( 126 | 97C146EE1CF9000F007C117D /* Runner.app */, 127 | ); 128 | name = Products; 129 | sourceTree = ""; 130 | }; 131 | 97C146F01CF9000F007C117D /* Runner */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, 135 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 136 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 137 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 138 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 139 | 97C147021CF9000F007C117D /* Info.plist */, 140 | 97C146F11CF9000F007C117D /* Supporting Files */, 141 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 142 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 143 | ); 144 | path = Runner; 145 | sourceTree = ""; 146 | }; 147 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | 97C146F21CF9000F007C117D /* main.m */, 151 | ); 152 | name = "Supporting Files"; 153 | sourceTree = ""; 154 | }; 155 | /* End PBXGroup section */ 156 | 157 | /* Begin PBXNativeTarget section */ 158 | 97C146ED1CF9000F007C117D /* Runner */ = { 159 | isa = PBXNativeTarget; 160 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 161 | buildPhases = ( 162 | 53ABC2889DFEF99112901778 /* [CP] Check Pods Manifest.lock */, 163 | 9740EEB61CF901F6004384FC /* Run Script */, 164 | 97C146EA1CF9000F007C117D /* Sources */, 165 | 97C146EB1CF9000F007C117D /* Frameworks */, 166 | 97C146EC1CF9000F007C117D /* Resources */, 167 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 168 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 169 | 05AE24404834919C87933FD8 /* [CP] Embed Pods Frameworks */, 170 | ); 171 | buildRules = ( 172 | ); 173 | dependencies = ( 174 | ); 175 | name = Runner; 176 | productName = Runner; 177 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 178 | productType = "com.apple.product-type.application"; 179 | }; 180 | /* End PBXNativeTarget section */ 181 | 182 | /* Begin PBXProject section */ 183 | 97C146E61CF9000F007C117D /* Project object */ = { 184 | isa = PBXProject; 185 | attributes = { 186 | LastUpgradeCheck = 0910; 187 | ORGANIZATIONNAME = "The Chromium Authors"; 188 | TargetAttributes = { 189 | 97C146ED1CF9000F007C117D = { 190 | CreatedOnToolsVersion = 7.3.1; 191 | }; 192 | }; 193 | }; 194 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 195 | compatibilityVersion = "Xcode 3.2"; 196 | developmentRegion = English; 197 | hasScannedForEncodings = 0; 198 | knownRegions = ( 199 | en, 200 | Base, 201 | ); 202 | mainGroup = 97C146E51CF9000F007C117D; 203 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 204 | projectDirPath = ""; 205 | projectRoot = ""; 206 | targets = ( 207 | 97C146ED1CF9000F007C117D /* Runner */, 208 | ); 209 | }; 210 | /* End PBXProject section */ 211 | 212 | /* Begin PBXResourcesBuildPhase section */ 213 | 97C146EC1CF9000F007C117D /* Resources */ = { 214 | isa = PBXResourcesBuildPhase; 215 | buildActionMask = 2147483647; 216 | files = ( 217 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 218 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 219 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 220 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 221 | 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */, 222 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 223 | ); 224 | runOnlyForDeploymentPostprocessing = 0; 225 | }; 226 | /* End PBXResourcesBuildPhase section */ 227 | 228 | /* Begin PBXShellScriptBuildPhase section */ 229 | 05AE24404834919C87933FD8 /* [CP] Embed Pods Frameworks */ = { 230 | isa = PBXShellScriptBuildPhase; 231 | buildActionMask = 2147483647; 232 | files = ( 233 | ); 234 | inputFileListPaths = ( 235 | ); 236 | inputPaths = ( 237 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", 238 | "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework", 239 | ); 240 | name = "[CP] Embed Pods Frameworks"; 241 | outputFileListPaths = ( 242 | ); 243 | outputPaths = ( 244 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", 245 | ); 246 | runOnlyForDeploymentPostprocessing = 0; 247 | shellPath = /bin/sh; 248 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; 249 | showEnvVarsInLog = 0; 250 | }; 251 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 252 | isa = PBXShellScriptBuildPhase; 253 | buildActionMask = 2147483647; 254 | files = ( 255 | ); 256 | inputPaths = ( 257 | ); 258 | name = "Thin Binary"; 259 | outputPaths = ( 260 | ); 261 | runOnlyForDeploymentPostprocessing = 0; 262 | shellPath = /bin/sh; 263 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; 264 | }; 265 | 53ABC2889DFEF99112901778 /* [CP] Check Pods Manifest.lock */ = { 266 | isa = PBXShellScriptBuildPhase; 267 | buildActionMask = 2147483647; 268 | files = ( 269 | ); 270 | inputFileListPaths = ( 271 | ); 272 | inputPaths = ( 273 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 274 | "${PODS_ROOT}/Manifest.lock", 275 | ); 276 | name = "[CP] Check Pods Manifest.lock"; 277 | outputFileListPaths = ( 278 | ); 279 | outputPaths = ( 280 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", 281 | ); 282 | runOnlyForDeploymentPostprocessing = 0; 283 | shellPath = /bin/sh; 284 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 285 | showEnvVarsInLog = 0; 286 | }; 287 | 9740EEB61CF901F6004384FC /* Run Script */ = { 288 | isa = PBXShellScriptBuildPhase; 289 | buildActionMask = 2147483647; 290 | files = ( 291 | ); 292 | inputPaths = ( 293 | ); 294 | name = "Run Script"; 295 | outputPaths = ( 296 | ); 297 | runOnlyForDeploymentPostprocessing = 0; 298 | shellPath = /bin/sh; 299 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 300 | }; 301 | /* End PBXShellScriptBuildPhase section */ 302 | 303 | /* Begin PBXSourcesBuildPhase section */ 304 | 97C146EA1CF9000F007C117D /* Sources */ = { 305 | isa = PBXSourcesBuildPhase; 306 | buildActionMask = 2147483647; 307 | files = ( 308 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, 309 | 97C146F31CF9000F007C117D /* main.m in Sources */, 310 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 311 | ); 312 | runOnlyForDeploymentPostprocessing = 0; 313 | }; 314 | /* End PBXSourcesBuildPhase section */ 315 | 316 | /* Begin PBXVariantGroup section */ 317 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 318 | isa = PBXVariantGroup; 319 | children = ( 320 | 97C146FB1CF9000F007C117D /* Base */, 321 | ); 322 | name = Main.storyboard; 323 | sourceTree = ""; 324 | }; 325 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 326 | isa = PBXVariantGroup; 327 | children = ( 328 | 97C147001CF9000F007C117D /* Base */, 329 | ); 330 | name = LaunchScreen.storyboard; 331 | sourceTree = ""; 332 | }; 333 | /* End PBXVariantGroup section */ 334 | 335 | /* Begin XCBuildConfiguration section */ 336 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 337 | isa = XCBuildConfiguration; 338 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 339 | buildSettings = { 340 | ALWAYS_SEARCH_USER_PATHS = NO; 341 | CLANG_ANALYZER_NONNULL = YES; 342 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 343 | CLANG_CXX_LIBRARY = "libc++"; 344 | CLANG_ENABLE_MODULES = YES; 345 | CLANG_ENABLE_OBJC_ARC = YES; 346 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 347 | CLANG_WARN_BOOL_CONVERSION = YES; 348 | CLANG_WARN_COMMA = YES; 349 | CLANG_WARN_CONSTANT_CONVERSION = YES; 350 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 351 | CLANG_WARN_EMPTY_BODY = YES; 352 | CLANG_WARN_ENUM_CONVERSION = YES; 353 | CLANG_WARN_INFINITE_RECURSION = YES; 354 | CLANG_WARN_INT_CONVERSION = YES; 355 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 356 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 357 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 358 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 359 | CLANG_WARN_STRICT_PROTOTYPES = YES; 360 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 361 | CLANG_WARN_UNREACHABLE_CODE = YES; 362 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 363 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 364 | COPY_PHASE_STRIP = NO; 365 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 366 | ENABLE_NS_ASSERTIONS = NO; 367 | ENABLE_STRICT_OBJC_MSGSEND = YES; 368 | GCC_C_LANGUAGE_STANDARD = gnu99; 369 | GCC_NO_COMMON_BLOCKS = YES; 370 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 371 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 372 | GCC_WARN_UNDECLARED_SELECTOR = YES; 373 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 374 | GCC_WARN_UNUSED_FUNCTION = YES; 375 | GCC_WARN_UNUSED_VARIABLE = YES; 376 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 377 | MTL_ENABLE_DEBUG_INFO = NO; 378 | SDKROOT = iphoneos; 379 | TARGETED_DEVICE_FAMILY = "1,2"; 380 | VALIDATE_PRODUCT = YES; 381 | }; 382 | name = Profile; 383 | }; 384 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 385 | isa = XCBuildConfiguration; 386 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 387 | buildSettings = { 388 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 389 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 390 | DEVELOPMENT_TEAM = S8QB4VV633; 391 | ENABLE_BITCODE = NO; 392 | FRAMEWORK_SEARCH_PATHS = ( 393 | "$(inherited)", 394 | "$(PROJECT_DIR)/Flutter", 395 | ); 396 | INFOPLIST_FILE = Runner/Info.plist; 397 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 398 | LIBRARY_SEARCH_PATHS = ( 399 | "$(inherited)", 400 | "$(PROJECT_DIR)/Flutter", 401 | ); 402 | PRODUCT_BUNDLE_IDENTIFIER = com.linxunfeng.xmlyfm; 403 | PRODUCT_NAME = "$(TARGET_NAME)"; 404 | VERSIONING_SYSTEM = "apple-generic"; 405 | }; 406 | name = Profile; 407 | }; 408 | 97C147031CF9000F007C117D /* Debug */ = { 409 | isa = XCBuildConfiguration; 410 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 411 | buildSettings = { 412 | ALWAYS_SEARCH_USER_PATHS = NO; 413 | CLANG_ANALYZER_NONNULL = YES; 414 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 415 | CLANG_CXX_LIBRARY = "libc++"; 416 | CLANG_ENABLE_MODULES = YES; 417 | CLANG_ENABLE_OBJC_ARC = YES; 418 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 419 | CLANG_WARN_BOOL_CONVERSION = YES; 420 | CLANG_WARN_COMMA = YES; 421 | CLANG_WARN_CONSTANT_CONVERSION = YES; 422 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 423 | CLANG_WARN_EMPTY_BODY = YES; 424 | CLANG_WARN_ENUM_CONVERSION = YES; 425 | CLANG_WARN_INFINITE_RECURSION = YES; 426 | CLANG_WARN_INT_CONVERSION = YES; 427 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 428 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 429 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 430 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 431 | CLANG_WARN_STRICT_PROTOTYPES = YES; 432 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 433 | CLANG_WARN_UNREACHABLE_CODE = YES; 434 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 435 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 436 | COPY_PHASE_STRIP = NO; 437 | DEBUG_INFORMATION_FORMAT = dwarf; 438 | ENABLE_STRICT_OBJC_MSGSEND = YES; 439 | ENABLE_TESTABILITY = YES; 440 | GCC_C_LANGUAGE_STANDARD = gnu99; 441 | GCC_DYNAMIC_NO_PIC = NO; 442 | GCC_NO_COMMON_BLOCKS = YES; 443 | GCC_OPTIMIZATION_LEVEL = 0; 444 | GCC_PREPROCESSOR_DEFINITIONS = ( 445 | "DEBUG=1", 446 | "$(inherited)", 447 | ); 448 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 449 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 450 | GCC_WARN_UNDECLARED_SELECTOR = YES; 451 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 452 | GCC_WARN_UNUSED_FUNCTION = YES; 453 | GCC_WARN_UNUSED_VARIABLE = YES; 454 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 455 | MTL_ENABLE_DEBUG_INFO = YES; 456 | ONLY_ACTIVE_ARCH = YES; 457 | SDKROOT = iphoneos; 458 | TARGETED_DEVICE_FAMILY = "1,2"; 459 | }; 460 | name = Debug; 461 | }; 462 | 97C147041CF9000F007C117D /* Release */ = { 463 | isa = XCBuildConfiguration; 464 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 465 | buildSettings = { 466 | ALWAYS_SEARCH_USER_PATHS = NO; 467 | CLANG_ANALYZER_NONNULL = YES; 468 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 469 | CLANG_CXX_LIBRARY = "libc++"; 470 | CLANG_ENABLE_MODULES = YES; 471 | CLANG_ENABLE_OBJC_ARC = YES; 472 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 473 | CLANG_WARN_BOOL_CONVERSION = YES; 474 | CLANG_WARN_COMMA = YES; 475 | CLANG_WARN_CONSTANT_CONVERSION = YES; 476 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 477 | CLANG_WARN_EMPTY_BODY = YES; 478 | CLANG_WARN_ENUM_CONVERSION = YES; 479 | CLANG_WARN_INFINITE_RECURSION = YES; 480 | CLANG_WARN_INT_CONVERSION = YES; 481 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 482 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 483 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 484 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 485 | CLANG_WARN_STRICT_PROTOTYPES = YES; 486 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 487 | CLANG_WARN_UNREACHABLE_CODE = YES; 488 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 489 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 490 | COPY_PHASE_STRIP = NO; 491 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 492 | ENABLE_NS_ASSERTIONS = NO; 493 | ENABLE_STRICT_OBJC_MSGSEND = YES; 494 | GCC_C_LANGUAGE_STANDARD = gnu99; 495 | GCC_NO_COMMON_BLOCKS = YES; 496 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 497 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 498 | GCC_WARN_UNDECLARED_SELECTOR = YES; 499 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 500 | GCC_WARN_UNUSED_FUNCTION = YES; 501 | GCC_WARN_UNUSED_VARIABLE = YES; 502 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 503 | MTL_ENABLE_DEBUG_INFO = NO; 504 | SDKROOT = iphoneos; 505 | TARGETED_DEVICE_FAMILY = "1,2"; 506 | VALIDATE_PRODUCT = YES; 507 | }; 508 | name = Release; 509 | }; 510 | 97C147061CF9000F007C117D /* Debug */ = { 511 | isa = XCBuildConfiguration; 512 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 513 | buildSettings = { 514 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 515 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 516 | ENABLE_BITCODE = NO; 517 | FRAMEWORK_SEARCH_PATHS = ( 518 | "$(inherited)", 519 | "$(PROJECT_DIR)/Flutter", 520 | ); 521 | INFOPLIST_FILE = Runner/Info.plist; 522 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 523 | LIBRARY_SEARCH_PATHS = ( 524 | "$(inherited)", 525 | "$(PROJECT_DIR)/Flutter", 526 | ); 527 | PRODUCT_BUNDLE_IDENTIFIER = com.linxunfeng.xmlyfm; 528 | PRODUCT_NAME = "$(TARGET_NAME)"; 529 | VERSIONING_SYSTEM = "apple-generic"; 530 | }; 531 | name = Debug; 532 | }; 533 | 97C147071CF9000F007C117D /* Release */ = { 534 | isa = XCBuildConfiguration; 535 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 536 | buildSettings = { 537 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 538 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 539 | ENABLE_BITCODE = NO; 540 | FRAMEWORK_SEARCH_PATHS = ( 541 | "$(inherited)", 542 | "$(PROJECT_DIR)/Flutter", 543 | ); 544 | INFOPLIST_FILE = Runner/Info.plist; 545 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 546 | LIBRARY_SEARCH_PATHS = ( 547 | "$(inherited)", 548 | "$(PROJECT_DIR)/Flutter", 549 | ); 550 | PRODUCT_BUNDLE_IDENTIFIER = com.linxunfeng.xmlyfm; 551 | PRODUCT_NAME = "$(TARGET_NAME)"; 552 | VERSIONING_SYSTEM = "apple-generic"; 553 | }; 554 | name = Release; 555 | }; 556 | /* End XCBuildConfiguration section */ 557 | 558 | /* Begin XCConfigurationList section */ 559 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 560 | isa = XCConfigurationList; 561 | buildConfigurations = ( 562 | 97C147031CF9000F007C117D /* Debug */, 563 | 97C147041CF9000F007C117D /* Release */, 564 | 249021D3217E4FDB00AE95B9 /* Profile */, 565 | ); 566 | defaultConfigurationIsVisible = 0; 567 | defaultConfigurationName = Release; 568 | }; 569 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 570 | isa = XCConfigurationList; 571 | buildConfigurations = ( 572 | 97C147061CF9000F007C117D /* Debug */, 573 | 97C147071CF9000F007C117D /* Release */, 574 | 249021D4217E4FDB00AE95B9 /* Profile */, 575 | ); 576 | defaultConfigurationIsVisible = 0; 577 | defaultConfigurationName = Release; 578 | }; 579 | /* End XCConfigurationList section */ 580 | }; 581 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 582 | } 583 | --------------------------------------------------------------------------------