5 minute read

가속도계 및 자일로스코프

sensor_plus 패키지를 사용하면 핸드폰의 가속도계와 자일로스코프 센서를 사용할 수 있다.

shake 플러그인을 사용하여 핸드폰 흔들기를 사용할 수 있다.

전체소스

main.dart

import 'package:flutter/material.dart';
import 'package:random_dice/screen/home_screen.dart';
import 'package:random_dice/const/colors.dart';
import 'package:random_dice/screen/root_screen.dart';

void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
scaffoldBackgroundColor: backgroundColor,
sliderTheme: SliderThemeData( // Slider 위젯 관련
thumbColor: primaryColor, // 동그라미 색
activeTrackColor: primaryColor, // 이동한 트랙 색

          // 아직 이동하지 않은 트랙 색
          inactiveTrackColor: primaryColor.withOpacity(0.3),         ),
        // BottomNavigationBar 위젯 관련
        bottomNavigationBarTheme: BottomNavigationBarThemeData(
          selectedItemColor: primaryColor,     // 선택 상태 색
          unselectedItemColor: secondaryColor, // 비선택 상태 색
          backgroundColor: backgroundColor,    // 배경 색
        ),
      ),
      home: RootScreen(),
    ),

);
}
home_screen.dart

import 'package:random_dice/const/colors.dart';
import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
final int number;

const HomeScreen({
required this.number,
Key? key,
}) : super(key: key);

@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [

        // ➊ 주사위 이미지
        Center(
          child: Image.asset('asset/img/$number.png'),
        ),
        SizedBox(height: 32.0),
        Text(
          '행운의 숫자',
          style: TextStyle(
            color: secondaryColor,
            fontSize: 20.0,
            fontWeight: FontWeight.w700,
          ),
        ),
        SizedBox(height: 12.0),
        Text(
          number.toString(),  // ➋ 주사위 값에 해당되는 숫자
          style: TextStyle(
            color: primaryColor,
            fontSize: 60.0,
            fontWeight: FontWeight.w200,
          ),
        ),
      ],
    );

}
}
root_screen.dart

import 'package:flutter/material.dart';
import 'package:random_dice/screen/home_screen.dart';
import 'package:random_dice/screen/settings_screen.dart';
import 'dart:math';
import 'package:shake/shake.dart';

class RootScreen extends StatefulWidget {
const RootScreen({Key? key}) : super(key: key);

@override
State<RootScreen> createState() => \_RootScreenState();
}

class \_RootScreenState extends State<RootScreen> with TickerProviderStateMixin{ // ➊
TabController? controller; // 사용할 TabController 선언
double threshold = 2.7;
int number = 1;
ShakeDetector? shakeDetector;

@override
void initState() {
super.initState();

    controller = TabController(length: 2, vsync: this);  // ➋

    controller!.addListener(tabListener);
    shakeDetector = ShakeDetector.autoStart(   // ➊ 흔들기 감지 즉시 시작
      shakeSlopTimeMS: 100,  // ➋ 감지 주기
      shakeThresholdGravity: threshold,  // ➌ 감지 민감도
      onPhoneShake: onPhoneShake,  // ➍ 감지 후 실행할 함수
    );

}

void onPhoneShake() { // ➎ 감지 후 실행할 함수
final rand = new Random();

    setState(() {
      number = rand.nextInt(5) + 1;
    });

}

tabListener() { // ➋ listener로 사용할 함수
setState(() {});
}

@override
dispose(){
controller!.removeListener(tabListener); // ➌ listener에 등록한 함수 등록 취소
shakeDetector!.stopListening();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: TabBarView( // ➊ 탭 화면을 보여줄 위젯
controller: controller,
children: renderChildren(),
),

      // ➋ 아래 탭 네비게이션을 구현하는 매개변수
      bottomNavigationBar: renderBottomNavigation(),
    );

}

List<Widget> renderChildren(){
return [
HomeScreen(number: number),
SettingsScreen( // 기존에 있던 Container 코드를 통째로 교체
threshold: threshold,
onThresholdChange: onThresholdChange,
),
];
}

void onThresholdChange(double val){ // ➊ 슬라이더값 변경 시 실행 함수
setState(() {
threshold = val;
});
}

BottomNavigationBar renderBottomNavigation() {
return BottomNavigationBar(
currentIndex: controller!.index,
onTap: (int index) { // ➎ 탭이 선택될 때마다 실행되는 함수
setState(() {
controller!.animateTo(index);
});
},
items: [
BottomNavigationBarItem( // ➊ 하단 탭바의 각 버튼을 구현
icon: Icon(
Icons.edgesensor_high_outlined,
),
label: '주사위',
),
BottomNavigationBarItem(
icon: Icon(
Icons.settings,
),
label: '설정',
),
],
);
}
}
setting_screen.dart

import 'package:random_dice/const/colors.dart';
import 'package:flutter/material.dart';

class SettingsScreen extends StatelessWidget {
final double threshold; // Slider의 현잿값

// Slider가 변경될 때마다 실행되는 함수
final ValueChanged<double> onThresholdChange;

const SettingsScreen({
Key? key,

    // threshold와 onThresholdChange는 SettingsScreen에서 입력
    required this.threshold,
    required this.onThresholdChange,

}) : super(key: key);

@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(left: 20.0),
child: Row(
children: [
Text(
'민감도',
style: TextStyle(
color: secondaryColor,
fontSize: 20.0,
fontWeight: FontWeight.w700,
),
),
],
),
),
Slider(
min: 0.1, // ➊ 최솟값
max: 10.0, // ➋ 최댓값
divisions: 101, // ➌ 최솟값과 최댓값 사이 구간 개수
value: threshold, // ➍ 슬라이더 선택값
onChanged: onThresholdChange, // ➎ 값 변경 시 실행되는 함수
label: threshold.toStringAsFixed(1), // ➏ 표싯값
),
],
);
}
}
colors.dart

import 'package:flutter/material.dart';

const backgroundColor = Color(0xFF0E0E0E); // 배경색

const primaryColor = Colors.white; // 주 색상

final secondaryColor = Colors.grey[600]; // 보조 색상

Updated:

Leave a comment