Android實(shí)現(xiàn)衛(wèi)星菜單效果
前言
最近需求中,需要實(shí)現(xiàn) 衛(wèi)星菜單的需求,最終通過自定義View和動畫屬性來實(shí)現(xiàn),具體功能如下:
1.自定義View
import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.AnimationUtils; import android.view.animation.RotateAnimation; import android.view.animation.TranslateAnimation; import com.xinrui.headsettest.R; /** * 衛(wèi)星菜單 */ public class SatelliteView extends ViewGroup { private View mBtnView; private MenuStatus mBStatus = MenuStatus.STATUS_CLOSE; private onSubItemClickListener onListener; public enum MenuStatus { STATUS_OPEN, STATUS_CLOSE } //子菜單點(diǎn)擊接口 public interface onSubItemClickListener { void onItemClick(View view, int position); } public void setOnSubItemClickListener(onSubItemClickListener mListener) { this.onListener = mListener; } public SatelliteView(Context context) { super(context); // this(context, null); } public SatelliteView(Context context, AttributeSet attrs) { super(context, attrs); // this(context, attrs, 0); } public SatelliteView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int count = getChildCount(); for (int i = 0; i < count; i++) { measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec); } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } //添加布局,就是所要顯示的控件View @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { if (changed) { //主菜單按鈕 onMainButton(); //子菜單按鈕 onSubItemButton(); } } //獲取主菜單按鈕 private void onMainButton() { mBtnView = getChildAt(0); mBtnView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //主菜單動畫旋轉(zhuǎn)動畫 Animation rotateAnim = AnimationUtils.loadAnimation(getContext(), R.anim.satellite_anim); mBtnView.startAnimation(rotateAnim); //子菜單動畫 subItemAnim(); } }); int l, t, r = 0, b = 0; int mWidth = mBtnView.getMeasuredWidth(); int mHeight = mBtnView.getMeasuredHeight(); l = getMeasuredWidth() - mWidth; t = getMeasuredHeight() - mHeight; mBtnView.layout(l, t, getMeasuredWidth(), getMeasuredHeight()); } //獲取子菜單按鈕 private void onSubItemButton() { int count = getChildCount(); for (int i = 0; i < count - 1; i++) { View childView = getChildAt(i + 1); //開始時不呈現(xiàn)子菜單 childView.setVisibility(View.GONE); int radius = 350; int cl, ct, cr, cb; cr = (int) (radius * Math.sin(Math.PI / 2 / (count - 2) * i)); cb = (int) (radius * Math.cos(Math.PI / 2 / (count - 2) * i)); int cWidth = childView.getMeasuredWidth(); int cHeight = childView.getMeasuredHeight(); cl = getMeasuredWidth() - cWidth - cr; ct = getMeasuredHeight() - cHeight - cb; //layout(l,t,r,b);前兩參數(shù)決定位置,后兩參數(shù)決定大小 //參數(shù)(1,t)為View控件的左上角坐標(biāo) // (r-l,b-t)為View控件大小,r-l為控件寬度,b-t為控件高度 childView.layout(cl, ct, getMeasuredWidth() - cr, getMeasuredHeight() - cb); } } //子菜單散開回籠動畫 public void subItemAnim() { int count = getChildCount(); for (int i = 0; i < count - 1; i++) { final View childView = getChildAt(i + 1); //點(diǎn)擊主菜單后,子菜單就立刻呈現(xiàn),否則后面的動畫無法完成 childView.setVisibility(VISIBLE); int radius = 350; int l, t, r, d; r = (int) (radius * Math.sin(Math.PI / 2 / (count - 2) * i)); d = (int) (radius * Math.cos(Math.PI / 2 / (count - 2) * i)); // int cWidth = cView.getMeasuredWidth(); // int cHeight = cView.getMeasuredHeight(); // // l = getMeasuredWidth() - cWidth - r; // t = getMeasuredHeight() - cHeight - d; AnimationSet mAnimationSet = new AnimationSet(true); Animation mTranAnimation = null; if (mBStatus == MenuStatus.STATUS_CLOSE) { //散開動畫 mTranAnimation = new TranslateAnimation(r, 0, d, 0); childView.setClickable(true); childView.setFocusable(true); } else { //回籠動畫 mTranAnimation = new TranslateAnimation(0, r, 0, d); childView.setClickable(false); childView.setFocusable(false); } mTranAnimation.setDuration(300); // tranAnim.setFillAfter(true); //讓最后一幀的動畫不消失 mTranAnimation.setStartOffset(100 * i / count); mTranAnimation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { if (mBStatus == MenuStatus.STATUS_CLOSE) { childView.setVisibility(GONE); } } @Override public void onAnimationRepeat(Animation animation) { } }); Animation rotateAnim = new RotateAnimation( 0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotateAnim.setDuration(300); // rotateAnim.setFillAfter(false); mAnimationSet.addAnimation(rotateAnim); mAnimationSet.addAnimation(mTranAnimation); childView.startAnimation(mAnimationSet); //散開后子菜單的點(diǎn)擊監(jiān)聽事件 final int pos = i + 1; childView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (onListener != null) { onListener.onItemClick(childView, pos); } //散開后點(diǎn)擊子菜單動畫 subItemClickAnim(pos - 1); changStatus(); } }); } changStatus(); } //監(jiān)聽子菜單狀態(tài)改變 private void changStatus() { mBStatus = (mBStatus == MenuStatus.STATUS_CLOSE ? MenuStatus.STATUS_OPEN : MenuStatus.STATUS_CLOSE); } //散開后點(diǎn)擊子菜單動畫 private void subItemClickAnim(int pos) { int count = getChildCount(); for (int i = 0;i<count-1;i++) { View mChildView = getChildAt(i+1); if(i == pos) { //變大,變透明 mChildView.startAnimation(toBig()); } else { //變小,變透明 mChildView.startAnimation(toSmall()); } mChildView.setClickable(false); mChildView.setFocusable(false); } } //變大,變透明 private Animation toBig(){ Animation big = AnimationUtils.loadAnimation(getContext(), R.anim.bigalpha); return big; } //變小,變透明 private Animation toSmall(){ Animation small = AnimationUtils.loadAnimation(getContext(),R.anim.smallalpha); return small; } //給ListView調(diào)用 public boolean isOpen() { return mBStatus == MenuStatus.STATUS_OPEN; } }
2.SatelliteActivity
import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.AbsListView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.Toast; import com.xinrui.headsettest.arc.SatelliteView; import java.util.ArrayList; import java.util.List; public class SatelliteActivity extends Activity { private SatelliteView mSatelliteView; private ListView mListView; private List<String> mData; private ArrayAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.satellite_layout); mSatelliteView = (SatelliteView) findViewById(R.id.view_arc); mSatelliteView.setOnSubItemClickListener(new SatelliteView.onSubItemClickListener() { @Override public void onItemClick(View view, int position) { Toast.makeText(SatelliteActivity.this, "position" + position, Toast.LENGTH_SHORT).show(); } }); initListView(); } private void initListView() { mListView = (ListView) findViewById(R.id.listview); mData = new ArrayList<String>(); for (int i = 'A'; i <= 'z'; i++) { mData.add((char) i + ""); } mAdapter = new ArrayAdapter<String>( SatelliteActivity.this, android.R.layout.simple_list_item_1, mData); mListView.setAdapter(mAdapter); mListView.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (mSatelliteView.isOpen()) { mSatelliteView.subItemAnim(); } } }); } }
3.satellite_layout.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:id="@+id/listview" android:layout_width="match_parent" android:layout_height="match_parent"/> <com.xinrui.headsettest.arc.SatelliteView android:id="@+id/view_arc" android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:src="@drawable/menu" /> </RelativeLayout> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/camera" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/chat" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/contacts" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/music" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/moon" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/location" /> </com.xinrui.headsettest.arc.SatelliteView> </RelativeLayout>
4.anim動畫 在res 新建anim文件夾
satellite_anim.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <rotate android:duration="300" android:fromDegrees="0" android:toDegrees="360" android:pivotX="50%" android:pivotY="50%"/> </set>
bigalpha.xml
<!--android:fillAfter="true"得加,取動畫結(jié)束后的最后一幀--> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true"> <alpha android:duration="200" android:fromAlpha="1" android:toAlpha="0"/> <scale android:duration="200" android:fromXScale="1" android:fromYScale="1" android:toXScale="3" android:toYScale="3" android:pivotX="50%" android:pivotY="50%" /> </set>
smallalpha.xml
<!--android:fillAfter="true"得加,取動畫結(jié)束后的最后一幀--> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true"> <alpha android:duration="200" android:fromAlpha="1" android:toAlpha="0"/> <scale android:duration="200" android:fromXScale="1" android:fromYScale="1" android:toXScale="0" android:toYScale="0" android:pivotX="50%" android:pivotY="50%" /> </set>
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android實(shí)現(xiàn)微博菜單彈出效果
- Android 側(cè)滑抽屜菜單的實(shí)現(xiàn)代碼
- Android實(shí)現(xiàn)動畫效果的自定義下拉菜單功能
- Android實(shí)現(xiàn)上下菜單雙向滑動
- Android如何實(shí)現(xiàn)底部菜單固定到底部
- Android實(shí)現(xiàn)微信加號菜單模式
- Android自定義轉(zhuǎn)盤菜單效果
- Android底部菜單欄(RadioGroup+Fragment)美化
- Android recyclerView橫條指示器實(shí)現(xiàn)淘寶菜單模塊
- android studio 的下拉菜單Spinner使用詳解
- Android仿新浪微博發(fā)送菜單界面的實(shí)現(xiàn)
相關(guān)文章
webview添加參數(shù)與修改請求頭的user-agent實(shí)例
這篇文章主要介紹了webview添加參數(shù)與修改請求頭的user-agent實(shí)例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03Android條紋進(jìn)度條的實(shí)現(xiàn)(調(diào)整view寬度仿進(jìn)度條)
這篇文章主要給大家介紹了關(guān)于Android實(shí)現(xiàn)條紋進(jìn)度條的方法,主要是通過調(diào)整view寬度仿進(jìn)度條,文中通過示例代碼介紹的非常詳細(xì),對各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧2018-09-09android教程使用webview訪問https的url處理sslerror示例
這篇文章主要介紹了android教程使用webview訪問https的url處理sslerror示例,大家參考使用吧2014-01-01淺談Android IPC機(jī)制之Binder的工作機(jī)制
IPC機(jī)制即為跨進(jìn)程通信,是inter-Process Communication的縮寫。是指兩個進(jìn)程之間進(jìn)行通信。在說進(jìn)程通信之前,我們的弄明白什么是線程,什么是進(jìn)程。進(jìn)程和線程是兩個截然不同的概念。本文將介紹Android IPC機(jī)制之Binder的工作機(jī)制。2021-06-06Android實(shí)現(xiàn)ListView數(shù)據(jù)動態(tài)加載的方法
這篇文章主要介紹了Android實(shí)現(xiàn)ListView數(shù)據(jù)動態(tài)加載的方法,通過ListView控件綁定setOnScrollListener方法簡單實(shí)現(xiàn)動態(tài)加載數(shù)據(jù)的功能,需要的朋友可以參考下2016-01-01Android視頻加水印之FFmpeg的簡單應(yīng)用實(shí)例
最近有個需求,需要錄制視頻,能添加水印,所以下面這篇文章主要給大家介紹了關(guān)于Android視頻加水印之FFmpeg的簡單應(yīng)用的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-05-05通過實(shí)例簡單講解Android App中的Activity組件
這篇文章主要介紹了通過Android App中的Activity組件,包括Activity的定義和繼承以及啟動等基本知識,需要的朋友可以參考下2016-04-04