Reputation: 303
I'm trying to update a child widget's orientation with Rotated Box, based on my device orientation.
However, I have a constraint: I don't want my main UI app to rotate. I want to keep it always locked (like "portrait up"), but I still want to receive device orientation updates.
This is the partial solution I've found, using native_device_orientation package and SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
.
The problem is: it's super sensible to changes, so it is not suitable in a user experience perspective (as pointed by native_device_orientation author here). Also, there is a 45 degree position that the sensor orientation goes frenzy, since the sensor is in the sweet spot between two orientations.
Is there another way or perspective to solve this problem?
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:native_device_orientation/native_device_orientation.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
int get_turns_based_on_orientation(NativeDeviceOrientation orientation) {
switch(orientation) {
_counter++;
case NativeDeviceOrientation.portraitDown:
return 2;
case NativeDeviceOrientation.portraitUp:
return 0;
case NativeDeviceOrientation.landscapeLeft:
return 1;
case NativeDeviceOrientation.landscapeRight:
return 3;
case NativeDeviceOrientation.unknown:
return 0;
}
}
@override
void initState() {
super.initState();
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: NativeDeviceOrientationReader(
useSensor: true,
builder: (context) {
final orientation = NativeDeviceOrientationReader.orientation(context);
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
RotatedBox(
quarterTurns: get_turns_based_on_orientation(orientation),
child: Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
),
],
),
);
}
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
Upvotes: 1
Views: 1710
Reputation: 3768
In order to have your orientation changed without any oscillation, you can try to reduce the sensibility with this as a workaround:
Adapting to your code it would be as follows:
[...]
//State Class properties
DateTime timeOfLastChange = DateTime.now();
NativeDeviceOrientation stableOrientation = NativeDeviceOrientation.portraitUp;
NativeDeviceOrientation currentOrientation = NativeDeviceOrientation.portraitUp;
[...]
builder: (context) {
currentOrientation = NativeDeviceOrientationReader.orientation(context);
timeOfLastChange = DateTime.now();
Future.delayed(Duration(milliseconds: 500), () {
if (DateTime
.now()
.difference(timeOfLastChange)
.inMilliseconds > 500) {
setState((){stableOrientation = currentOrientation;});
}
});
[...]
quarterTurns: get_turns_based_on_orientation(stableOrientation),
[...]
}
Keep in mind that the 500
value is a constant that can be adjusted to increase or decrease the delay in orientation changes.
Upvotes: 3
Reputation: 7640
I think you are not calling the setPreferredOrientations
method in the correct place. You need to call it in your initState()
and dispose()
methods depend on your requirements. Widget build()
method is the reason for the super sensible.
Upvotes: 0