当前位置: 移动技术网 > 移动技术>移动开发>Android > Android实现卫星菜单效果

Android实现卫星菜单效果

2020年07月30日  | 移动技术网移动技术  | 我要评论

前言

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

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>

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网