LoginSignup
1
1

ReactNativeでポップアップメニューの実装

Posted at

ReactNativeでポップアップメニューの実装

ReactNativeでポップアップメニューといえば react-native-material-menu での実装がよく見つかるのですが、表示内容のカスタマイズはまずできない構造だったので、仕方なく react-native-popup-menu に置き換えたというお話です。

react-native-material-menu でアイコンがうまく配置できない

このあたりの issues でアイコン配置についての言及があり、配置はスペースで調整しているようです。
最初は気にしていなかったんですが、コードを良く調べてみると、MenuItemに渡したchildrenはTextの配下に入るようです。
どおりで、どうやっても右端にアイコンが配置できないわけだ...。
(現在、2.0.0になっていますが、未だにMenuItemのchildrenはText配下です)

このままでは到底デザインどおりの配置は無理なので、別のライブラリを探しました。

react-native-popup-menu を使う

割と自由度が高そうなライブラリを見つけたのでポップアップメニューの類をそれに置き換えることにしました。

1. 最上層になる部分を MenuProvider で覆う

以下は react-native-material-menuBasic Usage にある実装サンプルです。
react-navigation を使っている場合はNavigationContainerを覆えば良さそうです。
後は中の画面で Menu 以下を追加するだけで簡単に実装できます。

App.tsx
import { MenuProvider } from 'react-native-popup-menu';

export const App = () => (
  <MenuProvider>
    <YourApp />
  </MenuProvider>
);

2. 表示するメニューの実装

ポップアップメニューを開くボタン込みで以下のような実装です。

Menu.tsx
import {
  Menu,
  MenuTrigger,
  MenuOptions,
  MenuOption,
  renderers,
} from 'react-native-popup-menu';

function createMenu() {
  return (
    <Menu renderer={renderers.NotAnimatedContextMenu}>
      <MenuTrigger>
        <Text>メニュー</Text>
      </MenuTrigger>
      <MenuOptions
        customStyles={{
          optionsContainer: styles.options,
          optionWrapper: styles.option,
        }}>
        <MenuOption onSelect={() => alert('Hoge')} text='Hoge' />
        <MenuOption onSelect={() => alert('Fuga')}>
          <Text style={{color: 'red'}}>Fuga</Text>
        </MenuOption>
      </MenuOptions>
    </Menu>
  );
}

const styles = StyleSheet.create({
  options: {
    width: 300,
    marginTop: 10,
    marginLeft: -30,
    borderRadius: 8,
  },
  option: {
    minHeight: 48,
    padding: 8,
  },
});

Menu: ポップアップメニューの開始タグです。rendererで開き方を指定できます。例はアニメーションしないメニューです。パッと開く感じです。Popoverで吹き出し型、SlideInMenuで下から生えてくるメニューが出せます。

MenuTrigger: ポップアップを開くボタンです。テキスト以外にもなんでも置けます。テキストだけの場合は、<MenuTrigger text='Menu' /> というふうにもできます。

MenuOptions: ポップアップの外枠です。これのマージンなどを調整するとボタンからの表示位置を調整できます。メニューの幅などもここに指定。(marginLeftにマイナス値を入れると、ボタンの左側に開きます)

MenuOption: ポップアップ内のリストです。一般的なView内配置になるので、よくあるテキスト左寄せ、アイコン右寄せみたいな作り込みのViewを渡しても大丈夫です。

以上の実装で十分過ぎるぐらいにポップアップメニューの実装は可能です。
この他、細かい設定が必要という場合は、react-native-popup-menu のサンプルやドキュメントを読むと良さそうです。

まとめ

凝ったデザインのポップアップメニューを作りたい場合は react-native-popup-menu をおすすめします。
また、MenuTrigger には disabled 属性があるので、このタイミングでメニューを開かせたくないという場合にも有効です。
MenuOption も disabled 属性があるので、色々とコントロールし易いのではないでしょうか。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1