はじめに
Vuetify を使うと優れた UI をとても簡単に作れますが、少し特殊なことをやろうとするとつまづくことが多いです。
本記事では、モバイルアプリでよく見かける、ボトムナビゲーションからはみ出たアイツ をつける方法を記載します。
アイツの一般的な名称は、多分「オーバーラップ FAB」なんですが。
出来上がるもの
開発環境
- Windows10
- Node.js 12.13.1
- Atom 1.42.0
- vue/cli 4.1.1
- Vue 2.6.1
- Vuetify 2.0.3
アイコンをインストールする
とりあえずアイコンを用意しましょう。今回は、Fontawesome を使います。
環境に合わせてご自由にどうぞ。
npm install @fortawesome/fontawesome-free -D
import Vue from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify';
import '@fortawesome/fontawesome-free/css/all.css' /* この行を追加する */
ボトムナビゲーションを追加する
v-app ディレクティブの後ろにコードを追加します。
<template>
<v-app>
<!-- 省略 -->
<!-- ここからボトムナビゲーション -->
<v-bottom-navigation
dark
grow
>
<v-btn>
<span>Home</span>
<v-icon>fas fa-home</v-icon>
</v-btn>
<v-btn>
<span>Edit</span>
<v-icon>fas fa-edit</v-icon>
</v-btn>
</v-bottom-navigation>
<!-- ここまでボトムナビゲーション -->
</v-app>
</template>
フローティングボタンを用意する
Vuetify では v-speed-dial ディレクティブを使うと、子ボタンを内包したフローティングボタンが使えます。
<template>
<v-app>
<!-- 省略 -->
<!-- ここからフローティングボタン -->
<v-layout justify-center row wrap>
<v-speed-dial
v-model="fab"
>
<template v-slot:activator>
<v-btn
color="red darken-2"
dark
fab
>
<v-icon v-if="fab">mdi-close</v-icon>
<v-icon v-else>mdi-plus</v-icon>
</v-btn>
</template>
<v-btn
fab
dark
small
color="orange"
>
<v-icon>mdi-note</v-icon>
</v-btn>
<v-btn
fab
dark
small
color="red"
>
<v-icon>mdi-camera</v-icon>
</v-btn>
<v-btn
fab
dark
small
color="indigo"
>
<v-icon>mdi-file</v-icon>
</v-btn>
</v-speed-dial>
</v-layout>
<!-- ここまでフローティングボタン -->
<!-- 省略 -->
<script>
export default {
name: 'App',
components: {
},
data: () => ({
fab: false, /* フローティングボタン のために追加 */
}),
};
</script>
あとはフローティングボタンを、ボトムナビゲーションに入れたら完成ですね
完成、そんなことはなかった
すみません、どうやら簡単にはできないようです。
ボトムナビゲーションにフローティングボタンを入れると、とても残念な結果になります。
一応ソースも置いておきます。
<template>
<v-app>
<!-- 省略 -->
<v-bottom-navigation
dark
grow
>
<v-btn>
<span>Home</span>
<v-icon>fas fa-home</v-icon>
</v-btn>
<!-- ここからフローティングボタン -->
<v-layout justify-center>
<v-speed-dial
v-model="fab"
>
<template v-slot:activator>
<v-btn
color="red darken-2"
dark
fab
>
<v-icon v-if="fab">mdi-close</v-icon>
<v-icon v-else>mdi-plus</v-icon>
</v-btn>
</template>
<v-btn
fab
dark
small
color="orange"
>
<v-icon>mdi-note</v-icon>
</v-btn>
<v-btn
fab
dark
small
color="red"
>
<v-icon>mdi-camera</v-icon>
</v-btn>
<v-btn
fab
dark
small
color="indigo"
>
<v-icon>mdi-file</v-icon>
</v-btn>
</v-speed-dial>
</v-layout>
<!-- ここまでフローティングボタン -->
<v-btn>
<span>Edit</span>
<v-icon>fas fa-edit</v-icon>
</v-btn>
</v-bottom-navigation>
</v-app>
</template>
ボタンのスタイルを !important で無理やり書き換えれば多少の抵抗はできそうですが、時間のムダです。
もちろん僕はやりました
やめておいた方が吉です
ボトムナビゲーションとフローティングボタンは分離する
ボトムナビゲーション内にフローティングボタンは置けません
ボトムナビゲーションは画面の下部に固定されるので、ついでにフローティングボタンもボトムナビゲーションの中に含めたくなりますが、それではうまくいきません。
そこで、v-footer ディレクティブを用意し、その中に、フローティングボタンとボトムナビゲーションを入れます。
...というわけで、v-footer ディレクティブの中に、フローティングボタンとボトムナビゲーションを入れます。
また、v-footer には fixed プロパティを付与し、画面下部に固定します。
<template>
<v-app>
<!-- 省略 -->
<v-footer
padless
fixed
>
<v-row>
<v-col
cols="12"
class="pa-0"
>
<v-layout justify-center>
<v-speed-dial
v-model="fab"
>
<template v-slot:activator>
<v-btn
color="red darken-2"
dark
fab
class="float"
>
<v-icon v-if="fab">mdi-close</v-icon>
<v-icon v-else>mdi-plus</v-icon>
</v-btn>
</template>
<v-btn
fab
dark
small
color="orange"
>
<v-icon>mdi-note</v-icon>
</v-btn>
<v-btn
fab
dark
small
color="red"
>
<v-icon>mdi-camera</v-icon>
</v-btn>
<v-btn
fab
dark
small
color="indigo"
>
<v-icon>mdi-file</v-icon>
</v-btn>
</v-speed-dial>
</v-layout>
</v-col>
<v-col
cols="12"
class="pa-0"
>
<v-bottom-navigation
dark
grow
>
<v-btn>
<span>Home</span>
<v-icon>fas fa-home</v-icon>
</v-btn>
<v-btn>
<span>Edit</span>
<v-icon>fas fa-edit</v-icon>
</v-btn>
</v-bottom-navigation>
</v-col>
</v-row>
</v-footer>
</v-app>
</template>
仕上げ
フローティングボタンをボトムナビゲーションに重ねます。
まず、フローティングボタンを配置している row の高さを 0 にします。
<template>
<v-app>
<!-- 省略 -->
<v-footer
padless
fixed
>
<v-row>
<v-col
cols="12"
class="pa-0"
style="height: 0px;" <!-- 高さを 0 にする -->
>
<!-- 省略 -->
</v-col>
</v-row>
</v-footer>
</v-app>
</template>
次に、フローティングボタンを上方向にズラすために、スタイルを適用します。
<template>
<v-app>
<!-- 省略 -->
<template v-slot:activator>
<v-btn
color="red darken-2"
dark
fab
class="float" <!-- 位置調整用のスタイルを適用 -->
>
<v-icon v-if="fab">mdi-close</v-icon>
<v-icon v-else>mdi-plus</v-icon>
</v-btn>
</template>
<!-- 省略 -->
</v-app>
</template>
<script>
export default {
name: 'App',
components: {
},
data: () => ({
fab: false,
}),
};
</script>
<style>
.float {
-webkit-transform: translateY(-20%); /* フローティングボタンを上部にズラす */
transform: translateY(-20%);
}
</style>
まとめ
Vuetify は色々と捗り過ぎて素晴らしいですが、単純にやり過ぎるとドツボにハマります。
やはりどのようなフレームワークを使おうが CSS の基本的な知識(特にFlexbox)は大事ですね。
あと、もっと楽な方法あったらコメントいただけると嬉しいです!