-
onMeasure & onLayout查看全部
-
测试和完善 1.添加一个ListView,在滚动ListView时如果菜单是打开的,那么将菜单将闭合 mListView.setOnScrollListener(new AbsListView.OnScrollListener() { public void onScroll(……) { if (mArcMenuLeftBottom.isOpen()){ mArcMenuLeftBottom.toggleMenu(600); } } }); 这个isOpen函数用来判断当前菜单是否是打开的 2.为菜单项添加点击相应事件 mArcMenuRightBottom.setOnMenuItemClickListener(new ArcMenu.OnMenuItemClickListener() { public void onClick(View view, int pos) { Toast.makeText(MainActivity.this, ""+view.getTag(), Toast.LENGTH_SHORT).show(); } }); 3.优化布局文件 (1)将ArcMenu的布局重新放入一个新的布局xml中,可以指定其位置 <com.zhangxt4.satellitemenu.view.ArcMenu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:zhangxt4="http://schemas.android.com/apk/res-auto" android:id="@+id/id_menu_left_bottom" zhangxt4:position="left_bottom" zhangxt4:radius="150dp"> 注意添加命名空间 (2)在主布局中直接include就行了 <include layout="@layout/menu_left_bottom" ></include> 注意ArcMenu的先后顺序,后面的会覆盖前面的,所以要把ArcMenu放到后面。查看全部
-
监听item点击事件——设置点击动画 1.实现目标: 当菜单展开后,点击某个子菜单,它会变大消失,其他菜单项会缩小消失 这个处理应该是toggleMenu的for循环中实现,因为每个子菜单都具备这样的功能。 思路: 当点击某个菜单项时,会遍历每个子菜单,根据pos参数来判断,被点击了就会放大,其他缩小。 2.步骤如下: final int pos = i+1; childView.setOnClickListener(new OnClickListener() { public void onClick(View v) { if(mMenuItemClickListener != null) { //设置点击事件 mMenuItemClickListener.onClick(childView, pos); } //设置点击后的动画,即被点击者放大消失,其他菜单缩小消失 menuItemAnim(pos); //更新菜单闭合/展开状态,如果当前是open的,点击后应该是close changeStatus(); } }); 3.点击某个子菜单后的动画效果: (1)遍历所有的子菜单View,如果是被点击的菜单item,就放大消失,其他缩小消失 (2)最后点击后的动画效果完毕后,所有的子View都不能点击和聚焦了 private void menuItemAnim(int pos) { for(int i = 1; i<getChildCount(); i++) { View childView = getChildAt(i); if (i == pos) { childView.startAnimation(scaleBigAnim(300)); } else { childView.startAnimation(scaleSmallAnim(300)); } childView.setClickable(false); childView.setFocusable(false); } } 4.被点击菜单项会出现放大消失两个动画效果(如图) 5.其他菜单项会出现缩小消失两个动画效果(同上)查看全部
-
展开item——结尾 1.最后需要设置一个移出的先后顺序,效果像是依次展开每个子菜单 tranAnim.setStartOffset((i*100)/count); 2.两个小注意点: (1)改变菜单展开/闭合状态的时间应该在for循环之外 (2)正确设置两个动画的先后顺序 animSet.addAnimation(rotateAnim); animSet.addAnimation(tranAnim);查看全部
-
展开item——子菜单的展开/闭合 1.在明确实现目标之后,在for循环中实现每个子View的平移和旋转动画效果 public void toggleMenu(int duration) { for (int i = 0; i < count-1; i++){ childView.setVisibility(View.VISIBLE); //起始应该是显示的 (1)创建一个AnimationSet来包含这两个动画 AnimationSet animSet = new AnimationSet(true); (2)平移动画 1)为子菜单项平移动画设置开始和结束位置 当ViewGroup在左边时,start位置相对于end是左移的,即(-cl) 当ViewGroup在顶部时,start位置相对于end是上移的,即(-ct) 2)根据当前状态来设置动画 if (Status.CLOSE){//to open tranAnim = new TranslateAnimation(cl*xflag, 0, ct*yflag, 0); }else {//to close tranAnim = new TranslateAnimation(0, cl*xflag, 0, ct*yflag); } 3)为动画设置一个监听,设置动画结束后子View的显示/消失 if (Status.CLOSE){ childView.setVisibility(View.GONE); } (2)旋转动画 RotateAnimation rotateAnim = new RotateAnimation(0, 720f, ……); (3)为子菜单view设置这两个动画 animSet.addAnimation(rotateAnim); animSet.addAnimation(tranAnim); childView.startAnimation(animSet); } (4)最后在for循环之后更新一下状态 changeStatus();//mCurrentStatus = (mCurrentStatus == Status.CLOSE?Status.OPEN:Status.CLOSE); }查看全部
-
展开item 1.首先要明确目标: 点击主按钮时,主按钮有一个旋转动画;同时子菜单项会展开,每个子菜单项有一个平移动画和一个旋转动画。 所以整个效果都会在主按钮的onClick()中实现 2.主按钮的旋转动画 (1)onClick() public void onClick(View v) { rotateCButton(v, 0f, 360f, 300); //将主按钮旋转动画专门放在一个函数中处理 …… } (2)rotateCButton() private void rotateCButton(View v, float start, float end, int duration) { //1. 创建一个旋转动画,指定起始和结束角度,以及旋转中心点 //旋转中心是以自己为中心,0.5f表示自己View的一半 RotateAnimation anim = new RotateAnimation(start, end, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); //2. 设置旋转时间,并指定在旋转后就固定住不动了 anim.setDuration(duration); anim.setFillAfter(true); //3. 为主按钮view设置这个动画 v.startAnimation(anim); } 3.展开/关闭子菜单时的动画 实现目标: (1)子菜单View本身就是存在于最终显示位置的,只是闭合时设置为GONE了 (2)点击主按钮时,每个子菜单View会从主按钮的位置平移到显示位置,同时伴随有旋转动画 (3)这些子菜单View旋转出来有一点点先后顺序 这里就需要有一个toggleMenu()的方法,根据当前菜单的闭合/展开状态来显示不同的动画效果,并更新状态 接下来单独拉出来一个笔记来说查看全部
-
定位item(定位每个子菜单的位置) (2)这是一个复杂的过程,首先通过图算出子菜单View的相对于父容器左边和顶部的宽和高,实际上就是对应layout(int l, int t, int r, int b)的l和t这两个参数 但是要注意由于菜单位置不同,l和t的计算值会不同 //逐个定位每个子菜单View的位置 for (int i = 0; i < count - 1; i++){ View child = getChildAt(i+1); //因为主按钮是0,所以子菜单从1开始到count-1 int cl = (int) (mRadius * Math.sin(Math.PI/2/(count-2)*i)); //注意第一个子菜单的sin角度为0 int ct = (int) (mRadius * Math.cos(Math.PI/2/(count-2)*i)); //每个子菜单View本身的宽和高 int cWidth = child.getMeasuredWidth(); int cHeight = child.getMeasuredHeight(); //如果菜单位于底部(左下,右下),相对于顶部的参数ct就需要调整 if (mPosition == Position.LEFT_BOTTOM || mPosition == Position.RIGHT_BOTTOM){ ct = getMeasuredHeight() - cHeight - ct; } //如果菜单位于右部(右下,右上),相对于左边的参数cl就需要调整 if (mPosition == Position.RIGHT_BOTTOM || mPosition == Position.RIGHT_TOP){ cl = getMeasuredWidth() - cWidth - cl; } child.layout(cl, ct, cl+cWidth, ct+cHeight); }查看全部
-
重写onMeasure()和onLayout() 1.要测量和定位自定义控件(ViewGroup)中的所有子View,就需要重写这两个方法 2.首先需要在layout布局中定义ArcMenu这个ViewGroup中的所有子View(child)(略) 注意: (1)第一个child View就是主按钮,即getChildAt(0)。它也是由两个图片合成的RelativeLayout (2)每个子菜单对应的View是一个ImageView,当然这里也可以定义成一个包裹ImageView的RelativeLayout 3.onMeasure()完成所有子View的测量 (如图) 4.onLayout()完成所有子View的定位 (1)定位主按钮 private void layoutCButton() { mCButton = getChildAt(0); //第一个子View就是主按钮 //定位一个view需要使用ViewGroup的layout(int l, int t, int r, int b)方法 四个参数分别为相对父容器的left,top,right和bottom 下面是根据主按钮的位置来确定这四个参数值 int l = 0, t = 0; //默认 int width = mCButton.getMeasuredWidth(); //获取主按钮的宽 int height = mCButton.getMeasuredHeight(); //获取主按钮的高 switch (mPosition){ case LEFT_TOP: case LEFT_BOTTOM: t = getMeasuredHeight() - height; //在下边时,t=ViewGroup的高-主按钮的高 case RIGHT_TOP: l = getMeasuredWidth() - width; //在右边时,l=ViewGroup的宽-主按钮的宽 case RIGHT_BOTTOM: 同上; } mCButton.layout(l, t, l+width, t+height); //传入四个参数来定位主按钮 } (2)定位子菜单的View(下一笔记)查看全部
-
自定义属性 2)在ArcMenu构造函数中获取属性值 TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ArcMenu, defStyleAttr, 0); int position = ta.getInt(R.styleable.ArcMenu_position, POS_RIGHT_BOTTOM); //获取在layout布局中指定的位置属性,默认是右下 mRadius = (int) ta.getDimension(R.styleable.ArcMenu_radius, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics())); //获取在layout布局中指定的半径属性值,默认是100dp;第二个参数是将100dp转换成像素值 3.为子菜单项设置点击回调接口 public interface OnMenuItemClickListener { //声明要实现的接口方法 void onClick(View view, int pos); } private OnMenuItemClickListener mMenuItemClickListener; //设置回调的接口 public void SetOnMenuItemClickListener(OnMenuItemClickListener mListener) { this.mMenuItemClickListener = mListener; }查看全部
-
自定义属性 1.定义两个自定义属性:主按钮位置、子菜单半径 2.自定义属性的使用步骤: (1)在attr.xml中定义这两个属性 <resources> <attr name="position" > <enum name="left_top" value="0" /> <enum name="left_bottom" value="1" /> <enum name="right_top" value="2" /> <enum name="right_bottom" value="3" /> </attr> <attr name="radius" format="dimension" /> <declare-styleable name="ArcMenu"> <attr name="position" /> <attr name="radius" /> </declare-styleable> (2)在layout中使用 注意在AS中需要按如下添加命名空间 xmlns:zhangxt4="http://schemas.android.com/apk/res-auto" //添加命名空间 <com.zhangxt4.satellitemenu.view.ArcMenu zhangxt4:position="right_bottom" zhangxt4:radius="150dp"> (3)在自定义控件中读取layout中指定的属性值 自定义控件为public class ArcMenu extends ViewGroup { 1)首先定义连个变量用来表示前面的两个属性 //菜单位置的枚举类 public enum Position { LEFT_TOP, LEFT_BOTTOM, RIGHT_TOP, RIGHT_BOTTOM } private Position mPosition = Position.RIGHT_BOTTOM; //默认是右下方 private int mRadius; //子菜单的半径 2)在ArcMenu构造函数中获取属性值(如图) 根据获取的属性值来设置主按钮位置和半径 3.为子菜单项设置回调点击事件查看全部
-
功能介绍 1.要完成的工作 (1)这是一个自定义控件,其位置属性可以是四个角的任何位置 (2)弹出子菜单的时候会有一些动画效果 (3)子菜单的位置本来就在(刚开始隐藏了),点击主按钮时会出现,同时伴随动画效果 (4)子菜单的位置要经过数学知识来计算得到查看全部
-
layout(左,上,右,下)原点是以屏幕的左上角查看全部
-
ScaleAnimation的构造函数,最难理解的应该就是:int pivotXType, float pivotXValue, int pivotYType, float pivotYValue。 pivotXType和pivotXValue指的就是放大和缩小的中心点。选择Animation.RELATIVE_TO_SELF和0.5f就是以自己为标准,x轴的中心。查看全部
-
讲的不错。查看全部
-
自定义ViewGroup查看全部
举报
0/150
提交
取消