Flutter TabBar how to detect or listen for the being of drag or swipe? - flutter

I have a tab bar with a controller that has a Listener to handle the on tab and user drag/swipe the issue is that I need to know right at the being of the drag so I can start to make the active icon changes with the current version the active icon only changes at the end of the swipe so there is a delay.
Here is my code
In the init state
// For tab selection
tabController = TabController(vsync: this, length: 4);
tabController.addListener(_handleTabSelection);
// Handles the tab section with on tab and drag
void _handleTabSelection() {
setState(() {
_selectedIndex = tabController.index;
});
}

Related

Flutter - How will you check from which screen you have clicked bottom navigation tab

I am trying to find how can I know from which screen user has clicked the bottom nav screen. Basically I have to send event from which screen user clicked on botton nav. I have 4 bottom nav.
There is no direct way to check a previously selected item in the bottom bar what you can do you can make use of
onTap: (index) => changeTab(index)
It gives an index of the item user taps, Save index to some variable, and next time when use tap on the item you can consider previously saved value as an item from which the user is tapping.
You can check the last selected index in bottom navigation bar :
static int currentTab = 0;
static int lastIndex = 0;
When you implement the onPressed or onTap method on bottom bar:
onTap: (){
setState(() {
currentTab = index;
lastIndex = currentTab; // It keeps the last selected index.
}
});
}
And then u can call
currentTab = lastIndex.

Dismiss keyboard on swipe back gesture in Flutter app

I am trying to dismiss the keyboard when the user swipes from the edge to pop route.
Currently the keyboard doesn't dismiss until the route is completely gone popped, messing up some of the other pages layout until it dismisses
I did try to use a WillPopScope to determine when the user was going to pop the route, but unfortunately this disables the swipe to pop functionality from iOS or the CupertinoPageRoute.
I just want to find out if there's anyway I can determine when the user swipes from the edge to pop or taps the back button on the appBar and dismiss the keyboard as they do so.
If possible, I am trying to dismiss keyboard as soon as they start swiping to pop, as it happens in many apps.
I am attaching attaching a gif showing the effect I'm trying to achieve.
As suggested by Ovidiu
class DismissKeyboardNavigationObserver extends NavigatorObserver {
#override
void didStartUserGesture(Route route, Route previousRoute) {
SystemChannels.textInput.invokeMethod('TextInput.hide');
super.didStartUserGesture(route, previousRoute);
}
}
and in your Material App
MaterialApp(
navigatorObservers: [DismissKeyboardNavigationObserver()],
)
You need to create a custom class extending NavigatorObserver, and pass an instance of it to the navigatorObservers property of your MaterialApp or CupertinoApp.
Within that custom class, you can override didStartUserGesture and didStopUserGesture, which will be called when the swipe gesture starts/ends. This should allow you to achieve the behavior you are looking for. Note that didStartUserGesture indicates the current route as well as the previous route, based on which you could add logic to determine whether the keyboard should be dismissed or not.
This should come naturally and you shouldn't be directly concerned with that because actually, when you pop a route with the keyboard on, it should dismiss properly.
However, if you want to detect when the user starts swiping and dismiss the keyboard along with it and then pop the current route, you can easily achieve it by wrapping your screen widget with a GestureDetector like so:
Widget build(BuildContext context) {
double dragStart = 0.0;
return GestureDetector(
onHorizontalDragStart: (details) => dragStart = details.globalPosition.dx,
onHorizontalDragUpdate: (details) {
final double screenWidth = MediaQuery.of(context).size.width;
// Here I considered a back swipe only when the user swipes until half of the screen width, but you can tweak it to your needs.
if (dragStart <= screenWidth * 0.05 && details.globalPosition.dx >= screenWidth) {
FocusScope.of(context).unfocus();
}
child: // Your other widgets...
},
this is something i wrote to handle this issue. doesnt use any external packages, you would just wrap your content in the main function at the top.
Widget swipeOffKeyboard(BuildContext context, {Widget? child}) {
return Listener(
onPointerMove: (PointerMoveEvent pointer) {
disKeyboard(pointer, context);
},
child: child, // your content should go here
);
}
void disKeyboard(PointerMoveEvent pointer, BuildContext context) {
double insets = MediaQuery.of(context).viewInsets.bottom;
double screenHeight = MediaQuery.of(context).size.height;
double position = pointer.position.dy;
double keyboardHeight = screenHeight - insets;
if (position > keyboardHeight && insets > 0) FocusManager.instance.primaryFocus?.unfocus();
}

Ionic 2 - native transition on alertcontroller

Is that possible to implement the native transition or animation (opacity etc) in alert controller like what we are doing in Modal dialog?
For modal dialog we can use like below code.
let modal = this.modalCtrl.create(SingleButtonAlertModalPage, { showBackdrop: false,
enableBackdropDismiss: false,
enterAnimation: 'modal-scale-up-enter'});
I want to implement fade in/out in alert controller. While alert dialog displaying it has to come from top of the screen? Is that possible ?
You can apply custom styles to ModalController by adding cssClass.
{ cssClass: 'native-transition' }
In your component.scss file, apply the properties to class for animation.
.native-transition{
opacity: 0.5;
}

How to make activity start at the bottom of the ScrollView?

I want to make a quiz application with levels. It has a long background image and as you scroll down, at the bottom I have the levels 1, 2, 3,...going up. How can I make the activity scroll at the bottom automatically when I enter the app?!
ScrollView scrollview = findViewById(R.id.scrollView);
scrollview.post(new Runnable() {
#Override
public void run() {
scrollview.fullScroll(ScrollView.FOCUS_DOWN);
}
});

How to have an Activity that uses a ScrollView AND keep onTouch method working properly?

I have an Activity that populates two views on a ViewFlipper. I added an onTouch(View v, MotionEvent event) public boolean method to the Activity. The method is implemented so that when the person taps on the screen the ViewFlipper goes to the next view. It works great but some of the text is too long so I went into my XML file and surrounded the textfield in one of my ViewFlipper views with a linearlayout and then a ScrollView. But now when I'm viewing the fields that are too long and show a scroll bar, I can't display the previous view. The onTouch method in my main activity isn't being executed. I have not been able to figure this out. I've read some posts about implementing or overriding the methods in ScrollView but I don't know where to do this in my activity. Does anyone know how I can program ScrollView to not intercept but keep its ability to scroll the view?
ScrollView myScroll;
myScroll.setOnTouchListener(new OnTouchListener){
#Override
public boolean onTouch(View v, MotionEvent touchevent) {
switch (touchevent.getAction()) {
case MotionEvent.ACTION_DOWN: {
oldTouchValue = touchevent.getX();
break;
}
case MotionEvent.ACTION_UP: {
float currentX = touchevent.getX();
if (oldTouchValue < currentX) {
//left swipe
return true;
}
if (oldTouchValue > currentX) {
//right swipe
return true;
}
return false;
}
}