Flutter Web horizontal scroll with responsive webapp - flutter

I want to figure out the position of scroll and depending on that results, I want to show some buttons.
This is my code of Scroll Widget.
Flexible(
child: Container(
constraints: BoxConstraints(
maxWidth: 730,
),
child: ListView.separated(
controller: _platformController,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
String platform = platformlistA[index].toLowerCase();
return InkWell(
onTap: () {
if (platformIndex !=
platformlistA.indexWhere(
(element) => element == platformlistA[index])) {
setState(() {
platformIndex = platformlistA.indexWhere(
(element) => element == platformlistA[index]);
});
} else {
setState(() {
platformIndex = -1;
});
}
},
child: Container(
alignment: Alignment.center,
height: 37,
width: platform != 'fortnite' ? 100 : 85,
padding: EdgeInsets.symmetric(
horizontal: 5,
),
child: WebsafeSvg.asset(
'assets/$platform.svg',
color: platformIndex ==
platformlistA.indexWhere(
(element) => element == platformlistA[index])
? Colors.black
: Color(0xffb7b7b7),
),
),
);
},
separatorBuilder: (context, index) {
return SizedBox(width: 7);
},
itemCount: platformlistA.length),
),
),
and this is the code getting the position of Scroll widget.
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
setState(() {
if (_platformController.position.maxScrollExtent > 0) {
if (_platformController.position.atEdge) {
if (_platformController.position.pixels == 0) {
print('left edge');
// show -> button at right
} else {
print('right edge');
// show <- button at left
}
} else {
print('middle of the scroll');
// show <-, -> buttons at both side
}
} else {
print('not scrollable');
// do not show any button.
}
});
});
I used WidgetsBinding.instance!.addPostFrameCallback because, it shows error if I handle with controller before the build.
Eventually, this works functionally, but it is too slow since WidgetsBinding.instance!.addPostFrameCallback in build function continues to run. I cannot put it in initstate because if() phrase has to be called everytime when the size of web application changes.
Is there any faster way than this method??? Please help!!

Map<String, dynamic> toJson() => {
'name': name,
'email': email,
};
Try adding => front of toJson()

Related

Flutter GetX tagged controller data update

First of all I don't know what i am facing, but I'll do my best to explain the situation.
I'm trying to build chat app and i have two sections on same page. These two different sections are rendering inside same ListView. Only thing that changing is the data which i am using to feed the ListView. I need to get the status of user in real time so i am putting tagged controllers for each tile which is rendering inside list view. Here comes the problem. The tiles rendered at the same index are not showing the true states of themselves until some state changes on that tile for example position of any Stack item.
Here is the code.
In this part I'm rendering ListView
ListView.builder(
itemCount: chatController.currentChats!.length,
itemBuilder: (context, index) {
return GetBuilder<UserOnlineController>(
global: false,
init: Get.find<UserOnlineController>(tag: chatController.currentUserID == chatController.currentChats![index].user1 ? chatController.currentChats![index].user2 : chatController.currentChats![index].user1),
builder: (userController) {
return Stack(
children: [
Positioned(
child: Container(
color: Colors.black,
width: Get.width,
height: Dimensions.h100,
child: Center(
child: Text(
"${userController.user!.name!}",
style: TextStyle(
color: Colors.white
),
),
),
)
)
],
);
}
);
}),
This is the part that I'm putting controllers and listening chats in real time.
void listenChats() async {
var chatController = Get.find<ChatController>();
var messagesController = Get.find<MessagesController>();
String userID = Get.find<SharedPreferenceService>().getUserID();
var currentUserDoc = (await firestoreService.getCollection('users').where('userID', isEqualTo: userID).get()).docs[0];
Stream<DocumentSnapshot> userStream = firestoreService.getCollection('users').doc(currentUserDoc.id).snapshots();
Stream<QuerySnapshot> chatStream = firestoreService.getCollection('chats').snapshots();
await for(var user in userStream){
var userObject = UserModel.fromJson(user.data() as Map<String,dynamic>);
await for(var chats in chatStream) {
List<Chat> activeChats = [];
List<Chat> unActiveChats = [];
List<Chat> newMatches = [];
List<Chat> allChats = [];
var filteredChats = chats.docs.where((chat) => userObject.chat!.active_chats!.contains(chat['chatID'])).toList();
filteredChats.forEach((chatDoc) {
var currentChat = Chat.fromJson(chatDoc.data() as Map<String,dynamic>);
if(currentChat.user1 == userID){
Get.put(
UserOnlineController(firestoreService: firestoreService, userID: currentChat.user2!),
tag: currentChat.user2!,
);
}
else{
Get.put(
UserOnlineController(firestoreService: firestoreService, userID: currentChat.user1!),
tag: currentChat.user1!
);
}
allChats.add(currentChat);
if(currentChat.isActive!){
if(currentChat.isStarted!){
activeChats.add(currentChat);
}
else{
newMatches.add(currentChat);
}
}
else{
unActiveChats.add(currentChat);
}
});
messagesController.generatePositions(activeChats.length, true);
messagesController.generatePositions(unActiveChats.length, false);
chatController.setAllChats(allChats);
chatController.setCurrentChats();
chatController.setChats(activeChats, unActiveChats, newMatches);
}
}
}
And this is the part that I'm using to control the UI state
void setAllChats(List<Chat> allChats) {
_allChats = allChats;
}
void setCurrentChats() {
_currentChats = _allChats!.where((chat) => chat.isActive! == isActiveMessages).toList();
update();
}
void setIsActiveMessages(bool state){
_isActiveMessages = state;
_currentChats = _allChats!.where((chat) => chat.isActive! == state).toList();
update();
}
In the above pictures all of these users are different but only true one is the third one at second screen shot.
Hello again this question basically explains all the details.
Multiple Instance with GetX tag not working in flutter
Basically you need to add key parameter.
GetBuilder<UserChatController>(
key: Key(currentUserControllerTag),
tag: currentUserControllerTag,
global: false,
init: Get.find<UserChatController>(tag: currentUserControllerTag),
builder: (controller) {
return controller.user != null ? Container(
width: Get.width,
height: Dimensions.h100,
child: Stack(
children: [
Positioned(
left: 0,
right: 0,
child: Container(
height: Dimensions.h100,
width: double.maxFinite,
color: Colors.black,
child:Center(
child: Text(
controller.user != null ? controller.user!.name! : "",
style: TextStyle(
color: Colors.white
),
),
)
))
],
),
) : Container();
},
)

Lazy Loading prevent the search or filter in my app (flutter & firestore)

I am new with flutter,
I would be grateful if you could help me with this problem:
I have a huge set of firestore data that I have to display i a listview, so I had to use Lazy Loading when I used it, the problem appeared, and I can't search or filter in all the data, only the data shown
so I need to use lazy Load or pagination and in the same time can search or filter all the firestore data
enter image description here
and
enter image description here
void initState() {
_chatScrollController = ScrollController()
..addListener(() {
if (_chatScrollController!.position.atEdge) {
if (_chatScrollController!.position.pixels == 0)
;
else {
setState(() {
loadMoreMsgs = loadMoreMsgs + a;
});
}
}
});
super.initState();
}
stream: FirebaseFirestore.instance
.collection(kProductsCollection)
.limit(loadMoreMsgs)
.snapshots(),
builder: (context, snapshots) {
return (snapshots.connectionState == ConnectionState.waiting)
? const Center(
child: CircularProgressIndicator(),
)
: ListView.builder(
controller: _chatScrollController,
itemCount: snapshots.data!.docs.length,
itemBuilder: (context, index) {
var data = snapshots.data!.docs[index].data()
as Map<String, dynamic>;
List<Product> products = [];
for (var doc in snapshots.data!.docs) {
products.add(
Product(
pId: doc.id,
pName: doc.get(kProductName),
pPrice: doc.get(kProductPrice),
pUrl: doc.get(kProductUrl),
pIngredients: doc.get(kProductIngredients),
pCompany: doc.get(kProductCompany),
pDose: doc.get(kProductDose),
pCode: doc.get(kProductCode),
pClass: doc.get(kProductClass),
pCountry: doc.get(kProductCountry),
pDescription: doc.get(kProductDescription),
pPregnancyCategory:
doc.get(kProductPregnancyCategory),
),
);
}
if (products[index]
.pName
.toString()
.toLowerCase()
.contains(name.toLowerCase())) {
return Padding(
padding: const EdgeInsets.fromLTRB(20, 5, 20, 5),
child: GestureDetector(
onTap: () {
Navigator.pushNamed(context, ProductDetalis.id,
arguments: products[index]);
},
child: CardWidget(
width: width, height: height, data: data)),
);
}

Flutter PageView.builder load more and pull to refresh

i am working on a project where i am using PageView.builder which basically scroll vertically. i am loading video list using PageView.builder where user can see the videos (one video at a time) i want to add load more functionality. currently i am fetching 10 videos at a time from the server and loading it in PageView.builder, when user reaches last video i.e 10th video i want to load more 10 videos from server. moreover i want to refresh the list by pulling it down if it's first video. below is the code which i am using. Does anyone know how to achieve the desired
function? thanks in advance.
Stack createListView(BuildContext context, AsyncSnapshot snapshot)
{
videoDataList =snapshot.data;
_videoListController.init(
_pageController,
videoDataList,
);
tkController.addListener(
() {
if (tkController.value == TikTokPagePositon.middle) {
_videoListController.currentPlayer.start();
} else {
_videoListController.currentPlayer.pause();
}
},
);
return Stack(
// index: currentPage == null ? 0 : 1,
children: <Widget>[
RefreshIndicator(
child: PageView.builder(
key: Key('home'),
controller: _pageController,
pageSnapping: true,
physics: ClampingScrollPhysics(),
scrollDirection: Axis.vertical,
itemCount: _videoListController.videoCount,
itemBuilder: (context, i) {
// Put together a video component
var data = videoDataList[i];
bool isF = SafeMap(favoriteMap)[i].boolean ?? false;
var player = _videoListController.playerOfIndex(i);
//Right button bar
Widget buttons = TikTokButtonColumn(
profilePic: Glob.ITEM_BASE_URL+data.user_profile,
isFavorite: isF,
videoModel: data,
onAvatar: () {
tkController.animateToPage(TikTokPagePositon.right);
},
onFavorite: () {
setState(() {
favoriteMap[i] = !isF;
});
// showAboutDialog(context: context);
},
onComment: () {
_getCommentData(data.post_id);
},
onShare: () {},
);
// video
Widget currentVideo = Center(
child: FijkView(
player: player,
color: Colors.black,
panelBuilder: (_, __, ___, ____, _____) => Container(),
),
);
currentVideo = TikTokVideoPage(
hidePauseIcon: player.state != FijkState.paused,
aspectRatio: 9 / 16.0,
key: Key(Glob.ITEM_BASE_URL+data.post_video + '$i'),
tag: Glob.ITEM_BASE_URL+data.post_video,
bottomPadding: hasBottomPadding ? 16.0 : 16.0,
userInfoWidget: VideoUserInfo(
viewers: data.post_view_count,
desc: data.post_description,
userName: data.user_name,
fullname: data.full_name,
bottomPadding: hasBottomPadding ? 16.0 : 50.0,
// onGoodGift: () => showDialog(
// context: context,
// builder: (_) => FreeGiftDialog(),
// ),
),
onSingleTap: () async {
if (player.state == FijkState.started) {
await player.pause();
} else {
await player.start();
}
setState(() {});
},
onAddFavorite: () {
setState(() {
favoriteMap[i] = true;
});
},
rightButtonColumn: buttons,
video: currentVideo,
);
return currentVideo;
},
),
onRefresh: _getData,
),
Opacity(
opacity: 1,
child: currentPage ?? Container(),
),
// Center(
// child: Text(_currentIndex.toString()),
// )
],
);
}

How to deselect rest index with list in flutter?

I have a list of buttons in row , there are 4 items or buttons in list,
I have made a model class for creating data for each button, the list is model type.
all working fine, I want to highlight or select the button, on which I pressed and rest index button should be deselected.
I'm able to highlight the pressed button but unable to deselect the rest buttons.
code
//Button model class
class TopButtonModel{
String buttonLable;
bool isOnTp;
TopButtonModel({this.buttonLable, this.isOnTp});
}
//initializing list with these data
int myIndex=0;
List<TopButtonModel> buttons = [
TopButtonModel(
buttonLable: 'Skin',
isOnTp: true
),
TopButtonModel(
buttonLable: 'Hair Style',
isOnTp: false
),
TopButtonModel(
buttonLable: 'Makeup',
isOnTp: false
),
TopButtonModel(
buttonLable: 'Handset & Feet',
isOnTp: false
),
];
buttonsRow() {
return Container(
color: Colors.white,
child: ListView.builder(
// Rpadding: const EdgeInsets.only(right: 9),
scrollDirection: Axis.horizontal,
itemCount: buttons.length,
itemBuilder:(context, index) {
// myIndex =in
return Padding(
padding: const EdgeInsets.only(right: 9,top: 9),
child: FlatButton(
color: buttons[index].isOnTp?Colors.indigo:Colors.grey[200],
onPressed: () {
print(index);
setState(() {
myIndex =index;
buttons[index].isOnTp =true;
});
// if (buttons.any((item) => item.isOnTp)) {
// setState(() {
// buttons[index].isOnTp = !buttons[index].isOnTp;
// });
// }
},
child: Text(buttons[index].buttonLable,
style: TextStyle(color: buttons[index].isOnTp?Colors.white:Colors.black),
)),
);
}
),
) ;
}
wanna achieve this
and what is happening
This should be as simple as this:
setState(() {
buttons[myIndex].isOnTp = false;
myIndex = index;
buttons[index].isOnTp = true;
});
Here is a working code example: Code Pen

Flutter: How to manually set index for builder?

I'm currently stuck with setting the index here. I've tried various ways to set the index but the index's value cant be changed. This method is comes from the package :
https://pub.dev/packages/flutter_tindercard
Since I'm building cards, I might need to go back in index to properly sync with the back button which brings back the card. But the builder's index just keeps adding even if I perform a decrement inside the builder. This is the code I have of the builder:
Widget _cardBuild() {
return TinderSwapCard(
orientation: AmassOrientation.BOTTOM,
totalNum: articleList.length != null ? articleList.length + backCount : 0,
stackNum: 3,
swipeEdge: 1.0,
animDuration: 50,
maxWidth: MediaQuery.of(context).size.width * 0.9,
maxHeight: 410.1,
minWidth: MediaQuery.of(context).size.width * 0.8,
minHeight: 410,
cardBuilder: (context, index) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Conditional.single(
context: context,
conditionBuilder: (BuildContext context) => pendingBack > 0,
widgetBuilder: (BuildContext context) {
return _generateCards(cardIndex);
},
fallbackBuilder: (BuildContext context) {
return _generateCards(index);
},
),
);
},
cardController: controller = CardController(),
swipeUpdateCallback: (DragUpdateDetails details, Alignment align) {
/// Get swiping card's alignment
if (align.x < 0) {
//Card is LEFT swiping
} else if (align.x > 0) {
//Card is RIGHT swiping
}
},
swipeCompleteCallback: (CardSwipeOrientation orientation, int index) {
if (index == articleList.length) {
setState(() {
isOutOfCards = true;
});
} else {
setState(() {
cardIndex++;
});
}
},
);
}
A sample screenshot of the app:
[