Android 動態(tài)菜單實(shí)現(xiàn)實(shí)例代碼
Android 動態(tài)菜單
先上效果圖

比較簡單,主要就是屬性動畫的使用和坐標(biāo)角度的小細(xì)節(jié)。
實(shí)現(xiàn)
實(shí)現(xiàn)效果:
圖標(biāo)按照路徑一路縮放漸變過來即可。
核心代碼
/**
* Item開啟動畫
*
* @param btnItem
* @param index
* @param total
* @param radius
*/
private void btnItemStartAnimator(View btnItem, int index, int total, int radius) {
if (btnItem.getVisibility() != View.VISIBLE) {
btnItem.setVisibility(View.VISIBLE);
}
double degree = Math.toRadians(90) / (total - 1) * index;//Math中根據(jù)度數(shù)得到弧度值的函數(shù)
int translationX = -(int) (radius * Math.sin(degree));
int translationY = -(int) (radius * Math.cos(degree));
AnimatorSet set = new AnimatorSet();
//實(shí)現(xiàn)平移縮放和透明動畫
set.playTogether(
ObjectAnimator.ofFloat(btnItem, "translationX", 0, translationX),
ObjectAnimator.ofFloat(btnItem, "translationY", 0, translationY),
ObjectAnimator.ofFloat(btnItem, "scaleX", 0, 1),
ObjectAnimator.ofFloat(btnItem, "scaleY", 0, 1),
ObjectAnimator.ofFloat(btnItem, "alpha", 0, 1)
);
set.setInterpolator(new BounceInterpolator());
set.setDuration(500).start();
}
/**
* Item關(guān)閉動畫
*
* @param btnItem
* @param index
* @param total
* @param radius
*/
private void btnItemCloseAnimator(View btnItem, int index, int total, int radius) {
double degree = Math.PI * index / ((total - 1) * 2);
int translationX = -(int) (radius * Math.sin(degree));
int translationY = -(int) (radius * Math.cos(degree));
AnimatorSet set = new AnimatorSet();
//包含平移、縮放和透明度動畫
set.playTogether(
ObjectAnimator.ofFloat(btnItem, "translationX", translationX, 0),
ObjectAnimator.ofFloat(btnItem, "translationY", translationY, 0),
ObjectAnimator.ofFloat(btnItem, "scaleX", 1f, 0f),
ObjectAnimator.ofFloat(btnItem, "scaleY", 1f, 0f),
ObjectAnimator.ofFloat(btnItem, "alpha", 1f, 0f));
set.setDuration(500).start();
if (btnItem.getVisibility() == View.VISIBLE) {
btnItem.setVisibility(View.INVISIBLE);
}
}
item開啟動畫和關(guān)閉動畫為一個逆過程,體現(xiàn)在x,y距離變化上。

x,y的距離開啟時距離逐漸增長
ObjectAnimator.ofFloat(btnItem, "translationX", 0, translationX),
ObjectAnimator.ofFloat(btnItem, "translationY", 0, translationY),
這里要注意下sin這些弧度的計(jì)算,可以使用Math.toRadins(數(shù)字)
double degree = Math.toRadians(90) / (total - 1) * index;//Math中根據(jù)度數(shù)得到弧度值的函數(shù)
int translationX = -(int) (radius * Math.sin(degree));
或者使用PI=180°來折算
double degree = Math.PI * index / ((total - 1) * 2);
int translationX = -(int) (radius * Math.sin(degree));
實(shí)例代碼:
package xsf.customView;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.view.View;
import android.view.animation.BounceInterpolator;
import android.widget.Button;
import android.widget.Toast;
import xsf.customView.base.BaseActvity;
public class StatelliteActivity extends BaseActvity {
private Button btnMenu, btnItem1, btnItem2, btnItem3, btnItem4, btnItem5;
private boolean isMenuOpen = false;
@Override
protected int setLayoutResourceId() {
return R.layout.activity_statellite;
}
@Override
protected void initView() {
btnMenu = (Button) findViewById(R.id.btnMenu);
btnMenu.setOnClickListener(this);
btnItem1 = (Button) findViewById(R.id.btnItem1);
btnItem1.setOnClickListener(this);
btnItem2 = (Button) findViewById(R.id.btnItem2);
btnItem2.setOnClickListener(this);
btnItem3 = (Button) findViewById(R.id.btnItem3);
btnItem3.setOnClickListener(this);
btnItem4 = (Button) findViewById(R.id.btnItem4);
btnItem4.setOnClickListener(this);
btnItem5 = (Button) findViewById(R.id.btnItem5);
btnItem5.setOnClickListener(this);
}
@Override
public void onClick(View v) {
btnMenu.requestFocus();
switch (v.getId()) {
case R.id.btnMenu:
showItemAnimator();
break;
case R.id.btnItem1:
Toast.makeText(StatelliteActivity.this, "點(diǎn)擊了Item1", Toast.LENGTH_SHORT).show();
break;
case R.id.btnItem2:
Toast.makeText(StatelliteActivity.this, "點(diǎn)擊了Item2", Toast.LENGTH_SHORT).show();
break;
case R.id.btnItem3:
Toast.makeText(StatelliteActivity.this, "點(diǎn)擊了Item3", Toast.LENGTH_SHORT).show();
break;
case R.id.btnItem4:
Toast.makeText(StatelliteActivity.this, "點(diǎn)擊了Item4", Toast.LENGTH_SHORT).show();
break;
case R.id.btnItem5:
Toast.makeText(StatelliteActivity.this, "點(diǎn)擊了Item5", Toast.LENGTH_SHORT).show();
break;
}
}
private void showItemAnimator() {
if (!isMenuOpen) {
//此時menu是關(guān)閉的
isMenuOpen = true;
btnItemStartAnimator(btnItem1, 0, 5, 300);
btnItemStartAnimator(btnItem2, 1, 5, 300);
btnItemStartAnimator(btnItem3, 2, 5, 300);
btnItemStartAnimator(btnItem4, 3, 5, 300);
btnItemStartAnimator(btnItem5, 4, 5, 300);
} else {
//此時menu是打開的
isMenuOpen = false;
btnItemCloseAnimator(btnItem1, 0, 5, 300);
btnItemCloseAnimator(btnItem2, 1, 5, 300);
btnItemCloseAnimator(btnItem3, 2, 5, 300);
btnItemCloseAnimator(btnItem4, 3, 5, 300);
btnItemCloseAnimator(btnItem5, 4, 5, 300);
}
}
/**
* 關(guān)閉動畫
*
* @param btnItem
* @param index
* @param total
* @param radius
*/
private void btnItemCloseAnimator(View btnItem, int index, int total, int radius) {
double degree = Math.PI * index / ((total - 1) * 2);
int translationX = -(int) (radius * Math.sin(degree));
int translationY = -(int) (radius * Math.cos(degree));
AnimatorSet set = new AnimatorSet();
//包含平移、縮放和透明度動畫
set.playTogether(
ObjectAnimator.ofFloat(btnItem, "translationX", translationX, 0),
ObjectAnimator.ofFloat(btnItem, "translationY", translationY, 0),
ObjectAnimator.ofFloat(btnItem, "scaleX", 1f, 0f),
ObjectAnimator.ofFloat(btnItem, "scaleY", 1f, 0f),
ObjectAnimator.ofFloat(btnItem, "alpha", 1f, 0f));
set.setDuration(500).start();
if (btnItem.getVisibility() == View.VISIBLE) {
btnItem.setVisibility(View.INVISIBLE);
}
}
/**
* 開啟動畫
*
* @param btnItem
* @param index
* @param total
* @param radius
*/
private void btnItemStartAnimator(View btnItem, int index, int total, int radius) {
if (btnItem.getVisibility() != View.VISIBLE) {
btnItem.setVisibility(View.VISIBLE);
}
double degree = Math.toRadians(90) / (total - 1) * index;//Math中根據(jù)度數(shù)得到弧度值的函數(shù)
int translationX = -(int) (radius * Math.sin(degree));
int translationY = -(int) (radius * Math.cos(degree));
AnimatorSet set = new AnimatorSet();
//實(shí)現(xiàn)平移縮放和透明動畫
set.playTogether(
ObjectAnimator.ofFloat(btnItem, "translationX", 0, translationX),
ObjectAnimator.ofFloat(btnItem, "translationY", 0, translationY),
ObjectAnimator.ofFloat(btnItem, "scaleX", 0, 1),
ObjectAnimator.ofFloat(btnItem, "scaleY", 0, 1),
ObjectAnimator.ofFloat(btnItem, "alpha", 0, 1)
);
set.setInterpolator(new BounceInterpolator());
set.setDuration(500).start();
}
}
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
- Android左右滑出菜單實(shí)例分析
- android底部菜單欄實(shí)現(xiàn)原理與代碼
- android popwindow實(shí)現(xiàn)左側(cè)彈出菜單層及PopupWindow主要方法介紹
- Android ListView長按彈出菜單二種實(shí)現(xiàn)方式示例
- Android開發(fā)技巧之我的菜單我做主(自定義菜單)
- Android仿QQ空間底部菜單示例代碼
- Android界面設(shè)計(jì)(APP設(shè)計(jì)趨勢 左側(cè)隱藏菜單右邊顯示content)
- 基于Android實(shí)現(xiàn)點(diǎn)擊某個按鈕讓菜單選項(xiàng)從按鈕周圍指定位置彈出
- Android之用PopupWindow實(shí)現(xiàn)彈出菜單的方法詳解
- Android仿UC底部菜單欄實(shí)現(xiàn)原理與代碼
相關(guān)文章
Android開發(fā)技巧之在a標(biāo)簽或TextView控件中單擊鏈接彈出Activity(自定義動作)
a標(biāo)簽以及TextView自動識別的特殊文本(網(wǎng)址、電話號、Email等),這些都可以通過單擊來觸發(fā)不同的動作;但如果讀者想在單擊鏈接時執(zhí)行任意自定義的動作,那么將要介紹的一定是你想要的了2013-01-01
Android使用動畫設(shè)置ProgressBar進(jìn)度的方法
這篇文章主要為大家詳細(xì)介紹了Android使用動畫設(shè)置ProgressBar進(jìn)度的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-01-01
android遞歸壓縮上傳多張圖片到七牛的實(shí)例代碼
本篇文章主要介紹了android遞歸壓縮上傳多張圖片到七牛的實(shí)例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08
Android中使用LayoutInflater要注意的一些坑
LayoutInflater類在我們?nèi)粘i_發(fā)中經(jīng)常會用到,最近在使用中就遇到了一些問題,所有下面這篇文章主要給大家總結(jié)了關(guān)于Android中使用LayoutInflater要注意的一些坑,希望通過這篇能讓大家避免走一些彎路,需要的朋友可以參考學(xué)習(xí),下面來一起看吧。2017-04-04
Android開發(fā)使用UncaughtExceptionHandler捕獲全局異常
本文主要介紹在Android開發(fā)中使用UncaughtExceptionHandler捕獲全局異常,需要的朋友可以參考下。2016-06-06
flutter 路由機(jī)制的實(shí)現(xiàn)
本文主要介紹 flutter 中的路由實(shí)現(xiàn)原理,包括初始化時的頁面加載、切換頁面的底層機(jī)制等。具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-07-07

