React Native のプロジェクトで、複数の浮いたボタンを表示させる方法を紹介します。
Star が多いライブラリは react-native-floating-action
と react-native-action-button
と の2つです。
- https://github.com/santomegonzalo/react-native-floating-action
- https://github.com/mastermoo/react-native-action-button
どちらも最終更新からだいぶ時間が経っていますが、react-native-floating-action
の方は最終が「2年前」で、 react-native-action-button
の「4年前」に比べるとまだ新しいかな、というのと、
ボタンをタップしたときに背景が暗くなるのが良いなと思ったので、react-native-floating-action
を使いました。
以下のコマンドで react-native-floating-action
をインストールしてください。
npm i react-native-floating-action --save
以下のようなコンポーネントを作成しました。 react-native-floating-action
はボタンの部分です。
自分でアイコンを選んで設定したい場合は、 @expo-vector-icons
を使います。
アイコンの一覧は以下から選択できます。
https://icons.expo.fyi/
公式のドキュメントは以下です。
https://docs.expo.dev/guides/icons/
基本的な使い方
以下のように、ボタンをタップしたときに表示するアイコンの配列を定義します。position
で配置する順番を設定できます。
interface FloatingActionProps {
text: string;
icon: JSX.Element;
name: string;
position: number;
}
const actions: FloatingActionProps[] = [
{
text: 'Register repeating tasks',
icon: <Feather name="repeat" size={20} color="white" />,
name: 'repeat_tasks',
position: 1,
},
{
text: 'Documenting Results',
icon: <Feather name="download" size={20} color="white" />,
name: 'documenting_results',
position: 2,
},
{
text: 'Reset all time',
icon: <FontAwesome name="repeat" size={20} color="white" />,
name: 'reset_all_time',
position: 3,
},
];
コンポーネントの中に以下のような FloatingAction
を配置してください。
<FloatingAction
actions={actions}
onPressItem={(name) => {
if (name !== undefined) {
console.log(`selected button: ${name}`);
}
}}
onOpen={() => {
setIsButtonOpen(true);
}}
onClose={() => {
setIsButtonOpen(false);
}}
/>
console.log(selected button: ${name});
に渡される name
は actions
で設定した name: 'reset_all_time',
のような name
です。
オリジナルのアイコンを設定する
デフォルトでは「+」マークのアイコンとなります。
ボタンを「+」=「追加」以外の用途で使いたいケースもあるでしょう。そういうときは、floatingIcon
プロパティにアイコンを指定すればOKです。 @expo/vector-icons
から import
したアイコンをそのまま設定できます。
<FloatingAction
actions={actions}
onPressItem={(name) => {
console.log(`selected button:`);
}}
floatingIcon={
<Entypo name="documents" size={24} color="white" />
}
onOpen={() => {
setIsButtonOpen(true);
}}
onClose={() => {
setIsButtonOpen(false);
}}
/>
オリジナルのアイコンを回転させる
上記で設定したオリジナルアイコンは、デフォルトの「+」アイコンのようなアニメーションが効きませんでした。デフォルトの場合は、タップしたタイミングで90度回転して、タップされたことがわかりやすくなっています。
全く回転しない場合、ユーザーへのフィードバックがやや足りない印象を受けます。Animated
を使って、タップしたタイミングで90度回転できるようにしましょう。
https://reactnative.dev/docs/animated
const [isButtonOpen, setIsButtonOpen] = useState(false);
const rotateAnim = useRef(new Animated.Value(0)).current;
useEffect(() => {
Animated.timing(rotateAnim, {
toValue: isButtonOpen ? 1 : 0,
duration: 200,
useNativeDriver: true,
easing: Easing.linear,
}).start();
}, [isButtonOpen]);
const rotation = rotateAnim.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '90deg'],
});
return (
<FloatingAction
actions={actions}
onPressItem={(name) => {
if (name !== undefined) {
console.log(`selected button: ${name}`);
}
}}
floatingIcon={
<Animated.View style={{ transform: [{ rotate: rotation }] }}>
<Entypo name="documents" size={24} color="white" />
</Animated.View>
}
onOpen={() => {
setIsButtonOpen(true);
}}
onClose={() => {
setIsButtonOpen(false);
}}
/>
)
上記のように Animated
を指定すれば、アイコンをタップしたときにクルっと90度回転させることができます。