AndroidStudio
から入ってCreate New Flutter Project
を選択し、エディタ(vsCode)で開きます。main.dart
を開いたらRun and Debug
を押します。
ios
を選択してFlutter Demo Home Page
が出てきたら準備完了です。
Text
を取り除いて、試しに再生アイコンを作ってみます。
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IconButton(
iconSize: 45.0,
color: Colors.black,
onPressed: () {},
icon: Icon(
Icons.skip_previous,
),
),
IconButton(
iconSize: 62.0,
color: Colors.black,
onPressed: () {},
icon: Icon(
Icons.play_arrow,
),
),
IconButton(
iconSize: 45.0,
color: Colors.black,
onPressed: () {},
icon: Icon(
Icons.skip_next,
),
),
],
),
実行してみると!?
やる気出てきました!
次に、ポッドキャストのiTunesUPodcast
のRSS/XML
フィードを取得してみます。pubspec.yaml
にhttp: ^0.13.3
とxml* ^5.1.2
を加えて、main.dart
に以下を記述します。
import 'package:http/http.dart' as http;
import 'package:xml/xml.dart';
@override
void initState() {
// アプリを起動時に一度だけ実行
super.initState();
Future(() async{
var url = Uri.parse('http://www.nhk.or.jp/rj/podcast/rss/english.xml');
print(await http.read(url));
var response = await http.read(url);
var document = XmlDocument.parse(response);
final enclosures = document.findAllElements('enclosure');
print(enclosures);
enclosures.first.getAttribute("url");
print(enclosures.first.getAttribute("url"));
});
}
実行してDEBUG CONSOLE
を見てみると!それらしき物が取得できています!
pubspec.yaml
にvideo_player
パッケージのVersion 2.0.2
を入れます。
ルート直下に、assets
ディレクトリを作りイメージ画像をドラッグ&ドロップで入れます。これは後に使用する為の画像です!
pubspec.yaml
のflutter:
内、uses-material-design: true
の下にassets: - assets/
を書きます。
lib
ディレクトリのmain.dart
を書き替えてとりあえず再生出来るようにうして行きます。
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:xml/xml.dart';
import 'package:video_player/video_player.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late VideoPlayerController _controller;
@override
void initState() {
// アプリを起動時に一度だけ実行
super.initState();
Future(() async {
var url = Uri.parse('http://www.nhk.or.jp/rj/podcast/rss/english.xml');
// print(await http.read(url));
var response = await http.read(url);
var document = XmlDocument.parse(response);
final enclosures = document.findAllElements('enclosure');
// print(enclosures);
enclosures.first.getAttribute("url");
print(enclosures.first.getAttribute("url"));
_controller = VideoPlayerController.network(
(enclosures.first.getAttribute("url")).toString());
_controller.initialize().then((_) {
setState(() {});
});
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: EdgeInsets.all(16),
child: Icon(Icons.music_video, size: 256),
),
VideoProgressIndicator(
_controller,
allowScrubbing: true,
),
_ProgressText(controller: _controller),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
IconButton(
onPressed: () {
_controller
.seekTo(Duration.zero)
.then((_) => _controller.play());
},
icon: Icon(Icons.refresh),
),
IconButton(
onPressed: () {
_controller.play();
},
icon: Icon(Icons.play_arrow),
),
IconButton(
onPressed: () {
_controller.pause();
},
icon: Icon(Icons.pause),
),
],
),
],
),
);
}
}
class _ProgressText extends StatefulWidget {
final VideoPlayerController controller;
const _ProgressText({
Key? key,
required this.controller,
}) : super(key: key);
@override
__ProgressTextState createState() => __ProgressTextState();
}
class __ProgressTextState extends State<_ProgressText> {
late VoidCallback _listener;
__ProgressTextState() {
_listener = () {
setState(() {});
};
}
@override
void initState() {
super.initState();
widget.controller.addListener(_listener);
}
@override
void deactivate() {
widget.controller.removeListener(_listener);
super.deactivate();
}
@override
Widget build(BuildContext context) {
final String position = widget.controller.value.position.toString();
final String duration = widget.controller.value.duration.toString();
return Text('$position / $duration');
}
}
それらしいのが作成出来ました。参照にさせて頂いたURL貼らせて頂きます。
Fultterで始めるアプリ開発「音楽・動画を再生する」
しっかりと再生出来ました!
ただ、これだと思っていたものと違うので装飾していきます。
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:xml/xml.dart';
import 'package:video_player/video_player.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
//アプリケーションのルートウィジェット
@override
Widget build(BuildContext context) {
return MaterialApp(
//こちらをfalseにすることでデバッグを消せます
debugShowCheckedModeBanner: false,
home: MyHomePage(title: ''),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late VideoPlayerController _controller;
//最初は再生させない
bool playing = false;
//再生ボタンアイコン
IconData playBtn = Icons.play_arrow;
//オブジェクトの宣言
Duration position = new Duration();
Duration musicLength = new Duration();
//プレーヤーの初期化
@override
void initState() {
// アプリを起動時に一度だけ実行
super.initState();
Future(() async {
var url = Uri.parse('http://www.nhk.or.jp/rj/podcast/rss/english.xml');
// print(await http.read(url));
var response = await http.read(url);
var document = XmlDocument.parse(response);
final enclosures = document.findAllElements('enclosure');
// print(enclosures);
enclosures.first.getAttribute("url");
print(enclosures.first.getAttribute("url"));
_controller = VideoPlayerController.network(
(enclosures.first.getAttribute("url")).toString());
_controller.initialize().then((_) {
setState(() {});
});
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
//メイン画面
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Colors.green.shade800,
Colors.green.shade200,
]),
),
child: Padding(
padding: EdgeInsets.only(
top: 48.0,
),
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(left: 12.0),
child: Text(
"NHK WORLD RADIO JAPAN",
style: TextStyle(
color: Colors.white,
fontSize: 38.0,
fontWeight: FontWeight.bold,
),
),
),
Padding(
padding: EdgeInsets.only(left: 12.0),
child: Text(
"This is the latest news in English from NHK WORLD RADIO JAPAN.",
style: TextStyle(
color: Colors.white,
fontSize: 24.0,
fontWeight: FontWeight.w400,
),
),
),
SizedBox(
height: 24.0,
),
//こちらでアセッツに入れた画像を使います
Center(
child:Container(
width: 280.0,
height: 280.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
image: DecorationImage(
image: AssetImage("assets/image.jpg"),
)),
),
),
SizedBox(
height: 18.0,
),
Center(
child: Text(
"English News",
style: TextStyle(
color: Colors.white,
fontSize: 32.0,
fontWeight: FontWeight.w600,
),
),
),
SizedBox(
height: 30.0,
),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30.0),
topRight: Radius.circular(30.0),
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
//プログレスバーを表示
VideoProgressIndicator(
_controller,
allowScrubbing: true,
),
_ProgressText(controller: _controller),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
IconButton(
iconSize: 62.0,
color: Colors.blue,
onPressed: () {
//再生ボタンの機能追加、停止の場合は音を止める
if (!playing) {
_controller.play();
setState(() {
playBtn = Icons.pause;
playing = true;
});
} else {
_controller.pause();
setState(() {
playBtn = Icons.play_arrow;
playing = false;
});
}
},
icon: Icon(
playBtn,
),
),
//リロード
IconButton(
iconSize: 62.0,
color: Colors.red,
onPressed: () {
_controller
.seekTo(Duration.zero)
.then((_) => _controller.pause());
},
icon: Icon(Icons.refresh),
),
],
),
],
),
))
]
)
)
)
)
);
}
}
//現在の再生時間を表示する
class _ProgressText extends StatefulWidget {
final VideoPlayerController controller;
const _ProgressText({
Key? key,
required this.controller,
}) : super(key: key);
@override
__ProgressTextState createState() => __ProgressTextState();
}
class __ProgressTextState extends State<_ProgressText> {
late VoidCallback _listener;
__ProgressTextState() {
_listener = () {
setState(() {});
};
}
@override
void initState() {
super.initState();
widget.controller.addListener(_listener);
}
@override
void deactivate() {
widget.controller.removeListener(_listener);
super.deactivate();
}
@override
Widget build(BuildContext context) {
final String position = widget.controller.value.position.toString();
final String duration = widget.controller.value.duration.toString();
return Text('$position / $duration');
}
}
実行してみましょう。