Slide-up view in Flutter - mobile

I'm trying to make something similar to google/apple maps screen in flutter. I just started experimenting in Flutter and I have a hard time understand that "Draggable widget". Could someone give me example code how they made their slide-up view, I can learn from? I can't find any.

There's also the sliding_up_panel Flutter library you could use to implement the same sort of design that Google/Apple Maps uses.

Draggable (and DragTarget) is not used for what you call slide-up view
slide-up view, from the android world, is for bottom aligned modals.
Draggable is to transfer data using Drag&Drop.
In flutter, bottom modals are fairly simple :
First, make sure you have somewhere above in your tree a Scaffold. As it's what will position everything together.
Then, call either showBottomSheet or showModalBottomSheet with whatever content you like. The content will now automatically appear at the bottom of your screen.
That's it, your job is done ! You can optionally now add a custom close event. For this, you'll just have to call Navigator.pop(context).
But both modal and non-modal bottom sheet can be closed out of the box using common gestures. Such as back button, navbar back, of click outside.
Full example :
class MyExample extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(title: new Text('Example')),
body: new Center(
child: new Builder(builder: (context) {
return new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new RaisedButton(
onPressed: () => modal(context),
child: new Text("modal"),
),
new RaisedButton(
onPressed: () => showSlideupView(context),
child: new Text("non modal"),
),
],
);
}),
),
),
);
}
void showSlideupView(BuildContext context) {
showBottomSheet(
context: context,
builder: (context) {
return new Container(
child: new GestureDetector(
onTap: () => Navigator.pop(context),
child: new Text("Click me to close this non-modal bottom sheet"),
),
);
});
}
modal(BuildContext context) {
showModalBottomSheet(
context: context,
builder: (context) {
return new Container(
child: new Text("This is a modal bottom sheet !"),
);
});
}
}

Now you can use Sliding Up Panel plugin to do that, its awesome.

As an alternative: From the docs https://api.flutter.dev/flutter/material/showModalBottomSheet.html
Widget build(BuildContext context) {
return Center(
child: ElevatedButton(
child: const Text('showModalBottomSheet'),
onPressed: () {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
color: Colors.amber,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text('Modal BottomSheet'),
ElevatedButton(
child: const Text('Close BottomSheet'),
onPressed: () => Navigator.pop(context),
)
],
),
),
);
},
);
},
),
);
}

Related

Mui Datagrid not populating, data is there

I have a few Mui datagrids through my app. I recently switched over to using RTK Query for the api and was able to get all the grids functioning and displaying fine. I honestly do not know what changed (since it took place after I was done mucking with the grid components and was adjusting the auth/login to RTK) but 3 of the 4 are displaying an empty grid with no errors. I can console the data, and even the corner of the grids shows the total number of entries, which reflects the changes if I add an item to the array that should be displayed by the grid. I already had the container components set to display: flex and set autoHeight and autoWidth on the grids. I've tried adjusting the containers, even putting height to 5000, with no change. As I mentioned, I have 1 that still displays correctly, and even copying the display props for that grid to the others had no effect.
import React from 'react';
import PropTypes from 'prop-types';
import { DataGrid, GridActionsCellItem } from '#mui/x-data-grid';
import { Link } from 'react-router-dom';
import { useGetVisitsByUserIdQuery } from '../../redux/apiSlice';
import { CircularProgress, Box } from '#mui/material';
const UserVisits = ({ user }) => {
const userId = user._id
const {
data,
isLoading,
isSuccess
} = useGetVisitsByUserIdQuery(userId);
console.log(data)
const columns =
[
{
field: 'client',
headerName: 'Client',
width: 150,
renderCell: (params) => {
return (
<Link to={`/ClientChart/${params?.value?._id}`}>{params?.value?.fullName}</Link>
)}
},
{
field: 'visitStart',
headerName: 'Start Time',
type: 'date',
width: 200,
valueFormatter: (params) => {
const date = new Date(params.value);
let options = {
year: "numeric",
month: "numeric",
day: "numeric"
};
return date.toLocaleTimeString("en-US", options);
}
},
{
field: 'visitEnd',
headerName: 'End Time',
type: 'date',
width: 200,
valueFormatter: (params) => {
const date = new Date(params.value);
let options = {
year: "numeric",
month: "numeric",
day: "numeric"
};
return date.toLocaleTimeString("en-US", options);
}
},
{field: 'location', headerName: 'Location', width: 150},
];
let content
if (isLoading) {
content = <CircularProgress />
} else if (isSuccess) {
content =
<div style={{ display: 'flex', height: '100%'}}>
<Box sx={{ flexGrow: 1 }}>
{ data &&
<DataGrid
autoHeight
autoWidth
getRowId={(row) => row.id}
rows={data}
columns={columns}
rowsPerPageOptions={[20, 50, 100]}
autoPageSize
//sx={{ height: '100%', width: '100%' }}
/>}
</Box>
</div>
}
return (
<div>
<h1>Visits</h1>
<div>
{content}
</div>
</div>
)
}
If I push new data to the grid, the number of entries in the bottom right corner adjusts, and the console shows the correct array of data, as well as Redux DevTools showing the data in state. Even manually adjusting the height of the div/Box containing the grid, the grid itself never changes in height.
Again they had been working perfectly, and I'm at a total loss as to what would have affected them. Any help is greatly appreciated.
Thanks
So the issue was resolved by removing 'autoPageSize' from the Datagrid props. Playing with it, it seems that autoHeight and autoPageSize cause the grid to break when in place together.
Could not find any specific references online to this being an issue, but I was able to recreate the issue on this codesandbox I found: https://codesandbox.io/s/datagrid-v5-0-1-autoheight-autopagesize-9dy64?file=/src/App.tsx
If you add in autoPageSize to the datagrid props, the grid goes empty.

Why Cloud Firestore updates so much? [duplicate]

This question already has an answer here:
Firestore - unexpected reads
(1 answer)
Closed 2 years ago.
I'm working on a project for a logistics warehouse.
The idea is that I use Cloud Firestore for store pallets in a rack and that I can find it back in the system.
I can see my pallets in the app and it works well.
Cloud Firestore has a read amount of 50.000 reads per day.
If I start up the app it calculates the number of documents in the list and I can see it in the usage tab.
That's okay but even if I do nothing in the app, the number increases.
Is there a solution to read the data only if the flutter page opens?
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class overzicht extends StatefulWidget {
#override
_overzichtState createState() => _overzichtState();
}
class _overzichtState extends State<overzicht> {
Future _data;
Future getPosts() async{
var firestore = Firestore.instance;
QuerySnapshot qn = await firestore.collection("locaties").getDocuments();
return qn.documents;
}
#override
void initState() {
super.initState();
_data = getPosts();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Center(child: Text('Overzicht')),backgroundColor: Color.fromRGBO(17, 32, 42, 1),),
body: Container(
child: FutureBuilder(
future: _data,
builder: (_, snapshot) {
if(snapshot.connectionState == ConnectionState.waiting){
return Center(
child: Text('Loading...'),
);
} else{
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (_, index){
return ListTile(
title: Text(snapshot.data[index].data["location"]),
);
});
}
}),
),
);
}
}
This has been answered before here:
If you leave the console open on a collection/document with busy write activity, the console will automatically read the changes that update the console's display. This is very often the source of unexpected reads.

electron-react-boilerplate :sub window on clicking a button

i have a doubt that how the reactjs file can be loaded into a new window on
clicking a button in electron-react-boilerplate.
const handleVideoCall=()=>{
const remote=require('electron').remote;
const BrowserWindow=remote.BrowserWindow;
const win = new BrowserWindow({
height: 600,
width: 800,
});
win.loadFile(fileName);
}
handleVideoCall is the method which is called on clicking the button.
FileName is the reactjs file that i needed to open.
As there is no documentation from react-electron-boilerplate i was stuck with this. Any help is appreciable.
i got the answer i think that this will be helpful for lot of peoples as there are no documentation for electron-react-boilerplate.
Make the nodeIntegration to true or preload js.
const handleVideoCallNew = async number => {
const remote=require('electron').remote;
const BrowserWindow=remote.BrowserWindow;
const win = new BrowserWindow({
height: 600,
width: 800,
frame:false,
webPreferences: {
nodeIntegration: true,
}
});
win.loadURL(`file://${__dirname}/app.html#/login`);
}
And on the router file
<Route path="/login" component={Login} />
By using this code we can open the reactjs file and route to login. The app.html is main file which is loaded in main.dev.js in electron-react-boilerplate code. The hashing is simplest method to open the reactjs file.
As the loadURL in electron only loads urls and htmls files we can't open js files. So open the main app.html and hash using routes.
Just create a react videoCall Component then create a window and load a url with query params like this,
const videoCallWidow = new BrowserWindow({
height: 600,
width: 800,
webPreferences: {
nodeIntegration: true,
webSecurity: false,
},
})
videoCallWidow.loadURL(
url.format({
pathname: path.join(__dirname, '../build/index.html'),
protocol: 'file:',
slashes: true,
query: {
page: 'videoCall',
},
})
)
after that, In your index.js file you will get query params so on that you can put a condition to load videoCall Component or app component .
ReactDOM.render(
locationPath === 'videoCall' ? <videoCallComponent /> : <App />,
document.getElementById('root')
)

Flutter: checkBox onChanged

I was trying to implement a checkbox that would disable and enable a button. But I was blocked by this following error:
I/flutter (19999): The following assertion was thrown building DisclaimerPage(dirty, state: DisclaimerPageState#24b3d):
I/flutter (19999): setState() or markNeedsBuild() called during build.
I/flutter (19999): This Overlay widget cannot be marked as needing to build because the framework is already in the
I/flutter (19999): process of building widgets. A widget can be marked as needing to be built during the build phase
I/flutter (19999): only if one of its ancestors is currently building. This exception is allowed because the framework
I/flutter (19999): builds parent widgets before children, which means a dirty descendant will always be built.
I/flutter (19999): Otherwise, the framework might not visit this widget during this build phase.
Here is my code for building the page:
class DisclaimerPageState extends State<DisclaimerPage> {
bool checkBoxValue = false;
#override
Widget build(BuildContext context) {
var _floatButtonOnPressed;
if (checkBoxValue) {
_floatButtonOnPressed = navToHome();
}
return new Scaffold(
appBar: AppBar(
title: Text("Disclaimer"),
leading: Container(),
),
body: Container(
child: Card(
child: Column(
children: <Widget>[
Text("ADHJASDKHKDAD"),
Row(
children: <Widget>[
Checkbox(
value: checkBoxValue,
onChanged: (bool newValue) {
setState(() {
checkBoxValue = newValue;
});
}),
Text("I understand"),
],
),
],
),
),
),
floatingActionButton: FloatingActionButton.extended(
onPressed: _floatButtonOnPressed,
label: Text("PROCEED"),
icon: Container(),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
navToHome() {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ImmunityHomePage(title: 'ImMUnity')),
);
}
}
Am I doing something wrong? My checkbox implementation is based on the documentation of checkbox.dart. So I am a little confused here. Help is appreciated. Thank you so much!
Instead of checking checkBoxValue & setting onPressed, you should check checkBoxValue inside your on press function then manage navigation.
SO first remove this
if (checkBoxValue) {
_floatButtonOnPressed = navToHome();
}
Then update onPressed of floating action button as
onPressed: (){navToHome();},
Then update you navToHome() function
navtoHome(){
if(checkValue){
//your navigation code here
}
}

React-leaflet how to resetStyle

I'm following Leaflet's Choropleth tutorial
http://leafletjs.com/examples/choropleth.html
and using react-leaflet.
I managed to setStyle without any modification from the original source code and it works.
highlightFeature(e) {
var layer = e.target;
layer.setStyle({
weight: 5,
color: '#666',
dashArray: '',
fillOpacity: 0.7
});
}
The layer has a setStyle property. Now to resetStyle that I'm having propblems.
I tried to access it with
resetHighlight(e) {
this.refs.geojson.resetStyle(e.target);
}
while having GeoJson
<GeoJson
ref="geojson"
data={this.state.data}
style={this.getStyle.bind(this)}
onEachFeature={this.onEachFeature.bind(this)}
/>
but it it doesn't have resetStyle property
Anyone can suggest another way of resetting the style in react-leaflet ?
The solution was to access the leafletElement of geojson which has resetStyle
resetHighlight(e) {
this.refs.geojson.leafletElement.resetStyle(e.target);
}
react-leaflet-choropleth is a way to handle choropleth if you are not wanting to write it from scratch. It is based off of the leaflet-choropleth plugin
import Choropleth from 'react-leaflet-choropleth'
import { Map } from 'react-leaflet'
const style = {
fillColor: '#F28F3B', //default color filll
weight: 2, //normal styling
opacity: 1,
color: 'white',
dashArray: '3',
fillOpacity: 0.5
}
const map = (geojson) => (
<Map>
<Choropleth
data={{type: 'FeatureCollection', features: geojson} /*feature collection or array*/}
valueProperty={(feature) => feature.properties.value /*value for choropleth*/}
visible={(feature) => feature.id !== active.id /*use choropleth color?*/}
scale={['#b3cde0', '#011f4b'] /*color range*/}
steps={7 /*how many different colors to use?*/}
mode={'e' /*use equadistance mode, others include kmeans and quantile*/}
style={style}
onEachFeature={(feature, layer) => layer.bindPopup(feature.properties.label)}
ref={(el) => this.choropleth = el.leafletElement /*get the geojson's layer container*/}
/>
</Map>
)
ReactDom.render(<map geojson={...} />, document.body)

Resources