版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】使用Flutter開(kāi)發(fā)一款電影APP的示例
在下給大家分享一下使用Flutter開(kāi)發(fā)一款電影APP的示例,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!前言使用Flutter開(kāi)發(fā)一款A(yù)pp是一件非常愉快的事情,其出色的性能、跨多端以及數(shù)量眾多的原生組件都是我們選擇Flutter的理由!今天我們就來(lái)使用Flutter開(kāi)發(fā)一款電影類的App,先看下App的截圖。從main.dart開(kāi)始在Flutter里main.dart是應(yīng)用開(kāi)始的地方:import
'package:flutter/material.dart';
import
'package:movie/utils/router.dart'
as
router;
void
main()
=>
runApp(MyApp());
class
MyApp
extends
StatelessWidget
{
//
This
widget
is
the
root
of
your
application.
@override
Widget
build(BuildContext
context)
{
return
MaterialApp(
debugShowCheckedModeBanner:
false,
title:
'電影',
theme:
ThemeData(
primarySwatch:
Colors.blue,
),
onGenerateRoute:
router.generateRoute,
initialRoute:
'/',
);
}
}一般的,在Flutter中管理路由有兩種方式,一種是直接使用Navigator.of(context).push(),這種方式比較適合非常簡(jiǎn)單的應(yīng)用,隨著應(yīng)用的不斷發(fā)展,邏輯越來(lái)越多,推薦使用具名路由來(lái)管理應(yīng)用,本文也是使用的這種方式。直接將路由掛在MaterialApp的onGenerateRoute字段上即可,具體的路由定義放在了單獨(dú)的文件中進(jìn)行管理utils/router.dart:import
'package:flutter/material.dart';
import
'package:movie/screens/home.dart';
import
'package:movie/screens/detail.dart';
import
'package:movie/screens/videoPlayer.dart';
Route<dynamic>
generateRoute(RouteSettings
settings)
{
switch
()
{
case
'/':
return
MaterialPageRoute(builder:
(context)
=>
Home());
case
'detail':
var
arguments
=
settings.arguments;
return
MaterialPageRoute(
builder:
(context)
=>
MovieDetail(id:
arguments));
case
'video':
var
arguments
=
settings.arguments;
return
MaterialPageRoute(
builder:
(context)
=>
VideoPage(url:
arguments));
default:
return
MaterialPageRoute(builder:
(context)
=>
Home());
}
}真是像極了前端的路由定義,先將組件import進(jìn)來(lái),然后在各自的路由中return即可。首頁(yè)在首頁(yè)中使用TabBar來(lái)展示"正在熱映"和"TOP250":import
'package:flutter/material.dart';
import
'package:movie/screens/hot.dart';
class
Home
extends
StatefulWidget
{
Home({Key
key})
:
super(key:
key);
_HomeState
createState()
=>
_HomeState();
}
class
_HomeState
extends
State<Home>
with
SingleTickerProviderStateMixin
{
TabController
_tabController;
@override
void
initState()
{
super.initState();
_tabController
=
TabController(vsync:
this,
initialIndex:
0,
length:
2);
}
@override
Widget
build(BuildContext
context)
{
return
Scaffold(
appBar:
AppBar(
title:
TabBar(
controller:
_tabController,
tabs:
<Widget>[
Tab(text:
'正在熱映'),
Tab(text:
'TOP250'),
],
),
),
body:
TabBarView(
controller:
_tabController,
children:
<Widget>[
Hot(),
Hot(history:
true),
],
),
);
}
}兩個(gè)頁(yè)面的布局是一樣的,只有數(shù)據(jù)是不同的,所以我們復(fù)用這個(gè)頁(yè)面Hot,傳入history參數(shù)來(lái)代表是否為T(mén)op250頁(yè)面復(fù)用的Hot組件在這個(gè)組件中,通過(guò)history字段來(lái)區(qū)分成兩個(gè)頁(yè)面。在頁(yè)面initState的生命周期中,請(qǐng)求數(shù)據(jù),再進(jìn)行相應(yīng)的展示。下拉刷新的功能是使用的RefreshIndicator組件,在其onRefresh中進(jìn)行下拉時(shí)的邏輯處理。Flutter沒(méi)有直接提供上拉加載的組件,但是也是很容易實(shí)現(xiàn),通過(guò)ListView的controller來(lái)做判斷即可:當(dāng)前滾動(dòng)的位置是否到達(dá)最大滾動(dòng)位置_scrollController.position.pixels==_scrollController.position.maxScrollExtent為了獲得良好的用戶體驗(yàn),Tab來(lái)回切換的時(shí)候,我們不希望頁(yè)面重新渲染,F(xiàn)lutter提供了混入類AutomaticKeepAliveClientMixin,重載wantKeepAlive即可,下面是完整的代碼:import
'package:flutter/material.dart';
import
'package:movie/utils/api.dart'
as
api;
import
'package:movie/widgets/movieItem.dart';
class
Hot
extends
StatefulWidget
{
final
bool
history;
Hot({Key
key,
this.history
=
false})
:
super(key:
key);
_HotState
createState()
=>
_HotState();
}
class
_HotState
extends
State<Hot>
with
AutomaticKeepAliveClientMixin
{
List
_movieList
=
[];
int
start
=
0;
int
total
=
0;
ScrollController
_scrollController
=
ScrollController();
@override
void
initState()
{
super.initState();
_scrollController.addListener(()
{
if
(_scrollController.position.pixels
==
_scrollController.position.maxScrollExtent)
{
getMore();
}
});
this.query(init:
true);
}
query({bool
init
=
false})
async
{
Map
res
=
await
api.getMovieList(
history:
widget.history,
start:
init
?
0
:
this.start);
var
start
=
res['start'];
var
total
=
res['total'];
var
subjects
=
res['subjects'];
setState(()
{
if
(init)
{
this._movieList
=
subjects;
}
else
{
this._movieList.addAll(subjects);
}
this.start
=
start
+
10;
this.total
=
total;
});
}
Future<Null>
_onRefresh()
async
{
await
this.query(init:
true);
}
getMore()
{
if
(start
<
total)
{
query();
}
}
@override
bool
get
wantKeepAlive
=>
true;
@override
Widget
build(BuildContext
context)
{
super.build(context);
return
RefreshIndicator(
onRefresh:
_onRefresh,
child:
ListView.builder(
controller:
_scrollController,
itemCount:
this._movieList.length,
itemBuilder:
(BuildContext
context,
int
index)
=>
MovieItem(data:
this._movieList[index]),
),
);
}
}電影的詳情頁(yè)面點(diǎn)擊單條電影時(shí)使用Navigator.pushNamed(context,'detail',arguments:data['id']);即可跳轉(zhuǎn)詳情頁(yè),在詳情頁(yè)中通過(guò)id再請(qǐng)求接口獲取詳情:import
'package:flutter/material.dart';
import
'package:movie/widgets/detail/detailTop.dart';
import
'package:movie/widgets/detail/rateing.dart';
import
'package:movie/widgets/detail/actors.dart';
import
'package:movie/widgets/detail/photos.dart';
import
'package:movie/widgets/detail/comments.dart';
import
'package:movie/utils/api.dart'
as
api;
class
MovieDetail
extends
StatefulWidget
{
final
id;
MovieDetail({Key
key,
this.id})
:
super(key:
key);
_MovieDetailState
createState()
=>
_MovieDetailState();
}
class
_MovieDetailState
extends
State<MovieDetail>
{
var
_data
=
{};
@override
void
initState()
{
super.initState();
this.init();
}
init()
async
{
var
res
=
await
api.getMovieDetail(widget.id);
setState(()
{
_data
=
res;
});
}
@override
Widget
build(BuildContext
context)
{
return
Scaffold(
body:
_data.isEmpty
?
Center(child:
CircularProgressIndicator(),)
:
SafeArea(
child:
Container(
height:
MediaQuery.of(context).size.height,
width:
MediaQuery.of(context).size.width,
child:
ListView(
scrollDirection:
Axis.vertical,
children:
<Widget>[
MovieDetailTop(data:
_data),
Rate(count:
_data['ratings_count'],
rating:
_data['rating']),
Container(padding:
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度商業(yè)綜合體店鋪裝修一體化服務(wù)合同
- 2025年度草莓種植與深加工一體化項(xiàng)目合同3篇
- 課題申報(bào)參考:南嶺走廊瑤族傳統(tǒng)建筑壁畫(huà)圖像敘事及活化研究
- 課題申報(bào)參考:面向患者情緒體驗(yàn)的大型醫(yī)療設(shè)備系統(tǒng)設(shè)計(jì)策略研究
- 課題申報(bào)參考:貿(mào)易面向型人工智能規(guī)則的發(fā)展及其特征研究
- 《短視頻編劇:選題構(gòu)想+腳本制作+劇本策劃+鏡頭拍攝》課件全套 第1-11章 選題方向:從賬號(hào)定位出發(fā) - 綜合案例:短劇《錯(cuò)過(guò)》
- 二零二五年度車輛抵押借款合同(含提前還款)4篇
- 二零二五版金融科技項(xiàng)目?jī)?nèi)部股東轉(zhuǎn)讓合同4篇
- 二零二五年度工業(yè)級(jí)模具開(kāi)模設(shè)計(jì)與制造合同3篇
- 2025年度新型個(gè)人汽車抵押借款合同范本
- 非ST段抬高型急性冠脈綜合征診斷和治療指南(2024)解讀
- 煤礦反三違培訓(xùn)課件
- 向流程設(shè)計(jì)要效率
- 安全文明施工的管理要點(diǎn)
- 2024年中國(guó)航空發(fā)動(dòng)機(jī)集團(tuán)招聘筆試參考題庫(kù)含答案解析
- 當(dāng)代中外公司治理典型案例剖析(中科院研究生課件)
- 動(dòng)力管道設(shè)計(jì)手冊(cè)-第2版
- 2022年重慶市中考物理試卷A卷(附答案)
- Python繪圖庫(kù)Turtle詳解(含豐富示例)
- 煤礦機(jī)電設(shè)備檢修技術(shù)規(guī)范完整版
- 榆林200MWp并網(wǎng)光伏發(fā)電項(xiàng)目可行性研究報(bào)告
評(píng)論
0/150
提交評(píng)論