React Native adaptive view

This commit is contained in:
Federico Kereki
2018-09-02 13:40:27 -03:00
parent 43945d111c
commit 0424e78c8c
16 changed files with 708 additions and 22 deletions
+22
View File
@@ -0,0 +1,22 @@
/* @flow */
import { getDeviceData } from "./device";
import type { deviceDataType } from "./device";
export const DEVICE_DATA = "device:data";
export type deviceDataAction = {
type: string,
deviceData: deviceDataType
};
export const setDevice = (deviceData?: object) =>
({
type: DEVICE_DATA,
deviceData: deviceData || getDeviceData()
}: deviceDataAction);
/*
A real app would have many more actions!
*/
@@ -0,0 +1,56 @@
/* @flow */
import React from "react";
import PropTypes from "prop-types";
import { View, Text, StyleSheet } from "react-native";
import type { deviceDataType } from "./device";
const textStyle = StyleSheet.create({
bigText: {
fontWeight: "bold",
fontSize: 24
}
});
export class AdaptiveView extends React.PureComponent<{
deviceData: deviceDataType
}> {
static propTypes = {
deviceData: PropTypes.object.isRequired
};
renderHandset() {
return (
<View>
<Text style={textStyle.bigText}>
I believe I am a HANDSET currently in
{this.props.deviceData.isPortrait
? " PORTRAIT "
: " LANDSCAPE "}
orientation
</Text>
</View>
);
}
renderTablet() {
return (
<View>
<Text style={textStyle.bigText}>
I think I am a
{this.props.deviceData.isPortrait
? " PORTRAIT "
: " LANDSCAPE "}
TABLET
</Text>
</View>
);
}
render() {
return this.props.deviceData.isTablet
? this.renderTablet()
: this.renderHandset();
}
}
@@ -0,0 +1,11 @@
/* @flow */
import { connect } from "react-redux";
import { AdaptiveView } from "./adaptiveView.component";
const getProps = state => ({
deviceData: state.deviceData
});
export const ConnectedAdaptiveView = connect(getProps)(AdaptiveView);
+25
View File
@@ -0,0 +1,25 @@
/* @flow */
import { Dimensions } from "react-native";
export type deviceDataType = {
isTablet: boolean,
isPortrait: boolean,
height: number,
width: number,
scale: number,
fontScale: number
};
export const getDeviceData = (): deviceDataType => {
const { height, width, scale, fontScale } = Dimensions.get("screen");
return {
isTablet: Math.max(height, width) / Math.min(height, width) <= 1.6,
isPortrait: height > width,
height,
width,
scale,
fontScale
};
};
@@ -0,0 +1,21 @@
/* @flow */
import React from "react";
import PropTypes from "prop-types";
import { View } from "react-native";
class DeviceHandler extends React.PureComponent<{
setDevice: () => any
}> {
static propTypes = {
setDevice: PropTypes.func.isRequired
};
onLayoutHandler = () => this.props.setDevice();
render() {
return <View hidden onLayout={this.onLayoutHandler} />;
}
}
export { DeviceHandler };
@@ -0,0 +1,15 @@
/* @flow */
import { connect } from "react-redux";
import { DeviceHandler } from "./deviceHandler.component";
import { setDevice } from "./actions";
const getDispatch = dispatch => ({
setDevice: () => dispatch(setDevice())
});
export const ConnectedDeviceHandler = connect(
null,
getDispatch
)(DeviceHandler);
+19
View File
@@ -0,0 +1,19 @@
/* @flow */
import React from "react";
import { View, StatusBar } from "react-native";
import { ConnectedAdaptiveView } from "./adaptiveView.connected";
import { ConnectedDeviceHandler } from "./deviceHandler.connected";
export class Main extends React.PureComponent<> {
render() {
return (
<View>
<StatusBar hidden />
<ConnectedDeviceHandler />
<ConnectedAdaptiveView />
</View>
);
}
}
+31
View File
@@ -0,0 +1,31 @@
/* @flow */
import { getDeviceData } from "./device";
import { DEVICE_DATA } from "./actions";
import type { deviceAction } from "./actions";
export const reducer = (
state: object = {
// initial state: more app data, plus
deviceData: getDeviceData()
},
action: deviceAction
) => {
switch (action.type) {
case DEVICE_DATA:
return {
...state,
deviceData: action.deviceData
};
/*
In a real app, here there would
be plenty more "case"s
*/
default:
return state;
}
};
+8
View File
@@ -0,0 +1,8 @@
/* @flow */
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import { reducer } from "./reducer";
export const store = createStore(reducer, applyMiddleware(thunk));
@@ -33,7 +33,7 @@ render() {
return (
<View>
{ordered.map(x => (
<View key={`${x.countryCode}-${x.regionCode}`>
<View key={`${x.countryCode}-${x.regionCode}`}>
<Text>{x.regionName}</Text>
</View>
))}