I can't get the set state to change in multiple areas from an onTap VoidCallback?
I have two AnimationController in different stateful widgets. What I would like to implement is that if controller1.value == 0.0 then it'll make sure that when onTap that the controller2.value == 1.0 and visa versa for if controller1.value == 1.0.
StatefulWidget bottom layer (passes the widget.onTapOpen/closed to the top layer)
onTap: () {
_toggleExpandingSheetPanelVisibility();
setState(() {
if (_controller1.value == 0.0){
widget.onTapOpen();
}
else if (_controller1.value == 1.0){
widget.onTapClosed();
}
});
},
StatefulWidget top layer
onTapOpen: _ensureVisible,
onTapClosed: _ensureInvisible,
void _ensureVisible() {
setState(() {
if (_controller2.value == 0.0) {
_toggleVisibility();
}
});
}
void _ensureInvisible() {
setState(() {
if (_controller2.value == 1.0) {
_toggleVisibility();
}
});
}
It worked when if (_controller2.value > or < 0.5) then it would toggle the visibility.
Related
i have created an android app via xamarin.android. i have a multispinnersearch in a fragment and when opened normally, all the items inside it are preselected. but i had a problem. if the user touches the screen outside the spinner, the latter closes and all the items get into my list. i don't want that. unless he clicks "ok" in the spinner, no items should be taken to my list. so i tried to handle the touch event to prevent the selection of items on screen touch but it didn't work. here are the codes i tried:
public override bool DispatchTouchEvent(MotionEvent ev)
{
if (ev.Action == MotionEventActions.Down)
{
View v = CurrentFocus;
if (v is MultiSpinnerSearch)
{
Rect outRect = new Rect();
v.GetGlobalVisibleRect(outRect);
if (!outRect.Contains((int)ev.RawX, (int) ev.RawY))
{
Toast.MakeText(this, "shgsg", ToastLength.Long).Show();
}
}
}
return base.DispatchTouchEvent(ev);
}
i tried this in my main activity but i didn't work. then i tried this in my fragment on the ontouch listener interface:
if (e.Action == MotionEventActions.Down)
{
if (labors_dropdown.IsFocused == true)
{
Android.Graphics.Rect rect = new Rect();
labors_dropdown.GetGlobalVisibleRect(rect);
if (!rect.Contains((int)e.RawX, (int)e.RawY))
{
Toast.MakeText(this.Context, "gfgf", ToastLength.Short).Show();
}
}
}
it didn't work too, what should i do? thanks in advance.
You could try the below method:
public override bool DispatchTouchEvent(MotionEvent ev)
{
if (ev.Action == MotionEventActions.Down)
{
View v = (MultiSpinnerSearch)FindViewById<MultiSpinnerSearch>(Resource.Id.xxxxx);
if (!IsTouchPointInView(v, (int)ev.GetX(), (int)ev.GetY()))
{
Toast.MakeText(this, "shgsg", ToastLength.Long).Show();
}
}
return base.DispatchTouchEvent(ev);
}
private bool IsTouchPointInView(View targetView, int currentX, int currentY)
{
if (targetView == null)
{
return false;
}
int[] localtion = new int[2];
targetView.GetLocationOnScreen(localtion);
int left = localtion[0];
int top = localtion[1];
int right = left + targetView.MeasuredWidth;
int bottom = top + targetView.MeasuredHeight;
if (currentY >= top && currentY <= bottom && currentX >= left
&& currentX <= right)
{
return true;
}
return false;
}
I'm still pretty new and I had a bug in my code wherein, if the device went to sleep during it's normal function, (while it was waiting for a response from a server) then the entire app basically just freezes, and doesn't come back.
Now I didn't have any lifecycle code in there at the time, so I understand that it's the solution, but how can I handle that specifically?
(Life cycle code)
#override
void initState() {
WidgetsBinding.instance.addObserver(this);
super.initState();
}
#override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if(state == AppLifecycleState.paused) {
/*
What information Needs to be saved?
*/
} else if(state == AppLifecycleState.resumed) {
/*
What information needs to be restored, and how to do so if it's not
instantly obvious?
*/
}
}
(Code with Timer that is giving the issue)
//Timer to check Status of Trip, and take action based of Trip Status
Timer.periodic(timerInterval, (ztimer) { // Timer to constantly refresh information
counter++;
if ((counter >= 120) && (switchedScreens) && (splashActive)){
ztimer.cancel();
cancelReq();
Navigator.of(context).pop();
}
getInfo(sessionID); // Get Request Info
info = updateInfo(); // Refresh info in program.
if (info != null) {
reqStatus = info['status'];
if (dispatchVerified == true) { // Check to see if the call has been verified
if (reqStatus != previousReqStatus) { // Check to see if the Status of the call has changed
previousReqStatus = reqStatus;
if ((reqStatus == 'deleted') || (reqStatus == 'complete') || (reqStatus == 'noCall')) { // If the request status would end the call, do so
ztimer.cancel();
if (splashActive) { //if deleted by server, would still be on Splash Screen
splashActive = false;
Navigator.of(context).pop();
}
cancelReq();
} else if (reqStatus == 'accepted') { // If accepted, switch back from Splash Page
if (splashActive) {
splashActive = false;
Navigator.of(context).pop();
}
reqPosition = new LatLng(info['cab'][0]['latitude'], info['req'][0]['longitude']); // add and update the position of the request for the marker
if (!addedReqPosition) {
addedReqPosition = true;
addReqPosition();
}
} else if (reqStatus == 'canceled'){ // If Call was cancelled, but on Splash Page, ensure it's removed.
ztimer.cancel();
if (splashActive) {
splashActive = false;
Navigator.of(context).pop();
}
cancelReq();
} else if (reqStatus == 'editing') {
dispatchVerified = false;
splashActive = true;
stream = new DataStream();
Navigator.push(context, CupertinoPageRoute(builder: (context) => SplashPage(stream: stream)));
}
}
} else {
if (reqStatus == 'editing') {
} else if ((reqStatus == 'unassigned') || (reqStatus == 'pendingConfirmation')) { // Request has now been verified
if (switchedScreens) {
dispatchVerified = true;
switchedScreens = false;
stream.dataSink.add(true);
}
} else if (reqStatus == 'deleted'){ // If Call was Deleted by Server, reset state of app.
ztimer.cancel();
if (splashActive) {
splashActive = false;
Navigator.of(context).pop();
}
cancelReq();
}
}
}
if (booking == false) {
ztimer.cancel();
}
mapState.setState(() {});
});
What can I try next?
I have a working circular progress button based ontapdown and ontapup, however i wanted it to trigger once the progress complete. Right now it only trigger only when the progress is complete and user tapUp.
onTapDown: (_) {
controller1.forward();
},
onTapUp: (_) {
if (controller1.status ==
AnimationStatus.forward) {
controller1.reverse();
} else if (controller1.status ==
AnimationStatus.completed) {
setState(() {
controller1.value = 0.0;
// widget.isClickCALLBOMBA = true;
// controller1.reverse();
Flushbar()
..title = allTranslations
.text('success')
..message =
"We will alert the bomba !"
..duration =
Duration(seconds: 3)
..backgroundColor =
Colors.red
..show(context);
});
}
},
You can add a listener to your AnimationController to do stuff when the animation is complete:
controller1.addStatusListener((status) {
if (status != AnimationStatus.completed) {
return;
}
//Animation is complete! Do completion stuff.
});
I want my splash screen to always appear in my application and it does which is great, but I have a walk through after the splash screen and I want it to be a one time walk through, So i want to add an integer to the shared preferences with a value of 0 and everytime I open the splash screen the value is incremented by one, so when "number" equals 1 or greater at the second run the splash screen skips the walkthrough and goes to home , here is the code that I want to edit now :
void initState() {
// TODO: implement initState
super.initState();
Timer(Duration(seconds: 5), () => MyNavigator.goToIntro(context));
}
And I want it to be like :
void initState() {
// TODO: implement initState
super.initState();int number=0;//this is in the shared prefs
Timer(Duration(seconds: 5), () => if(number==0){MyNavigator.goToIntro(context));
}else{MyNavigator.goToHome(context));
number++;}
}
The below code prints perfectly as we expect(during first launch only, "First launch"). You can use your navigation logic instead of print.
#override
void initState() {
super.initState();
setValue();
}
void setValue() async {
final prefs = await SharedPreferences.getInstance();
int launchCount = prefs.getInt('counter') ?? 0;
prefs.setInt('counter', launchCount + 1);
if (launchCount == 0) {
print("first launch"); //setState to refresh or move to some other page
} else {
print("Not first launch");
}
}
We need to have the number value to be saved across multiple app launches. We can use shared_preference plugin to achieve this.
secondly, getData that saved in our device.
Future<bool> getSaveData() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
bool isIntroScreenOpenedBefore =
sharedPreferences.getBool("isIntroScreenOpened") ?? false;
print(sharedPreferences.containsKey("isIntroScreenOpened")); // check your key either it is save or not?
if (isIntroScreenOpenedBefore == true) {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return LoginBoard();
}));
} else {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return WalKThroughScreen();
}));
}
return isIntroScreenOpenedBefore;
}
at first, let's save the data as boolean
Future<void> saveData() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
bool isIntroScreenOpened = true;
sharedPreferences.setBool("isIntroScreenOpened", isIntroScreenOpened); // saved data to your device.
}
Answer by #Dinesh Balasubramanian is works really fine.
But I have 4 initial screen that need to show once. I have done that using same logic in each screen. and then my app was showing 5th screen second time like fast forwarding all the previous screen and stopping on 5th screen.
To resolve this I am getting all the set Preferences at main.dart to open directly 5th screen. but when I do that I am having this problem,
"E/flutter (32606): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)]
Unhandled Exception: Navigator operation requested with a context that
does not include a Navigator.
E/flutter (32606): The context used to
push or pop routes from the Navigator must be that of a widget that is
a descendant of a Navigator widget."
Here is code to switch from main.dart:
int firstLogin, firstMobile, firstOtp, firstInfo;
void setValue() async {
final prefs = await SharedPreferences.getInstance();
firstLogin = prefs.getInt('counterLogin') ?? 0;
firstMobile = prefs.getInt('counterMobile') ?? 0;
firstOtp = prefs.getInt('counterOtp') ?? 0;
firstInfo = prefs.getInt('counterInfo') ?? 0;
prefs.setInt('counterLogin', firstLogin + 1);
prefs.setInt('counterMobile', firstMobile + 1);
prefs.setInt('counterOtp', firstOtp + 1);
prefs.setInt('counterInfo', firstInfo + 1);
if ((firstLogin == 0) && (firstMobile == 0) && (firstOtp == 0) && (firstInfo == 0)) {
setState(() {
print("first launch");
Navigator.of(context).pushNamed(LoginScreen.routeName);
});
} else {
setState(() {
print("not first launch");
Navigator.of(context).pushNamed(LandingSection.routeName);
});
}
}
And calling the setValue() in initState()
I am looking forward for solution.
I have a switch with that I switching between light theme and dark theme. Switch value true = dark theme. Switch value false = light. And the default is false.
If I switch from false to true the theme switches to dark so far so good. But if I restart the app is the switch false and the dark theme is shown.
bool _switchValue = false;
void _changeThemeInOpp(bool switchValue) {
setState(() {
_switchValue = switchValue;
});
if (_switchValue == true) {
DynamicTheme.of(context).setBrightness(Brightness.dark);
} else {
DynamicTheme.of(context).setBrightness(Brightness.light);
}
}
new Switch(
value: _switchValue,
onChanged: (bool switchValue) {
_changeThemeInOpp(switchValue);
}),
How I can restart the app and the switch have the right value?
You need to save the _switchValue in the disk using something like shared_preferences
for more information see :
Storing key-value data on disk
save the value when you change it :
void _changeThemeInOpp(bool switchValue) async{
// save new value
final _switchValue= await SharedPreferences.getInstance();
_switchValue.setInt('Value', switchValue);
setState(() {
_switchValue = switchValue;
});
if (_switchValue == true) {
DynamicTheme.of(context).setBrightness(Brightness.dark);
} else {
DynamicTheme.of(context).setBrightness(Brightness.light);
}
}