react-native#findNodeHandle JavaScript Examples

The following examples show how to use react-native#findNodeHandle. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: budget.js    From actual with MIT License 6 votes vote down vote up
componentDidUpdate(prevProps) {
    if (prevProps.editing !== this.props.editing) {
      if (this.props.editing && ACTScrollViewManager) {
        ACTScrollViewManager.setFocused(findNodeHandle(this.container));
      }
    }

    if (prevProps.editMode !== this.props.editMode) {
      Animated.timing(this.opacity, {
        toValue: this.props.editMode ? 0 : 1,
        duration: 200,
        easing: Easing.inOut(Easing.ease)
      }).start();
    }
  }
Example #2
Source File: useNodeHandle.js    From react-native-tv-demo with MIT License 6 votes vote down vote up
useNodeHandle = (ref) => {
  const [nodeHandle, setNodeHandle] = useState(null);

  useEffect(() => {
    if (ref.current) {
      setNodeHandle(findNodeHandle(ref.current));
    }
  }, [ref.current]);

  return nodeHandle;
}
Example #3
Source File: dragdrop.js    From actual with MIT License 5 votes vote down vote up
export function Droppable({ type, onDrop, getActiveStatus, children }) {
  let context = useContext(DragDropContext);
  let element = useRef(null);
  let id = useState(Math.random().toString());

  // TODO: This effect is missing deps, need to figure out how to
  // optimize
  useEffect(() => {
    let unregister = context.registerDroppable(id, {
      acceptedTypes: Array.isArray(type) ? type : [type],
      onDrop: onDrop,
      onMeasure: measure,
      getActiveStatus
    });

    return unregister;
  }, []);

  function measure() {
    if (element.current) {
      let el = element.current.getNode
        ? element.current.getNode()
        : element.current;
      el.measureLayout(
        findNodeHandle(context.container.current),
        (x, y, width, height) => {
          context.updateDroppable(id, {
            layout: { x, y, width, height }
          });
        }
      );
    }
  }

  let { currentDropping } = context;

  return (
    <View onLayout={measure} ref={element}>
      {children({
        activeStatus:
          currentDropping &&
          currentDropping.droppable.id === id &&
          currentDropping.status
      })}
    </View>
  );
}
Example #4
Source File: findNodeID.js    From react-native-tv-demo with MIT License 5 votes vote down vote up
findNodeID = (component) => {
  const handle = findNodeHandle(component);
  if (Platform.OS === 'web') {
    return handle.getAttribute('id');
  } else {
    return handle;
  }
}
Example #5
Source File: pull_view.rn.jsx    From taro-form with MIT License 4 votes vote down vote up
componentDidMount() {
    const { side = 'bottom', overlayOpacity = 0.5 } = this.props
    const position = {}
    const { positionOther } = this.state
    if (process.env.TARO_ENV === 'rn') {
      // RN端动画
      setTimeout(() => {
        const handle = findNodeHandle(this.anRef)
        UIManager.measureInWindow(handle, (x, y, width, height) => {
          const { animationRoot } = this.state
          switch (side) {
            case 'left':
              position.top = 0
              position.bottom = 0
              positionOther.left = width
              break
            case 'right':
              position.top = 0
              position.bottom = 0
              positionOther.right = width
              break
            case 'top':
              position.left = 0
              position.right = 0
              positionOther.top = height
              break
            case 'bottom':
              position.left = 0
              position.right = 0
              positionOther.bottom = height
              break
          }

          this.setState({
            styleRn: StyleSheet.create({
              position,
              other: positionOther
            })
          })
          Animated.timing(
            animationRoot,
            {
              toValue: 1,
              duration: this.animatedTime,
              useNativeDriver: false
            }
          ).start()
        })
      }, 100)
    } else {
      // 小程序和h5动画
      this.animated = Taro.createAnimation({
        transformOrigin: "50% 50%",
        duration: this.animatedTime,
        timingFunction: "ease-out",
        delay: 0
      })
      this.query = Taro.createSelectorQuery().in(process.env.TARO_ENV === 'h5' ? this : this.$scope)
      this.query.select('.pull-view__main').boundingClientRect(res => {
        switch (side) {
          case 'left':
            position.top = 0
            position.bottom = 0
            positionOther.left = res.width + "px"
            break
          case 'right':
            position.top = 0
            position.bottom = 0
            positionOther.right = res.width + "px"
            break
          case 'top':
            position.left = 0
            position.right = 0
            positionOther.top = res.height + "px"
            break
          case 'bottom':
            position.left = 0
            position.right = 0
            positionOther.bottom = res.height + "px"
            break
        }
        this.setState({
          position,
          positionOther
        }, () => {
          this.setState({
            animationMain: this.animated[side](0).opacity(1).step().export(),
            animationRoot: this.animated.backgroundColor(`rgba(0, 0, 0, ${overlayOpacity})`).step().export()
          })
        })
      }).exec()
    }
  }
Example #6
Source File: dragdrop.js    From actual with MIT License 4 votes vote down vote up
export function DragDrop({ makeHighlight, children, style }) {
  let x = useMemo(() => new Animated.Value(0), []);
  let y = useMemo(() => new Animated.Value(0), []);
  let ax = useMemo(() => new Animated.Value(0), []);
  let ay = useMemo(() => new Animated.Value(0), []);
  let scrollRef = useRef(null);
  let container = useRef(null);
  let containerBounds = useRef(null);
  let [currentDropping, setCurrentDropping] = useState(null);
  let [dragState, setDragState] = useState(null);
  let draggable = useRef(null);
  let scrollY = useRef(0);

  let lastDragArgs = useRef(null);

  let onDragMove = useCallback(([x, y]) => {
    if (draggable.current) {
      lastDragArgs.current = [x, y];

      let { droppable, status } = getDroppableInArea(
        [x, y],
        draggable.current.type
      );
      if (
        droppable &&
        (!currentDropping ||
          droppable.id !== currentDropping.droppable.id ||
          status !== currentDropping.status)
      ) {
        setCurrentDropping({ droppable, status });
      }

      let relY = y - containerBounds.current.y;
      let { height } = containerBounds.current;

      if (relY < 100) {
        requestAnimationFrame(() => {
          scrollRef.current
            .getNode()
            .scrollTo({ y: scrollY.current - 4, animated: false });
        });
      } else if (relY > height - 100) {
        requestAnimationFrame(() => {
          scrollRef.current
            .getNode()
            .scrollTo({ y: scrollY.current + 4, animated: false });
        });
      }
    }
  }, []);

  let onGestureEvent = Animated.event([
    {
      nativeEvent: ({
        absoluteX,
        absoluteY,
        translationX: tx,
        translationY: ty,
        state
      }) =>
        A.block([
          A.cond(A.eq(state, State.ACTIVE), [
            A.set(x, tx),
            A.set(y, ty),
            A.set(ax, absoluteX),
            A.set(ay, absoluteY),

           A.call([ax, ay], onDragMove),
          ])
        ])
    }
  ]);

  function onContainerLayout() {
    container.current.measureInWindow((x, y, width, height) => {
      containerBounds.current = { x, y, width, height };
    });
  }

  let onHandlerStateChange = useCallback(e => {
    if (e.nativeEvent.state === State.ACTIVE) {
      setDragState('dragging');
    }
  }, []);

  // Managing drag state
  let onDrag = useCallback((id, type, el, preview) => {
    if (container && preview) {
      el = el.getNode ? el.getNode() : el;
      el.measureLayout(
        findNodeHandle(container.current),
        (x, y, width, height) => {
          draggable.current = {
            id,
            type,
            bounds: { x, y: y - scrollY.current, width, height },
            preview
          };
          setDragState('pending');
        }
      );

      droppables.current.forEach(d => d.onMeasure());
    }
  }, []);
  let onDragStart = (id, type, container, preview) => {
    onDrag(id, type, container, preview);
  };
  let onDragEnd = () => {
    if (draggable.current && currentDropping) {
      let { droppable, status } = currentDropping;
      droppable.onDrop(
        draggable.current.id,
        draggable.current.type,
        droppable,
        status
      );
    }

    draggable.current = null;
    setDragState(null);
    setCurrentDropping(null);
    x.setValue(0);
    y.setValue(0);
  };

  // Handle scrolling
  function onScroll(e) {
    scrollY.current = e.nativeEvent.contentOffset.y;

    if (dragState === 'dragging' && lastDragArgs.current) {
      onDragMove(lastDragArgs.current);
    }
  }

  // Droppables
  let droppables = useRef([]);

  function getDroppableInArea([x, y], type) {
    if (!containerBounds.current) {
      return null;
    }

    x -= containerBounds.current.x;
    y -= containerBounds.current.y - scrollY.current;

    let droppable = droppables.current.find(({ acceptedTypes, layout }) => {
      return (
        acceptedTypes.indexOf(type) !== -1 &&
        layout &&
        x >= layout.x &&
        y >= layout.y &&
        x <= layout.x + layout.width &&
        y <= layout.y + layout.height
      );
    });

    if (droppable) {
      let { layout, getActiveStatus } = droppable;

      if (getActiveStatus) {
        let status = getActiveStatus(x, y, droppable, draggable.current || {});
        if (status) {
          return { droppable, status, position: { x, y } };
        }
      } else {
        return { droppable, status: true, position: { x, y } };
      }
    }
    return {};
  }

  function registerDroppable(id, events) {
    droppables.current = [
      ...droppables.current,
      {
        id,
        ...events,
        layout: { x: 0, y: 0, width: 0, height: 0 }
      }
    ];

    return () => {
      unregisterDroppable(id);
    };
  }

  function unregisterDroppable(id) {
    droppables.current = droppables.current.filter(d => d.id !== id);
  }

  function updateDroppable(id, data) {
    droppables.current = droppables.current.map(d => {
      if (d.id === id) {
        return { ...d, ...data };
      }
      return d;
    });
  }

  return (
    <DragDropContext.Provider
      value={{
        onDragStart,
        onDragEnd,
        container,
        dragging: dragState === 'dragging',

        registerDroppable,
        updateDroppable,
        unregisterDroppable,
        currentDropping
      }}
    >
      <View ref={container} onLayout={onContainerLayout} style={{ flex: 1 }}>
        {children({
          dragState,
          scrollRef,
          onScroll,
          onGestureEvent,
          onHandlerStateChange
        })}

        <Preview
          draggable={draggable.current}
          x={x}
          y={y}
          pending={dragState === 'pending'}
        />
      </View>
    </DragDropContext.Provider>
  );
}
Example #7
Source File: FlatListDemo.js    From react-native-tv-demo with MIT License 4 votes vote down vote up
FlatListDemo = () => {
  const flatListRef = useRef();

  useEffect(() => {
    if (Platform.OS === 'web' && flatListRef.current) {
      let node = findNodeHandle(flatListRef.current);
      if (node) {
        // Set FlatList spatial navigation action as focus to avoid scroll on up
        node.style.setProperty('--spatial-navigation-action', 'focus');
      }
    }
  }, []);

  function onItemFocus(e, item) {
    // Get row
    const row = Math.floor(item.index / COLS);
    // Get styles
    const rowsStyle = StyleSheet.flatten(styles.rows);
    const rowItemStyle = StyleSheet.flatten(styles.rowItem);
    // Get rows width / height
    const rowsHeight = rowsStyle.height;
    // Get item width / height
    const itemHeight = rowItemStyle.height + rowItemStyle.margin * 2;
    // Get vertical offset for current row in rows
    const itemTopOffset = itemHeight * row;
    // Scroll vertically to current row
    const rowsHeightHalf = rowsHeight / 2;
    if (itemTopOffset >= rowsHeightHalf - itemHeight) {
      flatListRef.current.scrollToOffset({
        offset: itemTopOffset,
        animated: true,
      });
    } else {
      flatListRef.current.scrollToOffset({offset: 0, animated: true});
    }
  }

  function renderItem(item) {
    const flatListItem = item.item;
    const key = 'flatlist_item_' + flatListItem.index;
    return (
      <FocusableHighlight
        onPress={() => {}}
        onFocus={(e) => {
          onItemFocus(e, item);
        }}
        underlayColor={Style.buttonFocusedColor}
        style={styles.rowItem}
        nativeID={key}
        key={key}>
        <Text style={styles.text}>{flatListItem.index}</Text>
      </FocusableHighlight>
    );
  }

  function getData() {
    // Load data
    let data = [];
    for (let i = 0; i < COLS * ROWS; i++) {
      data.push({index: i});
    }
    return data;
  }

  // Get row item height
  const rowItemStyle = StyleSheet.flatten(styles.rowItem);
  const rowItemHeight = rowItemStyle.height;

  // Render
  return (
    <View style={Style.styles.content}>
      <FlatList
        ref={flatListRef}
        style={styles.rows}
        nativeID={'flatlist'}
        data={getData()}
        renderItem={renderItem}
        numColumns={COLS}
        keyExtractor={(item) => item.index}
        getItemLayout={(data, index) => {
          return {length: rowItemHeight, offset: rowItemHeight * index, index};
        }}
        showsVerticalScrollIndicator={false}
      />
    </View>
  );
}
Example #8
Source File: ScrollViewDemo.js    From react-native-tv-demo with MIT License 4 votes vote down vote up
ScrollViewDemo = () => {
  const rowsRef = useRef(null);
  const rowRefs = useRef([]);

  function onItemFocus(e, row, item) {
    if (!rowRefs.current) {
      return;
    }
    if (row >= 0 && row < rowRefs.current.length) {
      // Check refs
      const rowRef = rowRefs.current[row];
      if (!rowRef || !rowsRef) {
        return;
      }
      // Get styles
      const rowsStyle = StyleSheet.flatten(styles.rows);
      const rowItemStyle = StyleSheet.flatten(styles.rowItem);
      // Get rows width / height
      const rowsWidth = rowsStyle.width;
      const rowsHeight = rowsStyle.height;
      // Get item width / height
      const itemWidth = rowItemStyle.width + rowItemStyle.margin * 2;
      const itemHeight = rowItemStyle.height + rowItemStyle.margin * 2;
      // Get horizontal offset for current item in current row
      const itemLeftOffset = itemWidth * item;
      // Get vertical offset for current row in rows
      const itemTopOffset = itemHeight * row;
      // Center item horizontally in row
      const rowsWidthHalf = rowsWidth / 2;
      if (itemLeftOffset >= rowsWidthHalf) {
        const x = itemLeftOffset - rowsWidthHalf + itemWidth / 2;
        rowRef.scrollTo({x: x, animated: true});
      } else {
        rowRef.scrollTo({x: 0, animated: true});
      }
      // Scroll vertically to current row
      const rowsHeightHalf = rowsHeight / 2;
      if (itemTopOffset >= rowsHeightHalf - itemHeight) {
        const y = itemTopOffset;
        rowsRef.current.scrollTo({y: y, animated: true});
      } else {
        rowsRef.current.scrollTo({y: 0, animated: true});
      }
    }
  }

  function showItems(row) {
    const items = Array.from(Array(ITEMS).keys());
    return items.map((item) => {
      const key = 'scrollview_item_' + row + '.' + item;
      return (
        <FocusableHighlight
          onPress={() => {}}
          onFocus={(e) => {
            onItemFocus(e, row, item);
          }}
          underlayColor={Style.buttonFocusedColor}
          style={styles.rowItem}
          nativeID={key}
          key={key}>
          <Text style={styles.text}>{row + '.' + item}</Text>
        </FocusableHighlight>
      );
    });
  }

  function showRow(row) {
    return (
      <ScrollView
        ref={(ref) => {
          rowRefs.current[row] = ref;
          if (Platform.OS === 'web') {
            let node = findNodeHandle(ref);
            if (node) {
              // Set ScrollView spatial navigation action as focus to avoid scroll on up
              node.style.setProperty('--spatial-navigation-action', 'focus');
            }
          }
        }}
        style={styles.row}
        horizontal={true}
        showsHorizontalScrollIndicator={false}
        nativeID={'scrollview_row_' + row}
        key={'scrollview_row_' + row}>
        {showItems(row)}
      </ScrollView>
    );
  }

  function showRows() {
    const rows = Array.from(Array(ROWS).keys());
    return rows.map((row) => {
      return showRow(row);
    });
  }

  return (
    <View style={Style.styles.content}>
      <ScrollView
        ref={rowsRef}
        style={styles.rows}
        nativeID={'rows'}
        showsVerticalScrollIndicator={false}>
        {showRows()}
      </ScrollView>
    </View>
  );
}
Example #9
Source File: SectionListDemo.js    From react-native-tv-demo with MIT License 4 votes vote down vote up
SectionListDemo = () => {
  const sectionListRef = useRef(null);
  const rowRefs = useRef([]);

  function onItemFocus(e, section, row, item) {
    if (!rowRefs.current) {
      return;
    }
    if (section >= 0 && section < rowRefs.current.length) {
      // Check refs
      const rowRef = rowRefs.current[section];
      if (!rowRef || !sectionListRef) {
        return;
      }
      // Get styles
      const rowsStyle = StyleSheet.flatten(styles.rows);
      const rowItemStyle = StyleSheet.flatten(styles.rowItem);
      const sectionHeader = StyleSheet.flatten(styles.sectionHeader);
      // Get rows width / height
      const rowsWidth = rowsStyle.width;
      const rowsHeight = rowsStyle.height;
      // Get item width / height
      const itemWidth = rowItemStyle.width + rowItemStyle.margin * 2;
      const itemHeight =
        rowItemStyle.height +
        rowItemStyle.margin * 2 +
        sectionHeader.fontSize +
        sectionHeader.marginTop;
      // Get horizontal offset for current item in current row
      const itemLeftOffset = itemWidth * item;
      // Get vertical offset for current row in rows
      const itemTopOffset = itemHeight * section;
      // Center item horizontally in row
      const rowsWidthHalf = rowsWidth / 2;
      if (itemLeftOffset >= rowsWidthHalf) {
        const x = itemLeftOffset - rowsWidthHalf + itemWidth / 2;
        rowRef.scrollTo({x: x, animated: true});
      } else {
        rowRef.scrollTo({x: 0, animated: true});
      }
      // Scroll vertically to current row
      const rowsHeightHalf = rowsHeight / 2;
      if (itemTopOffset >= rowsHeightHalf - itemHeight) {
        sectionListRef.current.scrollToLocation({
          sectionIndex: section,
          itemIndex: 0,
          animated: true,
        });
      } else {
        sectionListRef.current.scrollToLocation({
          sectionIndex: 0,
          itemIndex: 0,
          animated: true,
        });
      }
    }
  }

  function showItems(section, row) {
    const items = Array.from(Array(ITEMS).keys());
    return items.map((item) => {
      const key = 'sectionlist_item_' + section + '.' + row + '.' + item;
      return (
        <FocusableHighlight
          onPress={() => {}}
          onFocus={(e) => {
            onItemFocus(e, section, row, item);
          }}
          underlayColor={Style.buttonFocusedColor}
          style={styles.rowItem}
          nativeID={key}
          key={key}>
          <Text style={styles.text}>{section + '.' + item}</Text>
        </FocusableHighlight>
      );
    });
  }

  function showRow(sectionItem) {
    const item = sectionItem.item;
    const key = 'sectionlist_row_' + item.section + '.' + item.row;
    return (
      <ScrollView
        ref={(ref) => {
          rowRefs.current[item.section] = ref;
          if (Platform.OS === 'web') {
            let node = findNodeHandle(ref);
            if (node) {
              // Set ScrollView spatial navigation action as focus to avoid scroll on up
              node.style.setProperty('--spatial-navigation-action', 'focus');
            }
          }
        }}
        style={styles.row}
        horizontal={true}
        showsHorizontalScrollIndicator={false}
        nativeID={key}
        key={key}>
        {showItems(item.section, item.row)}
      </ScrollView>
    );
  }

  function renderSectionHeader(sectionHeader) {
    const section = sectionHeader.section;
    return <Text style={styles.sectionHeader}>{section.title}</Text>;
  }

  function getSections() {
    // Load data
    let sections = [];
    for (let i = 0; i < SECTIONS; i++) {
      let rows = [];
      for (let j = 0; j < SECTIONS_ROWS; j++) {
        rows.push({section: i, row: j});
      }
      sections.push({
        title: 'Section ' + i,
        data: rows,
      });
    }
    return sections;
  }

  // Render
  return (
    <View style={Style.styles.content}>
      <SectionList
        ref={sectionListRef}
        style={styles.rows}
        nativeID={'sectionlist'}
        sections={getSections()}
        renderItem={showRow}
        renderSectionHeader={renderSectionHeader}
        keyExtractor={(row) => row.row}
        showsVerticalScrollIndicator={false}
      />
    </View>
  );
}
Example #10
Source File: DrillPage.js    From UltimateApp with MIT License 4 votes vote down vote up
DrillPage = (props) => {
  const { route, navigation } = props;

  // Create Component refs
  const drillScrollView = useRef(null);
  const descriptionRef = useRef(null);

  // Get Header Height
  const headerHeight = useHeaderHeight();
  const screenDimension = Dimensions.get('window');
  const sizeBackground = screenDimension.height - headerHeight;
  const imageStyles = { ...styles.image, height: sizeBackground };

  const drillId = route.params.id;
  const drill = props.drills.find((drill) => drill.id == drillId);

  const startFitness = () => {
    navigation.navigate('FitnessPage', { drill });
  };

  const onPressStartButton = () => {
    if (drill.type === DrillTypes.FITNESS) {
      startFitness();
    } else {
      descriptionRef.current.measureLayout(findNodeHandle(drillScrollView.current), (x, y) => {
        drillScrollView.current.scrollTo({ x: 0, y, animated: true });
      });
    }
  };

  useLayoutEffect(() => {
    navigation.setOptions({
      title: drill.title,
      headerRight: () => <ShareDrill drill={drill} />,
      headerTitleContainerStyle: {
        ...Platform.select({
          ios: {
            marginRight: 50,
          },
        }),
      },
    });
  });

  let favoriteIcon = 'heart-outline';
  if (props.favoriteDrills.findIndex((item) => item.id === props.route.params.id) !== -1) {
    favoriteIcon = 'heart';
  }
  const imageSource = drill.custom && drill.image === undefined ? customDrillsImage : { uri: drill.image };

  return (
    <ScrollView ref={drillScrollView} style={styles.drillPage}>
      <ImageBackground source={imageSource} style={imageStyles} imageStyle={styles.imageOpacity}>
        <View style={styles.titleContainer}>
          <Text style={styles.title}>{drill.title}</Text>
          <Text style={styles.author}>{drill.author}</Text>
        </View>
        <View style={styles.infoWrapper}>
          <View style={styles.infoSubWrapper}>
            <Text style={styles.info}>{drill.durationInMinutes}</Text>
            <Text style={styles.info}>{I18n.t('drillPage.minutes')}</Text>
          </View>
          <View style={styles.separator} />
          <View style={styles.infoSubWrapper}>
            <Text style={styles.info}>{drill.minimalPlayersNumber}+</Text>
            <Text style={styles.info}>{I18n.t('drillPage.players')}</Text>
          </View>
          <View style={styles.separator} />
          <View style={styles.infoSubWrapper}>
            <Text style={styles.info}>{I18n.t(`data.levels.${drill.level}`)}</Text>
            <Text style={styles.info}>{I18n.t('drillPage.level')}</Text>
          </View>
        </View>
        <View style={styles.startButton}>
          <StartButton onPress={onPressStartButton} text={I18n.t('drillPage.start')} />
          <View style={styles.favoriteButton}>
            <TouchableOpacity onPress={() => props.toggleFavorite(drill)} testID="favoriteButton">
              <Ionicons name={favoriteIcon} color={theme.COLOR_PRIMARY_LIGHT} size={30} />
            </TouchableOpacity>
          </View>
        </View>
      </ImageBackground>
      <View ref={descriptionRef}>
        <Description drill={drill} />
      </View>
      <View style={styles.animation}>
        {drill.type === DrillTypes.FRISBEE && <FrisbeeDrillIllustration drill={drill} />}
        {drill.type === DrillTypes.FITNESS && <FitnessDrillIllustration drill={drill} startFitness={startFitness} />}
      </View>
    </ScrollView>
  );
}