Вы не можете сделать это с помощью одной функции onLayout
, так как вы используете две различные функции в текущей настройке. Так что это можно сделать с двумя. Вам просто нужно немного абстрагировать код, и тогда можно будет заставить его работать.
Если мы думаем о сетке, которую вы строите таким образом, мы можем легко найти каждую ячейку в сетке, если будем следовать прямому соглашению об именах XY
, где X
- строка, а Y
- столбец.
+----+----+----+
| 11 | 12 | 13 |
+----+----+----+
| 21 | 22 | 23 |
+----+----+----+
| 31 | 32 | 33 |
+----+----+----+
Используя эту идею, мы можем изменить ваши две onLayout
функции таким образом:
getExactPos = (e, key) => { // pass a key as well now
const { width, height, x, y } = e.nativeEvent.layout;
let position = {};
position.gridXstart = x;
position.gridXend = x + width;
position.gridYstart = y;
position.gridYend = y + height;
this.setState({ [key]: position }); // notice that we use the key to store it in state
}
getExactPosRow = (e, key) => { // pass a key as well now
const { y } = e.nativeEvent.layout;
this.setState({ [key]: y }); // notice that we use the key to store it in state
};
Мы установим ключи, используемые в этой функции, в constructViews
функция ниже. Теперь с их помощью мы можем построить функцию, которая, в свою очередь, построит сетку:
constructViews = () => {
let rows = [];
for (let i = 1; i < 4; i++) {
let row = [];
for (let j = 1; j < 4; j++) {
let stateKey = `${i}${j}`;
let styleKey = `box${stateKey}`;
row.push(
this.getExactPos(e, stateKey)} style={styles[styleKey]} key={stateKey}>{this.state[styleKey]}
);
}
rows.push(
this.getExactPosRow(e, `${i}`)} style={styles[`row${i}`]} key={i}>{row}
);
}
return rows;
}
В этой функции у нас есть вложенное for-loop
, которое создает сетку. Обратите внимание, что мы создаем и передаем ключи двум созданным нами функциям onLayout
. Мы можем расширить идею использования ключей дальше, динамически получая правильные стили и правильный текст.
Вот оно в рабочем POC. Это должно дать вам достаточно, чтобы реализовать то, что вы хотите. Я не внедрил никаких средств реагирования на жесты и оставлю это на ваше усмотрение.
import React from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
export default class App extends React.Component {
state = {
box11: 'Box 11',
box12: 'Box 12',
box13: 'Box 13',
box21: 'Box 21',
box22: 'Box 22',
box23: 'Box 23',
box31: 'Box 31',
box32: 'Box 32',
box33: 'Box 33'
}
getExactPos = (e, key) => {
const { width, height, x, y } = e.nativeEvent.layout;
let position = {};
position.gridXstart = x;
position.gridXend = x + width;
position.gridYstart = y;
position.gridYend = y + height;
this.setState({ [key]: position });
}
getExactPosRow = (e, key) => {
const { y } = e.nativeEvent.layout;
this.setState({
[key]: y
});
};
constructViews = () => {
let rows = [];
for (let i = 1; i < 4; i++) {
let row = [];
for (let j = 1; j < 4; j++) {
let stateKey = `${i}${j}`;
let styleKey = `box${stateKey}`;
row.push(
this.getExactPos(e, stateKey)} style={styles[styleKey]} key={stateKey}>{this.state[styleKey]}
);
}
rows.push(
this.getExactPosRow(e, `${i}`)} style={styles[`row${i}`]} key={i}>{row}
);
}
return rows;
}
render () {
return (
);
}
}
const styles = StyleSheet.create({
row1: { flexDirection: 'row', flex: 1, backgroundColor: 'red', width: '100%' },
row2: { flexDirection: 'row', flex: 1, backgroundColor: 'blue', width: '100%' },
row3: { flexDirection: 'row', flex: 1, backgroundColor: 'green', width: '100%' },
box11: { flex: 1, backgroundColor: 'yellow', justifyContent: 'center', alignItems: 'center' },
box12: { flex: 1, backgroundColor: 'orange', justifyContent: 'center', alignItems: 'center' },
box13: { flex: 1, backgroundColor: 'gray', justifyContent: 'center', alignItems: 'center' },
box21: { flex: 1, backgroundColor: 'green', justifyContent: 'center', alignItems: 'center' },
box22: { flex: 1, backgroundColor: 'red', justifyContent: 'center', alignItems: 'center' },
box23: { flex: 1, backgroundColor: 'blue', justifyContent: 'center', alignItems: 'center' },
box31: { flex: 1, backgroundColor: 'purple', justifyContent: 'center', alignItems: 'center' },
box32: { flex: 1, backgroundColor: 'skyblue', justifyContent: 'center', alignItems: 'center' },
box33: { flex: 1, backgroundColor: '#124567', justifyContent: 'center', alignItems: 'center' }
});
Здесь вы можете увидеть, как он работает в этой закуске https://snack.expo.io/@andypandy/dynamic-grid-using-onlayout
One of the things missing still (that is important for MVVM) is commanding. So you will be rolling at least a part of what the framework provides yourself.
I personally don't use any 3rd party framework, but do use an company internal framework that provides me with commanding and has base classes for the ViewModel part of MVVM.
У меня нет никакого опыта работы с этими фреймворками, но на основе только YAGNI и новизны Silverlight 3 и RIA Services,
У меня определенно есть личная предвзятость, основанная на том, что я делаю на работе, но функции, которые я нахожу супер полезными в любом проекте Silverlight ...
Если ваше приложение сложное / имеет несколько экранов ... 8. Навигация и, возможно, некоторые MVC
1 и 2. Мы надеемся обратиться к .NET RIA Services.
Остальные, я пытаюсь предоставить реализацию через Silverlight.FX ... первоначально как люди, использующие реализацию, могут использовать их как есть или в качестве отправной точки, и со временем загнать их в платформу / SDK.
Что касается самого командования, это, безусловно, полезно, но, на мой взгляд, не обязательно, если вы получил базовую функциональность связывания и способность связывать события с ванильными методами с помощью действий.
Мне нравится Silverlight.FX от Nikhil, так как он включает в себя команды, mvvm и некоторые «забавные» элементы, такие как прокрутка с помощью колесика мыши. Prism также довольно хорош, и я думаю, что его система публикации / подписки на события является более мощной, чем команда Silverlight.FX. В целом, я считаю Prism немного громоздким (и не совсем уместным, если вы планируете создать приложение для навигации SL3). Ninject - мой любимый на данный момент DI.