React Native - измерять компонент при получении реквизита

1

У меня есть ScrollView как корень моего представления. Внутри я показываю кучу текстовых компонентов. Каждый компонент имеет свой собственный "ref", поэтому они доступны. Теперь, я передаю опору с номером, и этот номер сообщает мне, к какому тексту я должен перейти. Поэтому мне нужно сначала измерить это. Я пробовал эти четыре подхода, но каждый из них дает мне только неопределенные значения. Какие-нибудь идеи?

componentWillReceiveProps(nextProps) {
    //this is a reference to my 'Text' component
    const chapterNo = nextProps.navigation.state.params.chapter;
    const chapterRef = this.refs["chapter" + chapterNo];

    //method 1:
    var RCTUIManager = require('NativeModules').UIManager;
    var handle = ReactNative.findNodeHandle(chapterRef);
    RCTUIManager.measure(handle, (x, y, width, height, pageX, pageY) => {
       console.log(x, y, width, height);
    });

    //method 2:
    NativeMethodsMixin.measure.call(chapterRef, (x, y, width, height) => {
       console.log(x, y, width, height);
    });

    //method 3:
    chapterRef.measure((ox, oy, width, height, px, py) => {
       console.log(ox, oy, width, height);
    });

    //method 4 (same as 3 but with setTimout):
    setTimeout(() => {
         chapterRef.measure((ox, oy, width, height, px, py) => {
            console.log(ox, oy, width, height);
         });
    }, 0);
 }
  • 0
    Вы уверены, что chapterRef указывает на допустимый компонент? Вам следует избегать строковых литералов в качестве ссылок. Они устарели.
  • 0
    да, это то, что я проверил, и я уверен, что это ссылка в порядке, и ссылка на состав действительна. Я знаю, что строки не самые лучшие, но я обновлю это позже, как только я решу эту проблему. Я выясняю, что измерение всего, что находится внутри прокрутки, - боль в заднице в RN ...
Теги:
react-native
react-navigation

1 ответ

3
Лучший ответ

См. Пример ниже

Предполагая, что каждый элемент вашего scrollView имеет другой размер (в противном случае это еще проще):

  • Создайте массив, который получит каждую высоту элемента. Например, в конструкторе компонента. По умолчанию он пуст.
  • Используйте свойство onLayout для получения высоты (вы также можете получить ширину и точную позицию x, y на экране) для каждого элемента вашего scrollView. onLayout вызывается при изменениях монтирования и макета: https://facebook.github.io/react-native/docs/view.html#onlayout
  • В вашей функции обратного вызова (тот, который вы вызываете onLayout) храните эту высоту с помощью индекса элемента. Вы получите, например, что-то вроде: this.widthsTab [0] = 312
  • Затем вам просто нужно пройти через widths.Tab, чтобы получить именно то, где находится ваш элемент, и прокрутить до этой точной позиции.
  • Вы также можете удалить половину высоты экрана, чтобы убедиться, что ваш элемент находится посередине экрана.

Извините, если это не совсем понятно, но я уверен, что вы поймете эту идею. Я добавлю пример ASAP.

Редактировать:

class HorizontalNavCustomerFlow extends Component {

  state = {
    heights: [],
    totalHeight: 0,
    heightsChecked: 0,
  };

  componentDidUpdate() {
    const { currentParagraph } = this.props; // Id of the paragraph you want to scroll to
    // Compute current item position and scroll when all item heights are computed
    if (this.state.widthsChecked === HOW_MANY_ITEMS_YOU_HAVE) { // use for example .lenght if you have an array
      let yposition = 0;
      const screenHeight = Dimensions.get('window').height;
      for (let i = 0; i <= currentParagraph; i++) {
        yposition += this.state.heights[i];
      }
      // Removing half of current element
      yposition -= this.state.heights[currentParagraph] / 2;
      // And half of screen height
      yposition -= screenHeight / 2;
      // Last elements
      if (yposition > (this.state.totalWidth - screenWidth)) {
        yposition = this.state.totalHeight - screenHeight;
      }
      // Scroll
      if (yposition > 0) this.refs.MainScrollView.scrollTo({ y: yposition, animated: false });
    }
  }

  // Render
  render() {
    return (
      <View>
        <ScrollView
          ref='MainScrollView'
          showsVerticalScrollIndicator={false}
        >

          // ... Your items
          <View
            onLayout={(object) => {
              const { height } = object.nativeEvent.layout;
              const newState = this.state;
              newState.heights[index] = width;
              newState.heightsChecked = this.state.heightsChecked + 1;
              newState.totalHeight = this.state.totalHeight + height;
              this.setState(newState);
            }}
          >
            <Text>...</Text>
          </View>

        </ScrollView>
      </View>
    );
  }
}

Индекс массива может меня отключить одним, в зависимости от того, считаете ли вы от 0 или 1. Не стесняйтесь настраивать с помощью + / -1. Кроме того, я удаляю половину текущей ширины элемента, потому что я хотел прокручивать ее прямо посередине, но опять же, не стесняйтесь меняться, если вы хотите прокрутить начало или этот элемент или что-то еще.

  • 0
    Да, я копал эту тему в течение нескольких часов, и похоже, что описанный вами способ - единственный возможный способ. Со строками одинаковой высоты это действительно легко, так как я мог бы использовать FlatList, и это метод goToIndex. Спасибо за отличный ответ. Я должен быть в состоянии пойти дальше.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню