지난 시간 버튼에 outline 주는 challenger가 있었는데, 그림자까지 넣어보았다
detail_screen.dart
import 'package:flutter/material.dart';
import 'package:toonflix/models/webtoon_detail_model.dart';
import 'package:toonflix/models/webtoon_episode_model.dart';
import 'package:toonflix/services/api_service.dart';
class DetailScreen extends StatefulWidget {
final String title, thumb, id;
const DetailScreen({
super.key,
required this.title,
required this.thumb,
required this.id,
});
@override
State<DetailScreen> createState() => _DetailScreenState();
}
class _DetailScreenState extends State<DetailScreen> {
late Future<WebtoonDetailModel> webtoon;
late Future<List<WebtoonEpisodeModel>> episodes;
@override
void initState() {
// TODO: implement initState
super.initState();
webtoon = ApiService.getToonById(widget.id);
episodes = ApiService.getLatestEpisodesById(widget.id);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
elevation: 3,
backgroundColor: Colors.white,
foregroundColor: const Color.fromARGB(255, 13, 10, 0),
title: Text(widget.title,
style: const TextStyle(
color: Colors.black,
)),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(50),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Hero(
tag: widget.id,
child: Container(
width: 250,
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
blurRadius: 15,
offset: const Offset(10, 10),
color: Colors.black.withOpacity(0.3),
)
],
),
child: Image.network(widget.thumb),
),
),
],
),
const SizedBox(
height: 25,
),
FutureBuilder(
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(snapshot.data!.about,
style: const TextStyle(
fontSize: 16,
)),
const SizedBox(
height: 15,
),
Text('${snapshot.data!.genre} / ${snapshot.data!.age}',
style: const TextStyle(
fontSize: 16,
)),
],
);
}
return const Text('.....');
},
future: webtoon,
),
const SizedBox(
height: 25,
),
FutureBuilder(
future: episodes,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
children: [
for (var episode in snapshot.data!)
Container(
margin: const EdgeInsets.only(
bottom: 5,
),
decoration: BoxDecoration(
boxShadow: const [
BoxShadow(
color: Color.fromARGB(255, 68, 68, 72),
spreadRadius: 1,
blurRadius: 3,
offset: Offset(5, 6),
)
],
color: Colors.white,
border: Border.all(
width: 1,
color:
const Color.fromARGB(255, 13, 92, 47),
),
borderRadius: BorderRadius.circular(25)),
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 12, horizontal: 30),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(episode.title,
style: const TextStyle(
fontSize: 15,
color:
Color.fromARGB(255, 17, 112, 20),
)),
const Icon(
Icons.chevron_right_rounded,
color: Color.fromARGB(255, 9, 112, 13),
),
],
),
)),
],
);
}
return Container();
},
)
],
),
),
),
);
}
}
#6.16 Url Launcher
flutter에서 브라우저 여는 법을 배울 것이다.
그러기 위해서는 플러터 개발자들이 만든 url_launche라는 패키지를 설치해야 한다.
$ flutter pub add url_launcher
그리고 configuration 파일에 무언가를 복사 붙여넣기 해야 한다.
ios로 작업하고 있다면 info.plist 파일에 아래 코드를 붙여넣어야 하고
안드로이드로 작업하고 있다면 아래 xml을 AndroidMenifest.xml에 추가해주어야 한다.
보다시피 어떤 종류의 url을 열 건지 명시해야 한다.
url launcher http url만 실행하는 것이 아니라 sms url 이나 telephone url도 실행할 수 있다
우리의 경우에는 그냥 http를 사용할 것이다.
(pub.dev에서 url_launcher example을 참고한다)
나는 안드로이드를 사용중이기 때문에
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.toonflix">
<application
android:label="toonflix"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<queries>
<!-- If your app checks for SMS support -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
<!-- If your app checks for call support -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
</queries>
</manifest>
방금 flutter가 실행되는 플랫폼의 configuration 파일인 xml파일과 .plist 파일을 수정했기 때문에 비주얼 스튜디어 코드를 재시작한다.
xCode / Android 파일을 변경했기 때문에 재시작 rebuild 해야 한다.
hot reloading 은 코드 변경만 감지하기 때문에 적용되지 않는다.
이제 detail_screen에서
방금 설치한 url launch를 사용하기 위한 method를 하나 작성해보자
중간에 에러 떠서 헤맸지만 해결하고
LaunchUrl은 Future을 가져다주는 function이기 때문에
Future를 주니까 우리는 await 해야 한다.
이제 버튼에 Gesture를 추가해보자
onButtonTap은 DetailScreenState에 있을 필요가 없다. Episode widget으로 옮겨주자 => 왜?
onTap: onButtonTap,
onTap했을 때 onButtonTap을 실행해주세요!
<!-- android:usesCleartextTraffic="true" -->
에러가 생다
'Flutter > Flutter로 웹툰 앱 만들기' 카테고리의 다른 글
[노마드코더: Flutter 로 웹툰 앱 만들기] #6.17 Favorites / 완료 (0) | 2022.12.21 |
---|---|
[노마드코더: Flutter 로 웹툰 앱 만들기] #6.15 Episodes (0) | 2022.12.20 |
[노마드코더: Flutter 로 웹툰 앱 만들기] #6.14 Detail Info (0) | 2022.12.20 |
[노마드코더: Flutter 로 웹툰 앱 만들기] #6.13 Futures (0) | 2022.12.14 |
[노마드코더: Flutter 로 웹툰 앱 만들기] #6.12 ApiService (0) | 2022.12.14 |