Expo/ReactNativeで特定のコンポーネントを表示する時に画面の明るさを変更する
Expo/ReactNativeで画面の明るさを変更するためのexpo-brightness
を使う機会があったので、コンポーネント化してみました。QRコードを表示する時に画面を明るくするなどの場面に使えそうです。
expo-brightness
のドキュメントはこちら
Androidではシステム設定の明るさとアプリ単位での明るさと2種類あり、ここではパーミッションが必要ない後者を使います。
iOSではアプリ単位での明るさ設定が使えないので、アプリがforegroundかbackgroundかを監視して、backgroundになった時に明るさを元に戻すようにしました。
また、明るさを変更した時にAndroidではデフォルトでアニメーションされるのに対してiOSではアニメーションされずパッと切り替わるので、durationIOS
を渡すとiOSでもアニメーションされるようにしてみました。
import React, { PureComponent } from "react";
import * as PropTypes from "prop-types";
import * as Brightness from "expo-brightness";
import { AppState, Animated, Easing, Platform } from "react-native";
/**
* 明るさを制御する
*/
class BrightnessControl extends PureComponent {
appState = null;
originalBrightness = null;
brightness = null;
componentDidMount() {
this._init();
}
/**
* 明るさを元に戻し、リスナーなどを解除
*/
componentWillUnmount() {
if (this.brightness) {
const { durationIOS } = this.props;
if (durationIOS && Platform.OS === "ios") {
Animated.timing(this.brightness, {
toValue: this.originalBrightness,
duration: durationIOS,
easing: Easing.in(Easing.out(Easing.ease))
}).start(() => {
this.brightness.removeListener(this._updateBrightness);
});
} else {
this.brightness.setValue(this.originalBrightness);
this.brightness.removeListener(this._updateBrightness);
}
AppState.removeEventListener("change", this._handleAppStateChange);
}
}
/**
* propsのbrightnessの変更に対応
* @param {object} prevProps
*/
componentDidUpdate(prevProps) {
if (
this.props.brightness !== prevProps.brightness &&
(this.appState === "active" || Platform.OS === "android")
) {
this.brightness.setValue(this.props.brightness);
this._updateBrightness();
}
}
/**
* 初期処理
* @returns {Promise<void>}
* @private
*/
_init = async () => {
this.originalBrightness = await Brightness.getBrightnessAsync(); // 元の明るさを保持しておく
// 明るさはAnimatedで変更
this.brightness = new Animated.Value(this.originalBrightness);
this.brightness.addListener(this._updateBrightness);
if (Platform.OS === "ios") {
// iOSの場合はAppStateでbackground/foregroundを監視
this._handleAppStateChange(AppState.currentState);
AppState.addEventListener("change", this._handleAppStateChange);
} else {
const { brightness } = this.props;
this.brightness.setValue(brightness);
}
};
/**
* 明るさを更新
* @private
*/
_updateBrightness = () => {
Brightness.setBrightnessAsync(this.brightness._value);
};
/**
* AppStateの変更に合わせて制御
* @param {string} nextAppState
* @returns {Promise<void>}
* @private
*/
_handleAppStateChange = async nextAppState => {
if (nextAppState !== this.appState) {
this.appState = nextAppState;
if (this.appState === "active") {
this.originalBrightness = await Brightness.getBrightnessAsync();
}
const { brightness, durationIOS } = this.props;
if (durationIOS) {
// アニメーションさせる場合
Animated.timing(this.brightness, {
toValue:
this.appState === "active" ? brightness : this.originalBrightness,
duration: durationIOS,
easing: Easing.in(Easing.out(Easing.ease))
}).start();
} else {
// アニメーションさせない場合
this.brightness.setValue(
this.appState === "active" ? brightness : this.originalBrightness
);
}
}
};
render() {
const { children } = this.props;
return <>{children}</>;
}
}
BrightnessControl.defaultProps = {
brightness: 1,
durationIOS: 0
};
BrightnessControl.propTypes = {
brightness: PropTypes.number, // 明るさ(0~1)
durationIOS: PropTypes.number // アニメーションの長さ(ms)
};
export default BrightnessControl;
下記のような感じで使うと、BrightnessControl
コンポーネントの表示・非表示によって明るさが変化するようになります。
<BrightnessControl brightness={1} durationIOS={500}>
{...}
</BrightnessControl>
Author And Source
この問題について(Expo/ReactNativeで特定のコンポーネントを表示する時に画面の明るさを変更する), 我々は、より多くの情報をここで見つけました https://qiita.com/mildsummer/items/323b6eba939d7405a4d4著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .