欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android实现卫星菜单效果

程序员文章站 2022-04-09 17:00:41
前言最近需求中,需要实现 卫星菜单的需求,最终通过自定义view和动画属性来实现,具体功能如下:1.自定义viewimport android.content.context;import andro...

前言

最近需求中,需要实现 卫星菜单的需求,最终通过自定义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>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。