Respecting the author's labor achievements, please indicate the article from http://blog.csdn.net/allen315410/article/details/39232535 when reproduced.
Recently learning, see a copy of the information on how to write a custom control, the above example is a youku earlier version of the client, the client's menu is a custom component (now the version is not clear there is no, did not download), well, not much to say, first on the Youku prototype diagram.
This custom component is sensory, three-storey design, each layer has different menu buttons, each layer also set the entry and exit animation, to enhance the user experience. This design is very good, concise and beautiful, the following is I modeled a cool menu custom component, written so-so, only as a reference.
1, first, inside and outside the three layer seemingly chaotic, in fact, nothing is the UI layout, not advanced. Here is the layout file:
<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 "Tools:context =". Mainactivity "> <relativelayout android:id=" @+id/rl_level1 "android:layout_width=" 100dip "an droid:layout_height= "50dip" android:layout_alignparentbottom= "true" android:layout_centerhorizontal= "true" android:background= "@drawable/level1" > <imagebutton android:id= "@+id/ib_home" an Droid:layout_width= "Wrap_content" android:layout_height= "Wrap_content" android:layout_centerinparent = "true" android:background= "@drawable/icon_home"/> </RelativeLayout> <relativelayout Android:id= "@+id/rl_level2" android:layout_width= "200dip" android:layout_height= "100dip" Android:layo Ut_alignparentbottom= "true" Android: Layout_centerhorizontal= "true" android:background= "@drawable/level2" > <imagebutton androi D:layout_width= "Wrap_content" android:layout_height= "Wrap_content" android:layout_alignparentbottom= "True" android:layout_marginbottom= "5dip" android:layout_marginleft= "10dip" android:backg round= "@drawable/icon_search"/> <imagebutton android:id= "@+id/ib_menu" Android:layout_ Width= "Wrap_content" android:layout_height= "Wrap_content" android:layout_centerhorizontal= "true" android:layout_margintop= "10dip" android:background= "@drawable/icon_menu"/> <imagebutton Android:layout_width= "Wrap_content" android:layout_height= "Wrap_content" android:layout_a Lignparentbottom= "true" android:layout_alignparentright= "true" android:layout_marginbottom= "5dip" Android:layout_marginright= "10dip" android:background= "@drawable/icon_myyouku"/> </RelativeLayout> <relativ Elayout android:id= "@+id/rl_level3" android:layout_width= "320dip" android:layout_height= "160dip" Android:layout_alignparentbottom= "true" android:layout_centerhorizontal= "true" android:background= "@drawa Ble/level3 "> <imagebutton android:id=" @+id/ib_channel1 "android:layout_width=" Wrap_con Tent "android:layout_height=" Wrap_content "android:layout_alignparentbottom=" true "Androi D:layout_marginbottom= "10dip" android:layout_marginleft= "15dip" android:background= "@drawable/channe L1 "/> <imagebutton android:id=" @+id/ib_channel2 "android:layout_width=" Wrap_content " android:layout_height= "Wrap_content" android:layout_above= "@id/ib_channel1" android:layout _marginbottom= "20dip" android:layout_marginleft= "40dip" android:background= "@drawable/channel2"/> <imagebutton Android:layout_width= "Wrap_content" android:layout_height= "Wrap_content" Android:layout_ Above= "@id/ib_channel2" android:layout_marginbottom= "15dip" android:layout_marginleft= "10dip" android:layout_torightof= "@id/ib_channel2" android:background= "@drawable/channel3"/> <imageb Utton android:layout_width= "wrap_content" android:layout_height= "Wrap_content" Android:la Yout_centerhorizontal= "true" android:layout_margintop= "10dip" android:background= "@drawable/channel4 "/> <imagebutton android:id=" @+id/ib_channel7 "android:layout_width=" Wrap_content " android:layout_height= "Wrap_content" android:layout_alignparentbottom= "true" Android:layout_ Alignparentright= "true" Android:layout_marginbottom= "10dip" android:layout_marginright= "15dip" Android:background = "@drawable/channel7"/> <imagebutton android:id= "@+id/ib_channel6" Android:layout_widt H= "Wrap_content" android:layout_height= "wrap_content" android:layout_above= "@id/ib_channel7" Android:layout_alignparentright= "true" android:layout_marginbottom= "20dip" Android:layout_margin right= "40dip" android:background= "@drawable/channel6"/> <imagebutton android:layout_wi Dth= "Wrap_content" android:layout_height= "wrap_content" android:layout_above= "@id/ib_channel6" Android:layout_marginbottom= "15dip" android:layout_marginright= "10dip" Android:layout_toleftof = "@id/ib_channel6" android:background= "@drawable/channel5"/> </relativelayout></relativelayout& Gt
The UI effect after layout is shown in the figure:
As shown, the layout is complete, the next step is to add some dynamic effect, the effect is described as: the menu from the inside Out is called "Level 1 Menu", "Level 2 Menu" and "Level 3 menu", 1-level menu and 2-level menu central location of the ImageButton to control the whole menu dynamic effect. When you click the Level 1 menu, if the level 2 or Level 3 menu is displayed, the 2 level and level 3 menus are hidden, and if not displayed, only the Level 2 menu is displayed. When you click on the Level 2 menu, you only control the display and hiding of the Level 3 menu.
All of the dynamic effects here are implemented by custom rotation animations, which we'll first complete with this custom rotation animation:
Package Com.example.youkumenu;import Android.view.animation.animation;import Android.view.animation.rotateanimation;import Android.widget.relativelayout;public class AnimationUtils {public static Boolean isrunninganimation = false; Record whether the animation is executing/** * rotate out of animation * * @param layout * object to animate * @param startoffset * delay time */public Static V OID outrotateanimation (relativelayout layout, long Startoffset) {//prevents child controls in the parent control from grabbing a strong focus and setting the child control to unavailable for (int i = 0; I < lay Out.getchildcount (); i++) {Layout.getchildat (i). SetEnabled (false);} Rotateanimation ra = new Rotateanimation (//0.0f,//rotation start angle -180.0f,//rotation end angle rotateanimation.relative_to_self,//rotation coordinate X Axis reference 0.5f,//relative to the reference x-axis percentage rotateanimation.relative_to_self,//rotation coordinate y-axis reference 1.0f//relative to the reference y-axis percentage); Ra.setduration (500); Ra.setstartoffset (Startoffset); Animation delay Time Ra.setfillafter (true); Ra.setanimationlistener (new Myanimationlistener ()); Layout.startanimation (RA);} /** * Rotate in animation * * @param layout * Animate objects */public static void InrotAteanimation (relativelayout layout) {//Come in, set all the child controls to available for (int i = 0; i < Layout.getchildcount (); i++) {layout.getc Hildat (i). SetEnabled (false);} Rotateanimation ra = new Rotateanimation (//-180.0f,//rotation start angle 0.0f,//rotation end angle rotateanimation.relative_to_self,//rotation coordinate X Axis reference 0.5f,//relative to the reference x-axis percentage rotateanimation.relative_to_self,//rotation coordinate y-axis reference 1.0f//relative to the reference y-axis percentage); Ra.setduration (500); Ra.setfillafter (True); Layout.startanimation (RA);} Static Class Myanimationlistener implements Animation.animationlistener {/** * animation start time execution */@Overridepublic void Onanimationstart (Animation Animation) {//TODO auto-generated method stubisrunninganimation = true;} /** * At the end of the animation execution */@Overridepublic void Onanimationend (Animation Animation) {//TODO auto-generated method Stubisrunningan Imation = false;} /** * Animation repeated execution time */@Overridepublic void Onanimationrepeat (Animation Animation) {//TODO auto-generated Method stub}}}
Here is the main code for mainactivity, which controls the dynamic change of the menu:
Package Com.example.youkumenu;import Android.os.bundle;import Android.app.activity;import android.view.KeyEvent; Import Android.view.view;import Android.view.view.onclicklistener;import Android.widget.relativelayout;public Class Mainactivity extends Activity implements Onclicklistener {private Relativelayout rllevel1;private relativelayout Rllevel2;private relativelayout rllevel3;/** Record Level 3 Menu Show */private boolean isDisplayLevel3 = true;/** Record Level 2 menu is displayed */ Private Boolean IsDisplayLevel2 = true;/** Records whether the Level 1 menu shows */private boolean isDisplayLevel1 = true; @Overrideprotected void OnC Reate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main); RlLevel1 = (relativelayout) Findviewbyid (r.id.rl_level1); RlLevel2 = (relativelayout) Findviewbyid (R.ID.RL_LEVEL2); RlLevel3 = (relativelayout) Findviewbyid (R.ID.RL_LEVEL3); Findviewbyid (R.id.ib_home). Setonclicklistener (this); Findviewbyid (R.id.ib_menu). Setonclicklistener (this);} @Overridepublic void OnClick (View v) {sWitch (V.getid ()) {case R.id.ib_home:if (animationutils.isrunninganimation)//When the current animation is executing, do not animate return;if ( ISDISPLAYLEVEL2) {//Level 2 menu is showing long startoffset = 0;//rotation delay time if (ISDISPLAYLEVEL3) {//3 level menu is also showing, first rotate out 3 level menu, Then rotate out the Level 2 menu animationutils.outrotateanimation (RlLevel3, startoffset); Startoffset + = 200;ISDISPLAYLEVEL3 =! IsDisplayLevel3;} Animationutils.outrotateanimation (RlLevel2, startoffset);} else {//Level 2 menu not showing, need to rotate in animationutils.inrotateanimation (RLLEVEL2);} IsDisplayLevel2 =!isdisplaylevel2;break;case r.id.ib_menu:if (animationutils.isrunninganimation) return;if ( ISDISPLAYLEVEL3) {//Level 3 menu is showing, need to rotate out animationutils.outrotateanimation (rlLevel3, 0);} else {//3 level menu not shown, Need to rotate in animationutils.inrotateanimation (RLLEVEL3);} IsDisplayLevel3 =!isdisplaylevel3;break;default:break;}} /** * Menu Button processing */@Overridepublic boolean onKeyDown (int keycode, keyevent event) {//TODO auto-generated method Stubif (KEYC Ode = = Keyevent.keycode_menu) {if (animationutils.isrunninganimation) return Super.onkeydown (KeyCode,The IF (ISDISPLAYLEVEL1) {///Level 1 menu rotates out long startoffset = 0;//Record delay time if (ISDISPLAYLEVEL2) {//2 level menu rotates out if (isdisplaylevel 3) {//3 level menu First spin out animationutils.outrotateanimation (RlLevel3, startoffset); Startoffset + = 200;ISDISPLAYLEVEL3 =! IsDisplayLevel3;} Animationutils.outrotateanimation (RlLevel2, startoffset); Startoffset + 200; Delay 200msisdisplaylevel2 =!isdisplaylevel2;} Animationutils.outrotateanimation (RlLevel1, startoffset);} else {//Level 1 menu rotation comes in animationutils.inrotateanimation (RLLEVEL1);} IsDisplayLevel1 =!isdisplaylevel1;} Return Super.onkeydown (KeyCode, event);}}
The above is the entire source code of the custom component, it is worth noting that:
1, about the focus of the control issue.
As you can see in the layout, the controls that I use in this relative layout relativelayout are Imagebutton,imagebutton A notable feature is that it has a particularly strong ability to grab focus. So for each level of the menu in the process of animation execution, the user clicked the ImageButton button, an event response occurs. This kind of user experience is extremely undesirable, then how to solve this problem.
It is true that through API Discovery, Relativelayout inherits from the ViewGroup class
ViewGroup provides a way to traverse a child element getchildat (int index), so we iterate through all the child controls on the menu and set them to be unavailable in the method that the animation animation spins out, and the way in which the animation rotates in, This contradiction is resolved by traversing all the child controls on the menu and setting them to be available.
2, about the Quick Click menu 2 times, when the Quick Click menu 2 times, that is, the first click on the menu, the menu has not been completely rotated out or rotated in, with the second click menu, here to perform the opposite animation effect, that is, the menu has not been completely out or in the time, halfway forced to stop operation, The opposite action is taken, that is, the rotation comes in or spins out. So, how to solve this problem?
With the animated API, you can find an interface that Android provides to us:
public static interface Animationlistener { /** * <p>notifies the start of the animation.</p> *< c3/>* @param animation The started animation. * /void Onanimationstart (Animation Animation); /** * <p>notifies The end of the animation. This callback isn't invoked * for animations with repeat count set to infinite.</p> * * @param animati On the animation which reached its end. * /void Onanimationend (Animation Animation); /** * <p>notifies The repetition of the animation.</p> * * @param animation the animation whic H was repeated. * /void Onanimationrepeat (Animation Animation); }
Through this interface, at a glance the use of these methods, as long as the implementation of a custom class, the implementation of the interface three methods, set a static variable to record whether the current animation is running state, the animation set this listener.
In mainactivity, just call this control menu animation method before, judge the animation running state, then do the operation, so that the problem can be solved.
The above is a personal hobby, the source has been uploaded, welcome everyone to exchange learning.
Please download the source code here
Android custom Controls--Youku Disk menu