Android学习教程之圆形Menu菜单制作方法(1)
程序员文章站
2024-02-29 10:12:46
本文实例为大家分享了android圆形菜单的使用方法,供大家参考,具体内容如下
mainactivity.java代码:
package siso.hand...
本文实例为大家分享了android圆形菜单的使用方法,供大家参考,具体内容如下
mainactivity.java代码:
package siso.handlerdemo; import android.app.notificationmanager; import android.content.intent; import android.support.v7.app.appcompatactivity; import android.os.bundle; import android.view.view; import android.widget.button; public class mainactivity extends appcompatactivity { private button btnstartservice; private button btnbro; private button btnfile; private button btnsr; private button btnlv; private button btngv; private button btnmth; private button btnmultispinner; private button btnmenu; private button btnslidemenu; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); //------------------------------------------------------------------------------- btnstartservice=(button)findviewbyid(r.id.btnstartservice); btnstartservice.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { intent intent=new intent(mainactivity.this, statusservice.class); startservice(intent); } }); //------------------------------------------------------------------------------- btnbro=(button)findviewbyid(r.id.btnrb); btnbro.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { intent intent=new intent(mainactivity.this, bractivity.class); startactivity(intent); } }); //------------------------------------------------------------------------------- btnfile=(button)findviewbyid(r.id.btnfile); btnfile.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { intent intent=new intent(mainactivity.this, fileactivity.class); startactivity(intent); } }); //------------------------------------------------------------------------------- btnsr=(button)findviewbyid(r.id.btnsr); btnsr.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { intent intent=new intent(mainactivity.this, sharedpactivity.class); startactivity(intent); } }); //------------------------------------------------------------------------------- btnlv=(button)findviewbyid(r.id.btnlv); btnlv.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { intent intent=new intent(mainactivity.this, listviewdemoactivity.class); startactivity(intent); } }); //------------------------------------------------------------------------------- btngv=(button)findviewbyid(r.id.btngv); btngv.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { intent intent=new intent(mainactivity.this, gvactivity.class); startactivity(intent); } }); //------------------------------------------------------------------------------- btnmth=(button)findviewbyid(r.id.btnmth); btnmth.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { intent intent=new intent(mainactivity.this, sampleactivity.class); startactivity(intent); } }); //------------------------------------------------------------------------------- btnmultispinner=(button)findviewbyid(r.id.btnmultispinner); btnmultispinner.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { intent intent=new intent(mainactivity.this, multispinneractivity.class); startactivity(intent); } }); //------------------------------------------------------------------------------- btnmenu=(button)findviewbyid(r.id.btnmenu); btnmenu.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { intent intent=new intent(mainactivity.this, circlemenuactivity.class); startactivity(intent); } }); btnslidemenu=(button)findviewbyid(r.id.btnslidemenu); btnslidemenu.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { intent intent=new intent(mainactivity.this, slidemenuactivity.class); startactivity(intent); } }); } @override protected void onstart() { super.onstart(); notificationmanager manager=(notificationmanager)getsystemservice(notification_service); manager.cancel(r.layout.activity_main); } }
activity_main.xml内容:
<?xml version="1.0" encoding="utf-8"?> <relativelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingbottom="@dimen/activity_vertical_margin" android:paddingleft="@dimen/activity_horizontal_margin" android:paddingright="@dimen/activity_horizontal_margin" android:paddingtop="@dimen/activity_vertical_margin" tools:context="siso.handlerdemo.mainactivity"> <button android:id="@+id/btnstartservice" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="start service" android:layout_alignparenttop="true" android:layout_alignparentstart="true" /> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="hello world!" android:id="@+id/textview" android:layout_below="@+id/btnsr" android:layout_centerhorizontal="true" /> <button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="广播页面" android:id="@+id/btnrb" android:layout_below="@+id/btnstartservice" android:layout_alignparentstart="true" /> <button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="文件保存页面" android:id="@+id/btnfile" android:layout_below="@+id/btnrb" android:layout_alignparentstart="true" /> <button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="使用sharedpreferences进行数据存储" android:id="@+id/btnsr" android:layout_below="@+id/btnfile" android:layout_alignparentstart="true" /> <button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="listview使用" android:id="@+id/btnlv" android:layout_below="@+id/textview" android:layout_centerhorizontal="true" /> <button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="gridview使用" android:id="@+id/btngv" android:layout_below="@+id/btnlv" android:layout_centerhorizontal="true" /> <button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="tabhost" android:id="@+id/btnmth" android:layout_below="@+id/btngv" android:layout_centerhorizontal="true" /> <button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="multispinner" android:id="@+id/btnmultispinner" android:layout_below="@+id/btnmth" android:layout_centerhorizontal="true" /> <button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="menu使用" android:id="@+id/btnmenu" android:layout_below="@+id/btnmultispinner" android:layout_tostartof="@+id/textview" /> <button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="滑动menu" android:id="@+id/btnslidemenu" android:layout_below="@+id/btnmultispinner" android:layout_alignstart="@+id/textview" android:layout_marginstart="37dp" /> </relativelayout>
circlemenuactivity.java代码:
package siso.handlerdemo; import android.support.v7.app.appcompatactivity; import android.os.bundle; import android.view.view; import android.widget.textview; import android.widget.toast; import siso.view.circleimageview; import siso.view.circlelayout; public class circlemenuactivity extends appcompatactivity implements circlelayout.onitemselectedlistener, circlelayout.onitemclicklistener { textview selectedtextview; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_circlemenu); circlelayout circlemenu = (circlelayout)findviewbyid(r.id.main_circle_layout); circlemenu.setonitemselectedlistener(this); circlemenu.setonitemclicklistener(this); selectedtextview = (textview)findviewbyid(r.id.main_selected_textview); selectedtextview.settext(((circleimageview)circlemenu.getselecteditem()).getname()); } @override public void onitemselected(view view, int position, long id, string name) { selectedtextview.settext(name); } @override public void onitemclick(view view, int position, long id, string name) { toast.maketext(getapplicationcontext(), getresources().getstring(r.string.start_app) + " " + name, toast.length_short).show(); } }
circleimageview.java代码:
package siso.view; import android.content.context; import android.content.res.typedarray; import android.util.attributeset; import android.widget.imageview; import siso.handlerdemo.r; public class circleimageview extends imageview { private float angle = 0; private int position = 0; private string name; public float getangle() { return angle; } public void setangle(float angle) { this.angle = angle; } public int getposition() { return position; } public void setposition(int position) { this.position = position; } public string getname(){ return name; } public void setname(string name){ this.name = name; } /** * @param context */ public circleimageview(context context) { this(context, null); } /** * @param context * @param attrs */ public circleimageview(context context, attributeset attrs) { this(context, attrs, 0); } /** * @param context * @param attrs * @param defstyle */ public circleimageview(context context, attributeset attrs, int defstyle) { super(context, attrs, defstyle); if (attrs != null) { typedarray a = getcontext().obtainstyledattributes(attrs, r.styleable.circleimageview); name = a.getstring(r.styleable.circleimageview_name); } } }
circlelayout.java代码:
package siso.view; import android.content.context; import android.content.res.typedarray; import android.graphics.bitmap; import android.graphics.bitmapfactory; import android.graphics.canvas; import android.graphics.matrix; import android.util.attributeset; import android.view.gesturedetector; import android.view.gesturedetector.simpleongesturelistener; import android.view.motionevent; import android.view.view; import android.view.viewgroup; import siso.handlerdemo.r; public class circlelayout extends viewgroup { private onitemclicklistener monitemclicklistener = null; private onitemselectedlistener monitemselectedlistener = null; private oncenterclicklistener moncenterclicklistener = null; private bitmap imageoriginal, imagescaled; private matrix matrix; private int mtappedviewspostition = -1; private view mtappedview = null; private int selected = 0; private int mmaxchildwidth = 0; private int mmaxchildheight = 0; private int childwidth = 0; private int childheight = 0; private int circlewidth, circleheight; private int radius = 0; private gesturedetector mgesturedetector; private boolean[] quadranttouched; private boolean allowrotating = true; private float angle = 90; private float firstchildpos = 90; private boolean rotatetocenter = true; private boolean isrotating = true; /** * @param context */ public circlelayout(context context) { this(context, null); } /** * @param context * @param attrs */ public circlelayout(context context, attributeset attrs) { this(context, attrs, 0); } /** * @param context * @param attrs * @param defstyle */ public circlelayout(context context, attributeset attrs, int defstyle) { super(context, attrs, defstyle); init(attrs); } protected void init(attributeset attrs) { mgesturedetector = new gesturedetector(getcontext(), new mygesturelistener()); quadranttouched = new boolean[] { false, false, false, false, false }; if (attrs != null) { typedarray a = getcontext().obtainstyledattributes(attrs, r.styleable.circle); angle = a.getint(r.styleable.circle_firstchildposition, 90); firstchildpos = angle; rotatetocenter = a.getboolean(r.styleable.circle_rotatetocenter, true); isrotating = a.getboolean(r.styleable.circle_isrotating, true); if (!isrotating) { rotatetocenter = false; } if (imageoriginal == null) { int picid = a.getresourceid( r.styleable.circle_circlebackground, -1); if (picid != -1) { imageoriginal = bitmapfactory.decoderesource( getresources(), picid); } } a.recycle(); if (matrix == null) { matrix = new matrix(); } else { matrix.reset(); } setwillnotdraw(false); } } public view getselecteditem() { return (selected >= 0) ? getchildat(selected) : null; } @override protected void ondraw(canvas canvas) { circleheight = getheight(); circlewidth = getwidth(); if (imageoriginal != null) { if (imagescaled == null) { matrix = new matrix(); float sx = (((radius + childwidth / 4) * 2) / (float) imageoriginal .getwidth()); float sy = (((radius + childwidth / 4) * 2) / (float) imageoriginal .getheight()); matrix.postscale(sx, sy); imagescaled = bitmap.createbitmap(imageoriginal, 0, 0, imageoriginal.getwidth(), imageoriginal.getheight(), matrix, false); } if (imagescaled != null) { int cx = (circlewidth - imagescaled.getwidth()) / 2; int cy = (circleheight - imagescaled.getheight()) / 2; canvas g = canvas; canvas.rotate(0, circlewidth / 2, circleheight / 2); g.drawbitmap(imagescaled, cx, cy, null); } } } @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { mmaxchildwidth = 0; mmaxchildheight = 0; int childwidthmeasurespec = measurespec.makemeasurespec( measurespec.getsize(widthmeasurespec), measurespec.at_most); int childheightmeasurespec = measurespec.makemeasurespec( measurespec.getsize(widthmeasurespec), measurespec.at_most); final int count = getchildcount(); for (int i = 0; i < count; i++) { final view child = getchildat(i); if (child.getvisibility() == gone) { continue; } child.measure(childwidthmeasurespec, childheightmeasurespec); mmaxchildwidth = math.max(mmaxchildwidth, child.getmeasuredwidth()); mmaxchildheight = math.max(mmaxchildheight, child.getmeasuredheight()); } childwidthmeasurespec = measurespec.makemeasurespec(mmaxchildwidth, measurespec.exactly); childheightmeasurespec = measurespec.makemeasurespec(mmaxchildheight, measurespec.exactly); for (int i = 0; i < count; i++) { final view child = getchildat(i); if (child.getvisibility() == gone) { continue; } child.measure(childwidthmeasurespec, childheightmeasurespec); } setmeasureddimension(resolvesize(mmaxchildwidth, widthmeasurespec), resolvesize(mmaxchildheight, heightmeasurespec)); } @override protected void onlayout(boolean changed, int l, int t, int r, int b) { int layoutwidth = r - l; int layoutheight = b - t; final int childcount = getchildcount(); int left, top; radius = (layoutwidth <= layoutheight) ? layoutwidth / 3 : layoutheight / 3; childwidth = (int) (radius / 1.5); childheight = (int) (radius / 1.5); float angledelay = 360 / getchildcount(); for (int i = 0; i < childcount; i++) { final circleimageview child = (circleimageview) getchildat(i); if (child.getvisibility() == gone) { continue; } if (angle > 360) { angle -= 360; } else { if (angle < 0) { angle += 360; } } child.setangle(angle); child.setposition(i); left = math .round((float) (((layoutwidth / 2) - childwidth / 2) + radius * math.cos(math.toradians(angle)))); top = math .round((float) (((layoutheight / 2) - childheight / 2) + radius * math.sin(math.toradians(angle)))); child.layout(left, top, left + childwidth, top + childheight); angle += angledelay; } } private void rotatebuttons(float degrees) { int left, top, childcount = getchildcount(); float angledelay = 360 / childcount; angle += degrees; if (angle > 360) { angle -= 360; } else { if (angle < 0) { angle += 360; } } for (int i = 0; i < childcount; i++) { if (angle > 360) { angle -= 360; } else { if (angle < 0) { angle += 360; } } final circleimageview child = (circleimageview) getchildat(i); if (child.getvisibility() == gone) { continue; } left = math .round((float) (((circlewidth / 2) - childwidth / 2) + radius * math.cos(math.toradians(angle)))); top = math .round((float) (((circleheight / 2) - childheight / 2) + radius * math.sin(math.toradians(angle)))); child.setangle(angle); if (math.abs(angle - firstchildpos) < (angledelay / 2) && selected != child.getposition()) { selected = child.getposition(); if (monitemselectedlistener != null && rotatetocenter) { monitemselectedlistener.onitemselected(child, selected, child.getid(), child.getname()); } } child.layout(left, top, left + childwidth, top + childheight); angle += angledelay; } } private double getangle(double xtouch, double ytouch) { double x = xtouch - (circlewidth / 2d); double y = circleheight - ytouch - (circleheight / 2d); switch (getquadrant(x, y)) { case 1: return math.asin(y / math.hypot(x, y)) * 180 / math.pi; case 2: case 3: return 180 - (math.asin(y / math.hypot(x, y)) * 180 / math.pi); case 4: return 360 + math.asin(y / math.hypot(x, y)) * 180 / math.pi; default: return 0; } } private static int getquadrant(double x, double y) { if (x >= 0) { return y >= 0 ? 1 : 4; } else { return y >= 0 ? 2 : 3; } } private double startangle; @override public boolean ontouchevent(motionevent event) { if (isenabled()) { if (isrotating) { switch (event.getaction()) { case motionevent.action_down: for (int i = 0; i < quadranttouched.length; i++) { quadranttouched[i] = false; } allowrotating = false; startangle = getangle(event.getx(), event.gety()); break; case motionevent.action_move: double currentangle = getangle(event.getx(), event.gety()); rotatebuttons((float) (startangle - currentangle)); startangle = currentangle; break; case motionevent.action_up: allowrotating = true; rotateviewtocenter((circleimageview) getchildat(selected), false); break; } } quadranttouched[getquadrant(event.getx() - (circlewidth / 2), circleheight - event.gety() - (circleheight / 2))] = true; mgesturedetector.ontouchevent(event); return true; } return false; } private class mygesturelistener extends simpleongesturelistener { @override public boolean onfling(motionevent e1, motionevent e2, float velocityx, float velocityy) { if (!isrotating) { return false; } int q1 = getquadrant(e1.getx() - (circlewidth / 2), circleheight - e1.gety() - (circleheight / 2)); int q2 = getquadrant(e2.getx() - (circlewidth / 2), circleheight - e2.gety() - (circleheight / 2)); if ((q1 == 2 && q2 == 2 && math.abs(velocityx) < math .abs(velocityy)) || (q1 == 3 && q2 == 3) || (q1 == 1 && q2 == 3) || (q1 == 4 && q2 == 4 && math.abs(velocityx) > math .abs(velocityy)) || ((q1 == 2 && q2 == 3) || (q1 == 3 && q2 == 2)) || ((q1 == 3 && q2 == 4) || (q1 == 4 && q2 == 3)) || (q1 == 2 && q2 == 4 && quadranttouched[3]) || (q1 == 4 && q2 == 2 && quadranttouched[3])) { circlelayout.this.post(new flingrunnable(-1 * (velocityx + velocityy))); } else { circlelayout.this .post(new flingrunnable(velocityx + velocityy)); } return true; } @override public boolean onsingletapup(motionevent e) { mtappedviewspostition = pointtoposition(e.getx(), e.gety()); if (mtappedviewspostition >= 0) { mtappedview = getchildat(mtappedviewspostition); mtappedview.setpressed(true); } else { float centerx = circlewidth / 2; float centery = circleheight / 2; if (e.getx() < centerx + (childwidth / 2) && e.getx() > centerx - childwidth / 2 && e.gety() < centery + (childheight / 2) && e.gety() > centery - (childheight / 2)) { if (moncenterclicklistener != null) { moncenterclicklistener.oncenterclick(); return true; } } } if (mtappedview != null) { circleimageview view = (circleimageview) (mtappedview); if (selected != mtappedviewspostition) { rotateviewtocenter(view, false); if (!rotatetocenter) { if (monitemselectedlistener != null) { monitemselectedlistener.onitemselected(mtappedview, mtappedviewspostition, mtappedview.getid(), view.getname()); } if (monitemclicklistener != null) { monitemclicklistener.onitemclick(mtappedview, mtappedviewspostition, mtappedview.getid(), view.getname()); } } } else { rotateviewtocenter(view, false); if (monitemclicklistener != null) { monitemclicklistener.onitemclick(mtappedview, mtappedviewspostition, mtappedview.getid(), view.getname()); } } return true; } return super.onsingletapup(e); } } private void rotateviewtocenter(circleimageview view, boolean fromrunnable) { if (rotatetocenter) { float velocitytemp = 1; float destangle = (float) (firstchildpos - view.getangle()); float startangle = 0; int reverser = 1; if (destangle < 0) { destangle += 360; } if (destangle > 180) { reverser = -1; destangle = 360 - destangle; } while (startangle < destangle) { startangle += velocitytemp / 75; velocitytemp *= 1.0666f; } circlelayout.this.post(new flingrunnable(reverser * velocitytemp, !fromrunnable)); } } private class flingrunnable implements runnable { private float velocity; float angledelay; boolean isfirstforwarding = true; public flingrunnable(float velocity) { this(velocity*0.4f, true); } public flingrunnable(float velocity, boolean isfirst) { this.velocity = velocity; this.angledelay = 360 / getchildcount(); this.isfirstforwarding = isfirst; } public void run() { if (math.abs(velocity) > 5 && allowrotating) { if (rotatetocenter) { if (!(math.abs(velocity) < 200 && (math.abs(angle - firstchildpos) % angledelay < 2))) { rotatebuttons(velocity / 75); velocity /= 1.0666f; circlelayout.this.post(this); } } else { rotatebuttons(velocity / 75); velocity /= 1.0666f; circlelayout.this.post(this); } } else { if (isfirstforwarding) { isfirstforwarding = false; circlelayout.this.rotateviewtocenter( (circleimageview) getchildat(selected), true); } } } } private int pointtoposition(float x, float y) { for (int i = 0; i < getchildcount(); i++) { view item = (view) getchildat(i); if (item.getleft() < x && item.getright() > x & item.gettop() < y && item.getbottom() > y) { return i; } } return -1; } public void setonitemclicklistener(onitemclicklistener onitemclicklistener) { this.monitemclicklistener = onitemclicklistener; } public interface onitemclicklistener { void onitemclick(view view, int position, long id, string name); } public void setonitemselectedlistener( onitemselectedlistener onitemselectedlistener) { this.monitemselectedlistener = onitemselectedlistener; } public interface onitemselectedlistener { void onitemselected(view view, int position, long id, string name); } public interface oncenterclicklistener { void oncenterclick(); } public void setoncenterclicklistener( oncenterclicklistener oncenterclicklistener) { this.moncenterclicklistener = oncenterclicklistener; } }
activity_circlemenu.xml内容:
<?xml version="1.0" encoding="utf-8"?> <relativelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:circle="http://schemas.android.com/apk/res-auto" android:paddingbottom="@dimen/activity_vertical_margin" android:paddingleft="@dimen/activity_horizontal_margin" android:paddingright="@dimen/activity_horizontal_margin" android:paddingtop="@dimen/activity_vertical_margin" tools:context="siso.handlerdemo.circlemenuactivity"> <siso.view.circlelayout android:id="@+id/main_circle_layout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_above="@+id/main_selected_textview" android:layout_gravity="center_horizontal" circle:firstchildposition="south" circle:rotatetocenter="false" circle:isrotating="true" > <siso.view.circleimageview android:id="@+id/main_facebook_image" android:layout_width="35dp" android:layout_height="35dp" android:src="@drawable/icon_facebook" circle:name="@string/facebook" /> <siso.view.circleimageview android:id="@+id/main_myspace_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/icon_myspace" circle:name="@string/myspace" /> <siso.view.circleimageview android:id="@+id/main_google_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/icon_google" circle:name="@string/google" /> <siso.view.circleimageview android:id="@+id/main_linkedin_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/icon_linkedin" circle:name="@string/linkedin" /> <siso.view.circleimageview android:id="@+id/main_twitter_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/icon_twitter" circle:name="@string/twitter" /> <siso.view.circleimageview android:id="@+id/main_wordpress_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/icon_wordpress" circle:name="@string/wordpress" /> </siso.view.circlelayout> <textview android:id="@+id/main_selected_textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentbottom="true" android:layout_centerhorizontal="true" android:layout_marginbottom="50dp" android:textappearance="?android:attr/textappearancelarge" /> </relativelayout>
strings.xml内容:
<string name="facebook">facebook</string> <string name="twitter">twitter</string> <string name="google">google</string> <string name="linkedin">linkedin</string> <string name="wordpress">wordpress</string> <string name="myspace">myspace</string> <string name="start_app">starting application:</string>
attrs.xml内容:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="circle"> <attr name="circlebackground" format="integer" /> <attr name="firstchildposition"> <enum name="east" value="0" /> <enum name="south" value="90" /> <enum name="west" value="180" /> <enum name="north" value="270" /> </attr> <attr name="rotatetocenter" format="boolean" /> <attr name="isrotating" format="boolean" /> </declare-styleable> <declare-styleable name="circleimageview"> <attr name="name" format="string" /> </declare-styleable> </resources>
运行结果如图:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。