FAILURE: Build failed with an exception.
* Where:
Build file '[프로젝트 디렉토리]\android\app\build.gradle' line: 24
* What went wrong:
A problem occurred evaluating project ':app'.
> Failed to apply plugin 'com.android.internal.application'.
> Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8.
You can try some of the following options:
- changing the IDE settings.
- changing the JAVA_HOME environment variable.
- changing `org.gradle.java.home` in `gradle.properties`.
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 6s
┌─ Flutter Fix ─────────────────────────────────────────────────────────────────┐
│ [!] You need Java 11 or higher to build your app with this version of Gradle. │
│ │
│ To get Java 11, update to the latest version of Android Studio on │
│ https://developer.android.com/studio/install. │
│ │
│ To check the Java version used by Flutter, run `flutter doctor -v`. │
└───────────────────────────────────────────────────────────────────────────────┘
Exception: Gradle task assembleDebug failed with exit code 1
어떻게 하라고 친절하게 알려준다.
그런데 저 gradle.properties 이 어디 있냐고????!!!
그거슨 바로 여기~~~
- [프로젝트 디렉토리]/android/gradle.properties
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
org.gradle.java.home=[JAVA 설치 디렉토리. ex) C:\\Program Files\\Java\\jdk-11]
그런데 말입니다~~~
난 이미 자바 11 버전을 쓰고 있는데 왜 이런 에러가 발생하는지... 참... --;;;
C:\Users\home>java -version
openjdk version "11" 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)
....
# The following section is specific to Flutter packages.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
assets:
- asset/img/
....
- PageView 는 여러개의 위젯을 독립적인 페이지로 생성하고 가로 또는 세로 스와이프로 페이지를 넘길 수 있게 하는 위젯이다.
- PageView 는 material 패키지에서 기본으로 제공
- children 변수에 페이지로 생성하고 싶은 위젯을 넣어준다.
- 핸드폰 크기와 이미지의 크기가 달라서 위아래로 흰색 여백이 생길수 있다. 핸드폰 화면 비율에 따라 위아래 대신 좌우가 남거나 운좋게 딱 맞을 수 도 있다. 여러 비율의 화면에 대응할 수 있게 이미지 fit 을 조절해줘서 항상 전체 화면을 차지하도록 설정한다.(fit: BoxFit.cover)
- 일정 시간이 지나면 자동으로 페이지가 변경되도록 Timer 클래스를 사용하여 자동 롤링 기능 추가.
※ Timer 를 추가하려면 HomeScreen 위젯을 StatelessWidget 이 아닌 StatefulWidget 으로 변경해야 한다. StatelessWidget 위젯을 사용하면 Timer 를 build() 에서 등록해야 하는데 이럴경우 위젯이 새로 생성될 때마다 매번 새로운 Timer 가 생성된다. 이렇게 구현하면 Memory leak 이 발생한다.
- 따라서, StatefulWidget 위젯을 사용하여 initState() 에서 한번만 Timer 를 등록하여 구현하면 된다.
② initState() 함수를 override 하면 StatefulWidget 생명주기에서의 initState() 함수를 사용할 수 있다.
③ 모든 initState() 함수는 부모의 initState() 함수를 호출해야 한다.
④ 3초마다 실행되는 Timer 등록.
8. PageController 사용
- PageView 를 조작하기 위해 PageController 사용.
- PageController 를 State 에 선언하고 PageView 에 매개변수로 입력
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:async';
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
// ❶ PageController 생성
final PageController pageController = PageController();
@override
void initState() {
super.initState();
Timer.periodic(
Duration(seconds: 3),
(timer) {
// ➌ 현재 페이지 가져오기.
int? nextPage = pageController.page?.toInt();
// 페이지 값이 없을 때 예외 처리
if (nextPage == null) {
return;
}
// 첫페이지와 마지막 페이지 분기 처리
if (nextPage == 4) {
nextPage = 0;
} else {
nextPage++;
}
pageController.animateToPage(
// ➍ 페이지 변경
nextPage,
duration: Duration(milliseconds: 500),
curve: Curves.ease,
);
},
);
}
@override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light);
return Scaffold(
body: PageView(
// ❷ PageController 등록
controller: pageController,
children: [1, 2, 3, 4, 5]
.map(
(number) => Image.asset(
'asset/img/image_$number.jpeg',
fit: BoxFit.cover,
),
)
.toList(),
),
);
}
}
① PageController 사용을 위한 생성.
② PageView 에 매개변수로 PageController 등록
③ pageController.page Getter 를 사용하여 PageView 의 현재 페이지를 가져올 수 있다. 페이지가 변경 중인 경우 소수점으로 표현돼서 double 로 값이 반환된다. animateToPage() 함수 실행시 정수값을 넣어줘야해서 toInt() 로 변환한다.
④ animateToPage() 함수를 이용해서 PageView 의 현재 페이지를 변경할 수 있다. curve 매개변수는 페이지가 변경되는 애니메이션의 작동 방식을 정의한다. 공식 홈페이지에서 애니메이션을 확인할 수 있다.
√ 다른 파일에서 불러올 경우 : package:[프로젝트의 이름]/[lib 폴더로 부터의 위치]/파일명(.dart)
√ 플러그인 기능 사용 시 : package:[플러그인 이름]/[플러그인 이름].dart
- MaterialApp 위젯은 플러터 앱의 최상위 위젯이며 앱이 처음 실행됐을 때 보여줄 화면을 home 매개변수에 입력할 수 있다. 여기서는 HomeScreen() 을 불러와서 첫화면으로 설정한다.
2. 홈 화면에서 사용할 HomeScreen 정의
- lib/screen/home_screen.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class HomeScreen extends StatelessWidget {
WebViewController? controller; // 컨트롤러 변수 생성
HomeScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar( // 앱바 위젯 추가
// 배경색 지정
backgroundColor: Colors.orange,
// 앱 타이틀 설정
title: Text('Childeye Blog'),
// 가운데 정렬
centerTitle: true,
actions: [
IconButton(
// 눌렀을 때 콜백 함수 설정
onPressed: () {
if (controller != null) {
// 웹뷰에서 보여줄 사이트 실행하기
controller!.loadUrl('https://childeye.tistory.com');
}
},
// 홈 버튼 아이콘 설정
icon: Icon(
Icons.home,
),
),
],
),
body: WebView( // WebView 추가하기
initialUrl: 'https://childeye.tistory.com',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController controller) {
this.controller = controller; // 위젯에 컨트롤러 저장
},
),
);
}
}
- HomeScreen 위젯 : 웹 앱이 실행되면 가장 먼저 보이는 위젯.
- 웹뷰 컨트롤러 : 홈 아이콘을 눌렀을 때 웹뷰 화면을 변경하려면 위젯 제어 기능이 필요하다. 이 기능을 하는 것이 웹뷰 컨트롤러가 담당한다.
√ WebViewController 를 저장할 변수를 선언한다.(controller 변수)
√ 웹뷰 위젯이 생성되면 onWebViewCreated 함수가 실행되는데 이때 WebViewController 를 매개변수로 받는다. 이 값을 controller 변수에 저장하면 웹뷰를 제어할 수 있다.
- 화면 구성 : 앱바와 웹뷰로 이루어져 있음.
√ 앱바 : 제목과 홈 버튼을 렌더링.
√ 웹뷰 : 지정한 URL(childeye.tistory.com)의 내용을 표시
- 앱바(AppBar)
√ HomeScreen 위젯에 앱바를 추가, 제목을 넣어주고 배경색을 설정한다.
√ 앱바 위젯은 일반적으로 Scaffold 위젯의 appBar 매개변수로 넣어준다.
√ AppBar 의 배경색을 지정한다.
√ AppBar 의 중간에 Text 위젯을 넣어주고 가운데 정렬한다.
√ AppBar 의 actions 매개변수에 홈아이콘을 생성하고 제어한다. actions 매개변수에 위젯을 넣으면 앱바의 오른쪽 끝에 순서대로 위젯이 배치된다.
√ 홈아이콘을 눌렀을 때 실행할 콜백 함수를 onPressed 매개변수에 정의한다. WebViewController 의 load() 함수를 이용하여 URL 로 이동시킨다. controller 변수에 ! 기호를 추가하는 이유는 controller 변수가 null 이 가능한 타입으로 선언됐기 때문이다. 위 코드에서는 controller 변수가 null 이 아닌 경우에만 load() 함수를 호출하니 ! 를 사용하여 controller 변수는 절대로 null 이 될수 없다고 표현한 것이다.