11 디지털 주사위
#가속도계 #자이로스코프 #Sensor_Plus
핸드폰을 흔들어 주사위를 굴리는 앱. 가속 수치를 인식해 특정 수치를 넘으면 특정행동을 실행하도록 한다.
11.1 사전 지식
11.1.1 가속도계
특정 물체가 특정 방향으로 이동하는 가속도가 어느 정도인지 숫자로 측정하는 기기.
3개의 축(x: 좌우, y: 위아래, z: 앞뒤)으로 방향에 따른 가속도를 측정한다. 물론 하나의 축으로 흔드는 건 불가능하기에 움직임 이벤트는 x,y,z축의 측정 결과가 모두 double값으로 반환된다.
11.1.2 자이로스코프
가속도계는 각 축으로의 직선 움직임만 측정하기에, 자이로스코프로 회전을 측정해 보완한다.
11.1.3 Sensor_Plus 패키지
핸드폰의 가속도계와 자이로스코프 센서를 사용할 수 있는 패키지. 센서의 데이터는 x,y,z축의 움직임을 각각 반환하기에, 전반적인 움직임을 측정하려면 정규화를 통해 흔든 정도를 수치화해야 한다.
shake 패키지는 미리 정규화 작업을 해둔 패키지이므로 여기선 해당 패키지를 사용한다.
11.2 사전 준비
11.2.1 상수 추가하기
글자 크기, 주색상 등 반복적으로 사용하는 값들은 별도의 파일에 상수로 정리해둔다.
lib/const/colors.dart 파일에 색상 관련 상수 정리
import 'package:flutter/material.dart';
const backgroundColor = Color(0xFF0E0E0E); //배경색
const primaryColor = Colors.white; //주색상
final secondaryColor = Colors.grey[600]; //보조색상
티스토리는 코드블럭에 다트를 추가하라 우우
600처럼 키값을 입력할 경우 런타임에 색상이 계산되므로 const 사용이 불가하다. (const는 컴파일타임에 값을 알고있어야 하므로...)
11.2.2 이미지 추가하기
asset/img 폴더에 사용할 이미지를 추가하고 pubspec.yaml에 위치 지정
flutter:
uses-material-design: true
assets:
- asset/img/
+shake 패키지도 추가
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.6
shake: 2.2.0
11.2.4 프로젝트 초기화하기
기본 홈스크린 설정, 메인에 홈 위젯 등록
11.2.5 Theme 설정하기
main.dart에 테마 설정
slideTheme은 slider 위젯 관련 테마로 노브 색상, 트랙 색상 등을 지정
구현으로 넘어가기 전, 에뮬레이터 대신 실제 휴대폰으로 프로젝트를 구동하는 설정을 해줘야 한다. 에뮬레이터는.. 흔들 수 없으니까..
휴대폰 켜서 설정 - 빌드 번호를 검색해 들어가 '빌드번호' 를 7번 탭한다. PIN을 입력하면 개발자 설정이 완료된다.
이후 개발자 옵션으로들어가 USB 디버깅도 활성화한다.
이제 컴퓨터로 돌아와 안드로이드 스튜디오에 Google USB Driver를 설치한다.
Tools - SDK Manager - Languages&Frameworks - Android SDK - SDK Tools에서 찾을 수 있다
유선으로 컴퓨터와 폰을 연결해도 되는데, 나는 마땅한 선이 없어서... 무선연결을 하도록 하겠다
컴퓨터와 휴대폰은 같은 와이파이에 연결되어 있어야 한다.
휴대폰의 개발자 옵션으로 이동해 무선 디버깅 설정을 활성화해준다.
그럼 QR 코드로 페어링 / 페어링 코드로 페어링 두가지 옵션이 나오는데 아무거나 선택해서 기기 페어링해주면 된다.
근데 위 방법만으로는 페어링 오류가 떠서 결국 구글링으로 추가적인 작업을 해줬다...
아래 글을 참고하였음!
https://rkdrkd-history.tistory.com/85
[Android] 안드로이드 스튜디오에서 무선 디버깅이 되지 않을 때, 수동으로 연결하는 방법
안녕하시죠?회사생활을 하느라 너무 오랜만에 포스팅을 하게 되었다.앞으로는 최소 2주에 1번씩은 포스팅을 해보도록 노력해 보겠다. 내가 이전에 이 문제 때문에 애먹었다가 최근에 문제를 해
rkdrkd-history.tistory.com
11.4 구현하기
11.4.1 RootScreen 위젯 구현하기
모든 위젯을 담고 있는 최상위 기본스크린위젯을 루트스크린이라 하자
기본 홈스크린 화면과 내비게이션바, 탭바가 들어가고 화면전환을 해야 한다.
TabBarView 위젯은 각종 Tab 위젯과 쉽게 연동할 수 있는 UI를 구현하기 위한 위젯이다. children 매개변수에 각 탭의 화면으로 활용하고 싶은 위젯을 List로 넣어준다.
BottomNaviagationBar은 Tab을 조정할 수 있는 UI를 아래에 배치하기 위한 위젯이다. 제공될 탭을 items 매개변수에 리스트로 넣어준다.
import 'package:flutter/material.dart';
class RootScreen extends StatelessWidget {
const RootScreen({Key? key}): super(key: key);
Widget build(BuildContext context){
return Scaffold(
body: TabBarView(
children: renderChildren(),
),
bottomNavigationBar: renderBottomNavigation(),
);
}
List<Widget> renderChildren(){
return [];
}
BottomNavigationBar renderBottomNavigation(){
return BottomNavigationBar(items: []);
}
}
main.dart에 기본스크린을 RootScreen으로 바꿔 화면에 보이게 한다.
우선 TabBarView에는 TabController가 필요하다. 컨트롤러는 위젯이 생성될 때 딱 한번 초기화되어야 하니 루트스크린을 StatefulWidget으로 바꾸고, initState를 통해 컨트롤러를 초기화해준다.
+ 탭컨트롤러는 초기화 시 vsync 기능이필요한데, 이는 TickerProviderMixin을 위젯에 mixin으로 제공해줘야 사용할 수 있다.
//...생략
class _RootScreenState extends State<RootScreen> with TickerProviderStateMixin {
TabController? controller;
void initState(){
super.initState();
controller = TabController(length:2, vsync: this);
}
//...생략
TickerProviderMixin은 애니메이션 효율을 담당한다.
다음으로 BottomNavigationBar 작업
BottomNavigationBarItem을 items 배열에 넣어준다.
이제 각 Tab을 TabBarView에 children으로 제공해준다.
테스트용으로 Tab 1 / Tab 2라고 적힌 컨테이너를 만들어줬다. 스와이프하면 화면이 넘어간다.
BottomNav바를 클릭해서 넘어가게 하려면 TabBarView와 연동이 필요하다. TabController를 연동해주자
addListener()은 컨트롤러 속성이 변할 때마다 특정 함수(tabListener)을 실행하도록 한다.
이 콜백함수인 tabListener이 setState()를 실행하므로, controller의 속성이 변경될 때마다 build()가 재실행된다.
리스너는 위젯 생성 시 한 번만 등록하면 되므로 initState()에서 실행한다.
위젯이 삭제될 때 리스너도 같이 삭제해줘야 하므로 dispose()함수에서 removeListener을 해준다.
BottomNav에서 불이 들어와야 하는 부분은 TabBarView의 controller의 인덱스와 동일해야 한다.
onTap은 내비게이션바 아이템이 눌릴 때마다 실행되며, 매개변수로 눌린 탭의 인덱스를 전달받아 setState를 실행해 화면을 해당 인덱스의 탭으로 다시 그린다.
11.4.2 HomeScreen 위젯 구현하기
주사위 이미지, 행운의 숫자가 들어갈 홈스크린(주사위 화면)을 만들자
보여줄 숫자는 RootScreen 위젯에서 정할 것이므로 생성자를 통해 number 매개변수값을 입력받는다.
Column으로 위젯들을 배치해준 뒤 Tab1이었던 화면을 홈스크린으로 대체해준다.
11.4.3 SettingsScreen 위젯 구현하기
SettingsScreen에서는 Slider위젯으로 민감도를 조정한다.
민감도 값을 threshold, 민감도 값이 변경될 때마다실행할 함수를 onThresholdChange라 하고 매개변수로 받을것이다
슬라이더위젯은 다음과 같이 주고
(division: 나누는 구간 개수, value: 현재값, onChanged: 콜백함수의 매개변수로 슬라이더 이동 값 제공, label: 스크롤할 때 화면에 표시할 문자)
루트스크린에서 threshold(기본값 2.7)을 선언하여 세팅스크린에 넘겨준다. Slider 위젯의 현재값이 변하면 threshold 변수에 값을 저장해주고 build()함수를 재실행해 변경된 값을 반영한 위젯을 화면에 다시 그려준다.
11.4.4 shake 플러그인 적용하기
휴대폰을 흔들면 새로운 숫자가 생성되어 주사위를 다른 숫자로 바꿔주어야 한다.
흔들기 감지를 위해 ShakeDetector을 사용한다.
autoStart로 감지를 즉시 시작하도록 하고, 옵션들을 정해준다. 민감도는 앞서 정한 threshold를 사용한다.
흔들기가 감지되면 랜덤 함수를 실행해 난수를 생성하고, 1~6 사이의 랜덤한 숫자로 number 값을 바꿔준다. setState를 호출해 화면을 다시 그리도록 한다.
리스너와 마찬가지로 shakeDetector도 dispose시 중지되어야 하므로 stopListening()을 사용해준다.
실제 기기를 흔들면 숫자가 랜덤하게 변하는 것을 볼 수 있다.
민감도는 숫자가 클수록 더 강한 움직임을 필요로 한다.