Android实现卫星菜单效果
程序员文章站
2022-04-09 17:00:41
前言最近需求中,需要实现 卫星菜单的需求,最终通过自定义view和动画属性来实现,具体功能如下:1.自定义viewimport android.content.context;import andro...
前言
最近需求中,需要实现 卫星菜单的需求,最终通过自定义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>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 【CSS3】纯CSS3制作页面切换效果
下一篇: ES6箭头函数和扩展实例分析