I have an app in which there is a common slider to display 2 different data values. And a button which controls the values to show (i.e. To use Array1 Or Array2).
Slider is displaying all values properly while doing back-n-forth in slider.
When I click the button, I update the state, Render gets called with correct Array to load from.
Issue: Slider starts from some random position. I want slider head to go to initial position.
Below is my slider code,
<Slider style={styleSliderView.slider}
minimumValue={0}
maximumValue={arr.length-1}
step={1}
onValueChange={(value)=>this._onValueChange(value)}/>
Any thoughts.
This is probably not just a random position. It's the new position at the new min/max range. What you need to do is somehow reset the slider.
You can try 2 possible solutions:
1) save the slider value in your state and reset it when the button is pressed:
<Slider
value={this.state.value}
onValueChange={(value) => this.setState({value})}
/>
onButtonPress() {
this.setState({value: 0});
}
2) reset the value using a ref to the slider:
<Slider
ref={r => this.slider = r}
/>
onButtonPress() {
this.slider.setNativeProps({value: 0});
}
Related
I would like to create a react-leaflet object dynamically. Normal leaflet objects work, but react-leaflet do not.
Code example on:
https://codesandbox.io/s/show-problem-react-leaflet-marker-popup-object-hm0o8?file=/src/MapView.js
Left click shows the desired behavior with leaflet objects and right click the problem with react-leaflet.
problem code:
var lat = e.latlng.lat;
var lon = e.latlng.lng;
// create popup contents
// use <Marker> from react-leaflet
var newMarker = <Marker position={[lat, lon]}>
{/* use Edit Popup */}
<Popup editable open>
Your stylable content here.
</Popup>
</Marker>;
// Problem addTo(map)
newMarker.addTo(map);
newMarker is a react element. You can't call the leaflet method addTo on it, because it is not a leaflet L.Marker instance.
If you want to be able to manage the markers through react, you would need to keep a state variable which is an array of coordinates. On map click, you can add the coordinate to that array, and then render a series of <Marker /> elements from that.
In your event handlers, you're simply going to capture the position of the click and pass it to a callback setMarkers:
function MyRightClickEventHandler({ setMarkers }) {
useMapEvents({
contextmenu: (e) => {
setMarkers(e.latlng);
}
});
return null;
}
setMarkers is a callback to setState on your primary MapView component, which adds the latlng to the state variable, which contains an array of latlngs:
// inside you'r MapContainer:
<MyRightClickEventHandler
setMarkers={(markers) =>
this.setState({
MarkerArray: [...this.state.MarkerArray, markers]
})
}
/>
Then map over the latlngs that are in that state variable, if there are any:
{this.state.MarkerArray &&
this.state.MarkerArray.map((latlng) => (
<Marker position={latlng}>
<Popup editable removable>
Thanks for using my editable popup plugin!
</Popup>
</Marker>
))}
Working codesandbox
Note that if you're going to use the editable, removable, or open props on editable popups rendered dynamically from an array, be sure to read my section on using editable popups rendered from a dynamic state array - it can get hairy if you're not careful. Feel free to ask questions in the comments if you run into problems.
I want to create a component as seen in the image attached. The circle is a progress bar and the blue colour is the progress, I could use a circular progress bar component for that but I'm not sure how can I show dates as seen in the image, the text in blue will be the current date. If anyone knows how to do this please help.
Edit: I want to add the date to the progress bar, I have found the circular progress bar component.
This is called Circular Progress
Usage
import { AnimatedCircularProgress } from 'react-native-circular-progress';
<AnimatedCircularProgress
size={120}
width={15}
fill={100}
tintColor="#00e0ff"
onAnimationComplete={() => console.log('onAnimationComplete')}
backgroundColor="#3d5875" />
You can also define a function that'll receive current progress and for example display it inside the circle:
<AnimatedCircularProgress
size={200}
width={3}
fill={this.state.fill}
tintColor="#00e0ff"
backgroundColor="#3d5875">
{
(fill) => (
<Text>
{ this.state.fill }
</Text>
)
}
</AnimatedCircularProgress>
You can also define a function that'll receive the location at the top of the progress circle and render a custom SVG element:
<AnimatedCircularProgress
size={120}
width={15}
fill={100}
tintColor="#00e0ff"
backgroundColor="#3d5875"
padding={10}
renderCap={({ center }) => <Circle cx={center.x} cy={center.y} r="10" fill="blue" />}
/>
Finally, you can manually trigger a duration-based timing animation by putting a ref on the component and calling the animate(toValue, duration, easing) function like so:
<AnimatedCircularProgress
ref={(ref) => this.circularProgress = ref}
...
/>
this.circularProgress.animate(100, 8000, Easing.quad); // Will fill the progress bar linearly in 8 seconds
The animate-function returns the timing animation so you can chain, run in parallel etc.
This is what you are looking for...
https://github.com/JesperLekland/react-native-svg-charts
It is ProgressCircle. hope help You...
Im having a strange issue where manually blurring and input in one spesific case will not work.
If i click the first input, then focus the second input by using the submit key on the keyboard, the onChangeText function on the second input will blur when text length reaches 2.
But if i focus the second input while the fist input is focused by clicking directly on it, the blur method called in the onChangeText will not blur the second input, and the keyboard will remain open.
onChangeText(text) {
if(text.length === 2) this.secondInput.blur();
}
onSubmitFirst() {
this.firstInput.blur();
this.secondInput.focus();
}
render() {
return (
<TextInput ref={ref => {this.firstInput = ref} onSubmitEditing={this.onSubmitFirst}/>
<TextInput ref={ref => {this.secondInput = ref} onChangeText={this.onChangeText}/>
)
}
I have also tried with Keyboard.dismiss(); dismissKeyboard(); neither will blur the second input if it was focused while the first input was also focused. I need to be able to blur this input by code to prevent the keyboard from remaining open.
EDIT
It seems .blur() will only work if .focus() has been called manually.
If i add onBlur={() => this.secondInput.focus()} to the first textinput the .blur() method will work even if im jumping to the next input by clicking on it
I want to have a functionality similar to Google Inbox (demo), when swiping an item causes a change of the background color and size of the icon.
My implementation has a ListView of Swipeable components as rows and I want to change the content or style of a row (in the right pane for example) based on the swipe position.
In order to have the ListView to re-render while swiping I added a pos state which I set using the onPanAnimatedValueRef prop of the Swipeable.
The problem is that the ListView doesn't re-render and nothing changes.
<ListView
...
renderRow={(data) => (
<Swipeable rightContent={
<View><Text>{this.state.pos}</Text></View>
}
...
onPanAnimatedValueRef={(pan) => {
pan.addListener(val => {
this.setState({
pos: val.x
});
}}>
{data}
</Swipeable>
)}
/>
Do you see any problem with this?
I would wrap the Swipeable in your own component, hold state there and your animation logic. It is not the ListView's responsibility to rerender the whole thing since the data hasn't changed, just your row itself.
Alternatively, you could change the data via setState to the ListView's data source (which presumably was based in state and hence force a rerender but this is a less efficient path)
I want a row in a FlatList to scroll to the top of the screen whenever a user clicks on it. I am currently doing this by using the scrollToIndex method but the problem is that I have to animate the top margin (from 10 to 0) to get it flushed to the top of the screen. I also have an issue where if a user clicks on a row to expand the row, and a previous row was already expanded, the previous row will collapse causing the original scrollToIndex to animate to some position off the top of the screen.
My current two alternatives are to trigger an additional scrollToIndex once the previous row finishes contracting or use scrollToOffset to figure out where to scroll to based on good old math values. Is there a way to figure out row offset positions by index or some other value whenever it is clicked?
Thanks for any help anybody might be able to provide!
You can use scrollToItem to achieve what you are trying to achieve
So suppose you have this FlatList component
<FlatList
ref={(ref) => { this._flatList = ref; }}
data = {dataSourche}
renderItem = {( info: {item:item, index:number}) => this._renderFlatListItem(info.item, info.index)}
keyExtractor = {(item) => item.id}
decelerationRate={0}
snapToInterval={cardHeight}
snapToAlignment={"start"} //Can also be 'center' or 'end'
onMomentumScrollEnd = {(event) => this._onMomentumScrollEnd(event)}
getItemLayout = {this.getItemLayout}/>
You will need to define a method getItemLayout that will tell the flatList 3 things
length: In your case height of the card
offset: this is distance from top of the list to current card usually we can set it as length * index of the card
index of the card
so this is a sample getItemLayout which you can refer to
getItemLayout = (data, index) => (
{ length: 170, offset: 170 * index, index }
);
Next will be your FlatList scrollToItem call
this._flatList.scrollToItem({
animated:true, //can also be false
item:item,
viewPosition:0 //this is the first position that is currently attached to the window
})
Instead of trying to figure out where to scroll to using the scrollToOffset method, I'm still using the scrollToIndex method and use the viewOffset parameter in order to calculate how much offset to add to the method: the difference between the expanded and collapsed heights of any other currently expanded item (if any) and subtracting the top margin of the clicked item.