软件编程
位置:首页>> 软件编程>> Android编程>> Android实现卫星菜单效果

Android实现卫星菜单效果

作者:爱码士_yan  发布时间:2021-12-12 23:44:28 

标签:Android,卫星菜单

前言

最近需求中,需要实现 卫星菜单的需求,最终通过自定义View和动画属性来实现,具体功能如下:

Android实现卫星菜单效果

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;
/**
* 卫星菜单
*/
public class SatelliteView extends ViewGroup {
 private View mBtnView;
 private MenuStatus mBStatus = MenuStatus.STATUS_CLOSE;
 private onSubItemClickListener onListener;

public enum MenuStatus {
   STATUS_OPEN, STATUS_CLOSE
 }

//子菜单点击接口
 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) {
       //主菜单动画旋转动画
       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);

//开始时不呈现子菜单
     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);前两参数决定位置,后两参数决定大小
     //参数(1,t)为View控件的左上角坐标
     // (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);

//点击主菜单后,子菜单就立刻呈现,否则后面的动画无法完成
     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);

//散开后子菜单的点击监听事件
     final int pos = i + 1;
     childView.setOnClickListener(new OnClickListener() {
       @Override
       public void onClick(View v) {
         if (onListener != null) {
           onListener.onItemClick(childView, pos);
         }
         //散开后点击子菜单动画
         subItemClickAnim(pos - 1);
         changStatus();
       }
     });
   }
   changStatus();
 }

//监听子菜单状态改变
 private void changStatus() {
   mBStatus = (mBStatus == MenuStatus.STATUS_CLOSE ? MenuStatus.STATUS_OPEN : MenuStatus.STATUS_CLOSE);
 }

//散开后点击子菜单动画
 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调用
 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"得加,取动画结束后的最后一帧-->
<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"得加,取动画结束后的最后一帧-->
<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>

来源:https://blog.csdn.net/baidu_41666295/article/details/106909156

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com