動畫必須有(二):懸浮選單瞭解一下!
目錄
- 前言
- 效果圖
- FloatingActionButton基礎
- FloatingActionButton例項
- 最後
前言
懸浮按鈕是我非常喜歡的, 可以把最關鍵的功能放入到懸浮按鈕中. 比如日記app裡的新建日記, 閱讀類app裡的喜歡. 稍微處理一下可以將懸浮按鈕擴充套件成懸浮選單, 來看下實現吧! github直接看原始碼
效果圖
廢話不多說, 先看圖, 感興趣再往下看!
FloatingActionButton基礎
記得導包.
compile 'com.android.support:design:26.+'
- 搭配Snackbar
官方推薦配合Snackbar來使用, 這都不多說了.
- 顯示和隱藏
然後還有就是懸浮按鈕的隱藏和顯示函式.
Button btHide = (Button) findViewById(R.id.bt_hide);
btHide.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
fab.hide();
}
});
Button btShow = (Button) findViewById(R.id.bt_show);
btShow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
fab.show();
}
});
- 顏色
可以設定點選顏色app:rippleColor, 以及背景顏色app:backgroundTint. 我將背景色改成藍色, 點選水波紋擴散變為紫色, 效果圖如下:
- 位置
當然了, 位置可以隨便改, 甚至可以吸附在某個控制元件之上.
android:layout_gravity="bottom|left"
吸附效果如下, 即使滾動也會保持相對的位置:
app:layout_anchor="@id/toolbar"
app:layout_anchorGravity="center|bottom"
FloatingActionButton例項
來看看效果圖是如何實現的吧.
- 佈局檔案
佈局檔案是個要點, 裡面塞進了兩個選單, 你選一個喜歡的用就好. 一個是扇型的, 一個是線型的.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/fl_fan_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginBottom="@dimen/twenty_dp"
android:layout_marginEnd="@dimen/twenty_dp"
android:src="@mipmap/ic_launcher"
app:backgroundTint="@color/colorAccent"
app:elevation="@dimen/zero_dp"
app:fabSize="mini" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_left_top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginBottom="@dimen/twenty_dp"
android:layout_marginEnd="@dimen/twenty_dp"
android:src="@mipmap/ic_launcher"
app:backgroundTint="@color/colorAccent"
app:elevation="@dimen/zero_dp"
app:fabSize="mini" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginBottom="@dimen/twenty_dp"
android:layout_marginEnd="@dimen/twenty_dp"
android:src="@mipmap/ic_launcher"
app:backgroundTint="@color/colorAccent"
app:elevation="@dimen/zero_dp"
app:fabSize="mini" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_origin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginBottom="@dimen/twenty_dp"
android:layout_marginEnd="@dimen/twenty_dp"
android:src="@drawable/ic_add"
app:backgroundTint="@color/colorPrimary"
app:fabSize="normal" />
</FrameLayout>
<RelativeLayout
android:id="@+id/rl_line_menu"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/rl_menu_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<LinearLayout
android:id="@+id/ll_fun1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="@dimen/hundred_dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_toLeftOf="@+id/fab_mini1"
android:layout_weight="1"
android:gravity="right"
android:paddingRight="@dimen/eight_dp"
android:text="1"
android:textColor="@android:color/white"
android:textSize="@dimen/sixteen_sp" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_mini1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/twenty_six_dp"
android:src="@mipmap/ic_launcher"
app:backgroundTint="@color/colorPrimary"
app:fabSize="mini" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_fun2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/ll_fun1"
android:layout_marginBottom="@dimen/twenty_dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_toLeftOf="@+id/fab_mini2"
android:layout_weight="1"
android:gravity="right"
android:paddingRight="@dimen/eight_dp"
android:text="2"
android:textColor="@android:color/white"
android:textSize="@dimen/sixteen_sp" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_mini2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/twenty_six_dp"
android:src="@mipmap/ic_launcher"
app:backgroundTint="@color/colorPrimary"
app:fabSize="mini" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_fun3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/ll_fun2"
android:layout_marginBottom="@dimen/twenty_dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_toLeftOf="@+id/fab_mini2"
android:layout_weight="1"
android:gravity="right"
android:paddingRight="@dimen/eight_dp"
android:text="3"
android:textColor="@android:color/white"
android:textSize="@dimen/sixteen_sp" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_mini3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/twenty_six_dp"
android:src="@mipmap/ic_launcher"
app:backgroundTint="@color/colorPrimary"
app:fabSize="mini" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_fun4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/ll_fun3"
android:layout_marginBottom="@dimen/twenty_dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_toLeftOf="@+id/fab_mini2"
android:layout_weight="1"
android:gravity="right"
android:paddingRight="@dimen/eight_dp"
android:text="4"
android:textColor="@android:color/white"
android:textSize="@dimen/sixteen_sp" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_mini4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/twenty_six_dp"
android:src="@mipmap/ic_launcher"
app:backgroundTint="@color/colorPrimary"
app:fabSize="mini" />
</LinearLayout>
</RelativeLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="@dimen/twenty_dp"
android:layout_marginEnd="@dimen/twenty_dp"
android:backgroundTint="@color/colorAccent"
android:src="@drawable/ic_add"
app:fabSize="normal"
app:rippleColor="@color/colorPrimaryDark" />
</RelativeLayout>
<Button
android:id="@+id/bt_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/switch_menu" />
</RelativeLayout>
- normal與mini
懸浮按鈕有兩種尺寸, normal和mini. 在xml中加入app:fabSize="mini"
就變成mini尺寸的了. 所以在設定動畫和位置的時候不是將按鈕全部放置在同一位置, 需要修正位置. 修正距離就是(normal-mini)/2, 應該很好理解.
// 計算偏移值
int w = View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED);
int h = View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED);
mFabOrigin.measure(w, h);
mFabLeft.measure(w, h);
mOffset = (mFabOrigin.getMeasuredHeight() - mFabLeft.getMeasuredHeight()) / 2;
// 修正位置
FrameLayout.LayoutParams lParams = (FrameLayout.LayoutParams) mFabLeft.getLayoutParams();
lParams.setMargins(0, 0, UIUtil.dp2px(20) + mOffset, UIUtil.dp2px(20) + mOffset);
mFabLeft.setLayoutParams(lParams);
FrameLayout.LayoutParams ltParams = (FrameLayout.LayoutParams) mFabLeftTop.getLayoutParams();
ltParams.setMargins(0, 0, UIUtil.dp2px(20) + mOffset, UIUtil.dp2px(20) + mOffset);
mFabLeftTop.setLayoutParams(ltParams);
FrameLayout.LayoutParams tParams = (FrameLayout.LayoutParams) mFabTop.getLayoutParams();
tParams.setMargins(0, 0, UIUtil.dp2px(20) + mOffset, UIUtil.dp2px(20) + mOffset);
mFabTop.setLayoutParams(tParams);
- 關於動畫
只要位置算對了, 動畫不是特別難, 當然想要像google或者apple的動畫那樣舒適還是很難的. 沒看第一篇的可以回頭看看.
/**
* 顯示扇型選單
*/
private void showFanMenu() {
// 識別符號設定是
mFanMenuOpen = true;
// 按鈕1向左移動
int x = (int) mFabOrigin.getX();
int y = (int) mFabOrigin.getY();
ValueAnimator va1 = ValueAnimator.ofInt(x, x - ConstantUtil.FAN_OFFSET);
va1.setDuration(500).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int l = (int) animation.getAnimatedValue();
int t = (int) mFabLeft.getY();
int r = mFabLeft.getWidth() + l;
int b = mFabLeft.getHeight() + t;
mFabLeft.layout(l, t, r, b);
}
});
// 按鈕2向左上移動
ValueAnimator va2x = ValueAnimator.ofInt(x, x - (int) (ConstantUtil.FAN_OFFSET / Math.pow(2, 1.0 / 2)));
ValueAnimator va2y = ValueAnimator.ofInt(y, y - (int) (ConstantUtil.FAN_OFFSET / Math.pow(2, 1.0 / 2)));
va2x.setDuration(500).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int l = (int) animation.getAnimatedValue();
int t = (int) mFabLeftTop.getY();
int r = mFabLeftTop.getWidth() + l;
int b = mFabLeftTop.getHeight() + t;
mFabLeftTop.layout(l, t, r, b);
}
});
va2y.setDuration(500).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int l = (int) mFabLeftTop.getX();
int t = (int) animation.getAnimatedValue();
int r = mFabLeftTop.getWidth() + l;
int b = mFabLeftTop.getHeight() + t;
mFabLeftTop.layout(l, t, r, b);
}
});
// 按鈕3向上移動
ValueAnimator va3 = ValueAnimator.ofInt(y, y - ConstantUtil.FAN_OFFSET);
va3.setDuration(500).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int l = (int) mFabTop.getX();
int t = (int) animation.getAnimatedValue();
int r = mFabTop.getWidth() + l;
int b = mFabTop.getHeight() + t;
mFabTop.layout(l, t, r, b);
}
});
// 開始動畫
va1.start();
va2x.start();
va2y.start();
va3.start();
}
- 切換圖示
然後就是在不同狀態切換懸浮按鈕的圖示, 使用setImageResource方法即可.
mFabAdd.setImageResource(mLineMenuOpen ? R.drawable.ic_add : R.drawable.ic_close);
最後
我本人還是很喜歡google的material design的, 這個懸浮按鈕也非常實用. 喜歡記得點贊或者關注我哦, 有意見或者建議評論區見~
相關文章
- 外掛-懸浮選單
- 滑鼠懸浮導航選單底部出現動畫橫線動畫
- css滑鼠懸浮二級下拉導航選單CSS
- 滑鼠懸浮具有背景動畫跟隨效果的導航選單動畫
- 有關WebSocket必須瞭解的知識Web
- css滑鼠懸浮下拉選單效果CSS
- Java 開發, volatile 你必須瞭解一下Java
- 滑鼠懸浮底部有橫條伸展的導航選單
- 滑鼠懸浮背景變色導航選單
- 滑鼠懸浮緩慢下拉導航選單
- 滑鼠懸浮三形選單變叉號
- 淺解前端必須掌握的演算法(二):簡單選擇排序前端演算法排序
- 人生苦短,瞭解一下前端必須明白的http知識點前端HTTP
- CSS 滑鼠懸浮動畫暫停效果CSS動畫
- Vue 資料雙向繫結實現二級下拉懸浮選單Vue
- Zookeeper必須瞭解的基礎
- CSS滑鼠懸浮圖片動畫放大效果CSS動畫
- Andorid 任意介面懸浮窗,實現懸浮窗如此簡單
- CSS3滑鼠懸浮動畫按鈕效果CSSS3動畫
- CSS3連結<a>滑鼠懸浮動畫效果CSSS3動畫
- 滑鼠懸浮可以上下伸縮的導航選單
- css3滑鼠懸浮背景滑動導航選單CSSS3
- BLOCK、BFC、邊距合併,滑鼠懸浮選單出現BloC
- 你必須瞭解Spring的生態Spring
- 滑鼠懸浮中英文切換橫向導航選單
- JavaScript實現HTML導航欄下拉選單[懸浮顯示]JavaScriptHTML
- css3滑鼠懸浮展開收縮導航選單CSSS3
- 你必須瞭解的「架構」小歷史架構
- Perl開發者必須瞭解的14個資源
- 使用Redis之前5個必須瞭解的事情Redis
- 手寫promise,瞭解一下(二)Promise
- HTML+CSS+JQuery實現下拉選單滑鼠懸浮顯示下拉選單,取消隱藏HTMLCSSjQuery
- 你必須瞭解的分散式事務解決方案分散式
- 看你骨骼驚奇,這裡有一套 Canvas 粒子動畫方案瞭解一下?Canvas動畫
- CSS3 滑鼠懸浮立體翻滾的導航選單CSSS3
- js滑鼠懸浮連結背景動畫方式漸變效果JS動畫
- 滑鼠懸浮遮罩層動畫方式滑動切換效果遮罩動畫
- 滑鼠懸浮實現圖片動畫上下切換效果動畫