Cross fade

This commit is contained in:
Rajarshee Chatterjee
2021-08-25 08:52:51 +05:30
parent e8785c2905
commit 4a0195762d
5 changed files with 230 additions and 108 deletions
+110
View File
@@ -0,0 +1,110 @@
import PropTypes from "prop-types";
import React, { PureComponent, Children } from "react";
import { View, Animated, StyleSheet } from "react-native";
export default class FadeView extends PureComponent {
static defaultProps = {
animationDuration: 225,
active: false,
removeHiddenSubviews: true,
};
static propTypes = {
animationDuration: PropTypes.number,
active: PropTypes.bool,
removeHiddenSubviews: PropTypes.bool,
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node,
]),
};
constructor(props) {
super(props);
this.renderChild = this.renderChild.bind(this);
this.mounted = false;
let { active } = this.props;
this.state = {
progress: new Animated.Value(Number(active)),
animating: false,
};
}
componentDidMount() {
this.mounted = true;
}
componentWillUnmount() {
this.mounted = false;
}
componentWillReceiveProps({ active, animationDuration }) {
let { progress } = this.state;
if (active ^ this.props.active) {
this.setState({ animating: true });
Animated.timing(progress, {
toValue: Number(active),
duration: animationDuration,
useNativeDriver: true,
}).start(() => {
if (this.mounted) {
this.setState({ animating: false });
}
});
}
}
renderChild(child, index) {
let { active, removeHiddenSubviews } = this.props;
let { animating, progress } = this.state;
let opacity = progress.interpolate({
inputRange: [0, 1],
outputRange: index ? [0, 1] : [1, 0],
});
let hidden = active ^ !!index;
if (removeHiddenSubviews) {
if (!animating && hidden) {
return null;
}
}
let pointerEvents = hidden ? "none" : "box-none";
return (
<Animated.View
style={[styles.container, { opacity }]}
pointerEvents={pointerEvents}
>
{child}
</Animated.View>
);
}
render() {
let { children, ...props } = this.props;
return (
<View {...props}>{Children.map(children, this.renderChild)}</View>
);
}
}
const styles = StyleSheet.create({
container: {
// ...StyleSheet.absoluteFillObject,
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
},
});
+16 -14
View File
@@ -2,6 +2,7 @@ import React, { useState } from "react";
import { View } from "react-native";
import { Appbar } from "react-native-paper";
import FadeView from "../../../components/Common/CrossFadeView";
import { bookmarkChapterAction } from "../../../redux/novel/novel.actions";
const ChapterAppbar = ({
@@ -16,19 +17,20 @@ const ChapterAppbar = ({
}) => {
const [bookmarked, setBookmarked] = useState(bookmark);
if (hide) {
return null;
} else {
return (
return (
<FadeView
style={{
flex: 1,
position: "absolute",
width: "100%",
top: 0,
zIndex: 1,
}}
active={hide}
animationDuration={150}
>
<View
style={{
position: "absolute",
flex: 1,
backgroundColor: `${theme.colorPrimary}E6`,
width: "100%",
top: 0,
zIndex: 1,
}}
style={{ flex: 1, backgroundColor: `${theme.colorPrimary}E6` }}
>
<Appbar.Header
style={{ backgroundColor: "transparent", elevation: 0 }}
@@ -58,8 +60,8 @@ const ChapterAppbar = ({
/>
</Appbar.Header>
</View>
);
}
</FadeView>
);
};
export default ChapterAppbar;
@@ -1,6 +1,7 @@
import React from "react";
import { Pressable, StyleSheet, View } from "react-native";
import { IconButton } from "react-native-paper";
import FadeView from "../../../components/Common/CrossFadeView";
const ChapterFooter = ({
hide,
@@ -22,10 +23,8 @@ const ChapterFooter = ({
radius: 50,
};
if (hide) {
return null;
} else {
return (
return (
<FadeView active={hide} animationDuration={150}>
<View
style={{
position: "absolute",
@@ -109,8 +108,8 @@ const ChapterFooter = ({
/>
</Pressable>
</View>
);
}
</FadeView>
);
};
export default ChapterFooter;
@@ -3,6 +3,7 @@ import { Dimensions, View, Text, StyleSheet } from "react-native";
import Slider from "@react-native-community/slider";
import { getDeviceOrientation } from "../../../services/utils/helpers";
import FadeView from "../../../components/Common/CrossFadeView";
const VerticalScrollbar = ({
theme,
@@ -22,84 +23,95 @@ const VerticalScrollbar = ({
setLoading(false);
};
if (hide) {
return null;
} else if (getDeviceOrientation() === "potrait") {
if (getDeviceOrientation() === "potrait") {
return (
<View
style={[
styles.verticalSliderContainer,
{ backgroundColor: `${theme.colorPrimary}E6` },
]}
<FadeView
style={{
position: "absolute",
zIndex: 2,
right: -(Dimensions.get("window").width / 2) + 40,
bottom: 300,
}}
active={hide}
animationDuration={150}
>
<Text
style={{
color: theme.textColorPrimary,
marginLeft: 16,
transform: [{ rotate: "-90deg" }],
}}
<View
style={[
styles.verticalSliderContainer,
{ backgroundColor: `${theme.colorPrimary}E6` },
]}
>
{scrollPercentage}
</Text>
<Slider
style={{
flex: 1,
height: 40,
}}
minimumValue={0}
maximumValue={100}
step={1}
value={scrollPercentage}
onSlidingComplete={onSlidingComplete}
thumbTintColor={theme.colorAccent}
minimumTrackTintColor={theme.colorAccent}
maximumTrackTintColor={theme.textColorPrimary}
/>
<Text
style={{
color: theme.textColorPrimary,
marginRight: 16,
transform: [{ rotate: "-90deg" }],
}}
>
100
</Text>
</View>
<Text
style={{
color: theme.textColorPrimary,
marginLeft: 16,
transform: [{ rotate: "-90deg" }],
}}
>
{scrollPercentage}
</Text>
<Slider
style={{
flex: 1,
height: 40,
}}
minimumValue={0}
maximumValue={100}
step={1}
value={scrollPercentage}
onSlidingComplete={onSlidingComplete}
thumbTintColor={theme.colorAccent}
minimumTrackTintColor={theme.colorAccent}
maximumTrackTintColor={theme.textColorPrimary}
/>
<Text
style={{
color: theme.textColorPrimary,
marginRight: 16,
transform: [{ rotate: "-90deg" }],
}}
>
100
</Text>
</View>
</FadeView>
);
} else {
return (
<View style={styles.horizontalSliderContainer}>
<Text
style={{
color: "#FFFFFF",
marginLeft: 16,
}}
>
{scrollPercentage}
</Text>
<Slider
style={{
flex: 1,
height: 40,
}}
minimumValue={0}
maximumValue={100}
step={1}
value={scrollPercentage}
onSlidingComplete={onSlidingComplete}
thumbTintColor={theme.colorAccent}
minimumTrackTintColor={theme.colorAccent}
maximumTrackTintColor={theme.textColorPrimary}
/>
<Text
style={{
color: "#FFFFFF",
marginRight: 16,
}}
>
100
</Text>
</View>
<FadeView active={hide} animationDuration={150}>
<View style={styles.horizontalSliderContainer}>
<Text
style={{
color: "#FFFFFF",
marginLeft: 16,
}}
>
{scrollPercentage}
</Text>
<Slider
style={{
flex: 1,
height: 40,
}}
minimumValue={0}
maximumValue={100}
step={1}
value={scrollPercentage}
onSlidingComplete={onSlidingComplete}
thumbTintColor={theme.colorAccent}
minimumTrackTintColor={theme.colorAccent}
maximumTrackTintColor={theme.textColorPrimary}
/>
<Text
style={{
color: "#FFFFFF",
marginRight: 16,
}}
>
100
</Text>
</View>
</FadeView>
);
}
};
@@ -108,11 +120,6 @@ export default VerticalScrollbar;
const styles = StyleSheet.create({
verticalSliderContainer: {
position: "absolute",
zIndex: 2,
right: -(Dimensions.get("window").width / 2) + 40,
bottom: 300,
backgroundColor: "rgba(0,0,0,0.7)",
flexDirection: "row",
justifyContent: "flex-end",
alignItems: "center",
@@ -124,7 +131,6 @@ const styles = StyleSheet.create({
position: "absolute",
zIndex: 2,
bottom: 100,
backgroundColor: "rgba(0,0,0,0.7)",
flexDirection: "row",
justifyContent: "flex-end",
alignItems: "center",
+15 -10
View File
@@ -44,6 +44,7 @@ import JumpToChapterModal from "./components/JumpToChapterModal";
import { Actionbar } from "../../components/Actionbar/Actionbar";
import EditInfoModal from "./components/EditInfoModal";
import { setCustomNovelCover } from "../../database/queries/NovelQueries";
import FadeView from "../../components/Common/CrossFadeView";
const Novel = ({ route, navigation }) => {
const item = route.params;
@@ -198,26 +199,29 @@ const Novel = ({ route, navigation }) => {
{ backgroundColor: theme.colorPrimaryDark },
]}
>
{selected.length > 0 ? (
<FadeView
style={{
position: "absolute",
zIndex: 1,
width: Dimensions.get("window").width,
elevation: 2,
}}
active={selected.length == 0}
animationDuration={150}
>
<View
style={{
backgroundColor: theme.colorPrimary,
position: "absolute",
zIndex: 1,
width: Dimensions.get("window").width,
paddingTop: StatusBar.currentHeight,
flexDirection: "row",
alignItems: "center",
paddingTop: StatusBar.currentHeight,
paddingBottom: 8,
elevation: 2,
}}
>
<Appbar.Action
icon="close"
color={theme.textColorPrimary}
onPress={() => {
setSelected([]);
}}
onPress={() => setSelected([])}
/>
<Appbar.Content
title={selected.length}
@@ -232,7 +236,8 @@ const Novel = ({ route, navigation }) => {
}}
/>
</View>
) : (
</FadeView>
{selected.length == 0 && (
<View
style={{
position: "absolute",