[add] Dimensions event listeners

Close #511
This commit is contained in:
Vu Le
2017-07-08 20:04:39 -07:00
committed by Nicolas Gallagher
parent 1190ca20a7
commit 0bf6e893c6
5 changed files with 128 additions and 3 deletions

View File

@@ -4,8 +4,9 @@
* @flow
*/
import DimensionsChange from './examples/DimensionsChange';
import { storiesOf } from '@kadira/storybook';
import UIExplorer, { DocItem } from '../../ui-explorer';
import UIExplorer, { AppText, Code, DocItem, TextList } from '../../ui-explorer';
import React from 'react';
const sections = [
@@ -19,6 +20,34 @@ const sections = [
example={{
code: "const { height, width } = Dimensions.get('window')"
}}
/>,
<DocItem
name="static addEventLitener"
typeInfo="(type: string, handler: function) => void"
description={[
<AppText>Add an event handler. Supported events:</AppText>,
<TextList
items={[
<AppText>
<Code>change</Code>: Fires when a property within the <Code>Dimensions</Code> object
changes. The argument to the event handler is an object
with <Code>window</Code> and <Code>screen</Code> properties whose values are the
same as the return values of <Code>Dimensions.get('window')</Code> and{' '}
<Code>Dimensions.get('screen')</Code>,
respectively.
</AppText>
]}
/>
]}
example={{
render: () => <DimensionsChange />
}}
/>,
<DocItem
name="static removeEventLitener"
typeInfo="(type: string, handler: function) => void"
description="Remove an event handler."
/>
]
}
@@ -29,5 +58,6 @@ storiesOf('APIs', module).add('Dimensions', () =>
description="Note: dimensions may change (e.g., due to device rotation) so any rendering logic or styles that depend on these constants should try to call this function on every render, rather than caching the value."
sections={sections}
title="Dimensions"
url="apis/Dimensions"
/>
);

View File

@@ -0,0 +1,61 @@
import { Button, Dimensions, ScrollView, StyleSheet, Text, View } from 'react-native';
import React, { Component } from 'react';
export default class ChangeEventExample extends Component {
state = {
listened: false,
logs: []
};
componentWillUnmount() {
Dimensions.removeEventListener('change', this._handleChange);
}
render() {
const { logs, listened } = this.state;
const buttonTitle = listened ? 'Remove listener' : 'Add listener';
return (
<View>
<Button onPress={this.toggle} title={buttonTitle} />
<ScrollView style={styles.logs}>
{logs.map((log, i) => <Text key={i} style={styles.log}>{log}</Text>)}
</ScrollView>
</View>
);
}
toggle = () => {
const { listened } = this.state;
if (listened) {
Dimensions.removeEventListener('change', this._handleChange);
this._log('Removed listener');
} else {
Dimensions.addEventListener('change', this._handleChange);
this._log('Added listener');
}
this.setState(() => ({ listened: !listened }));
};
_handleChange = ({ window, screen }) => {
window = JSON.stringify(window, null, 2);
screen = JSON.stringify(screen, null, 2);
this._log(`Changed\nwindow = ${window}\nscreen = ${screen}`);
};
_log = msg => {
this.setState(state => ({
logs: [`${new Date().toTimeString()} - ${msg}`, ...state.logs]
}));
};
}
const styles = StyleSheet.create({
logs: {
maxHeight: 256
},
log: {
fontFamily: 'monospace, monospace',
marginTop: 8,
marginBottom: 8
}
});

View File

@@ -26,7 +26,7 @@ const styles = StyleSheet.create({
bullet: {
position: 'absolute',
left: 6,
top: '50%',
top: '.65625rem',
marginTop: -2,
height: 4,
width: 4,

View File

@@ -1,5 +1,23 @@
/* eslint-env jasmine, jest */
import Dimensions from '..';
describe('apis/Dimensions', () => {
test.skip('NO TEST COVERAGE', () => {});
test('addEventListener', () => {
const handler = jest.fn();
Dimensions.addEventListener('change', handler);
Dimensions.set();
expect(handler).toHaveBeenCalledTimes(1);
expect(handler).toHaveBeenLastCalledWith({
window: Dimensions.get('window'),
screen: Dimensions.get('screen')
});
});
test('removeEventListener', () => {
const handler = jest.fn();
Dimensions.removeEventListener('change', handler);
Dimensions.set();
expect(handler).toHaveBeenCalledTimes(0);
});
});

View File

@@ -27,6 +27,7 @@ const win = canUseDOM
};
const dimensions = {};
const listeners = {};
export default class Dimensions {
static get(dimension: string): Object {
@@ -48,6 +49,21 @@ export default class Dimensions {
scale: win.devicePixelRatio || 1,
width: win.screen.width
};
if (Array.isArray(listeners['change'])) {
listeners['change'].forEach(handler => handler(dimensions));
}
}
static addEventListener(type, handler): void {
listeners[type] = listeners[type] || [];
listeners[type].push(handler);
}
static removeEventListener(type, handler): void {
if (Array.isArray(listeners[type])) {
listeners[type] = listeners[type].filter(_handler => _handler !== handler);
}
}
}