自定义过程见源码,注释很详细
public class FloatingActionMenu extends ViewGroup {
//展开方向(上下左右)
public static final int EXPAND_UP = 0;
public static final int EXPAND_DOWN = 1;
public static final int EXPAND_LEFT = 2;
public static final int EXPAND_RIGHT = 3;
private static final int ANIMATION_DURATION = 300;//动画持续时间(毫秒ms)
private AnimatorSet mExpandAnimation = new AnimatorSet().setDuration(ANIMATION_DURATION);
private AnimatorSet mCollapseAnimation = new AnimatorSet().setDuration(ANIMATION_DURATION);
private View mBaseView;//菜单中放入的第一个基础控件
private int mExpandDirection;//展开方向
private int mChildviewSpacing;//空白距离
private boolean mExpanded;//菜单是否打开
private int mMaxnWidth;//总的最大宽度
private int mMaxHeight;//总的最大高度
private int mChildCount;//item数
private TouchDelegateGroup mTouchDelegateGroup;//委派类 夸大view的点击范围
private OnFloatingActionsMenuUpdateListener mListener;//展开或收起更新监听
public interface OnFloatingActionsMenuUpdateListener {
void onMenuExpanded();//打开
void onMenuCollapsed();//收起
}
public FloatingActionMenu(Context context) {
this(context, null);
}
public FloatingActionMenu(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public FloatingActionMenu(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
private void init(Context context, AttributeSet attributeSet) {
mChildviewSpacing = 8;
mTouchDelegateGroup = new TouchDelegateGroup(this);
setTouchDelegate(mTouchDelegateGroup);//设置委派 扩大view的点击范围
TypedArray attr = context.obtainStyledAttributes(attributeSet, R.styleable.FloatingActionsMenu, 0, 0);
mExpandDirection = attr.getInt(R.styleable.FloatingActionsMenu_fab_expandDirection, EXPAND_UP);
attr.recycle();
//添加一个基础控件,用于点击展开和收起菜单
createBaseView(context);
}
private void createBaseView(Context context) {
//可以设置各种布局或控件为菜单的打开控件
//设置根布局
mBaseView = LayoutInflater.from(context).inflate(R.layout.baseview_layout,null);
//mBaseView = new Button(context);
// mBaseView.setBackgroundResource(R.drawable.bg_childview);
mBaseView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
toggle();
}
});
addView(mBaseView, super.generateDefaultLayoutParams());
mChildCount++;
}
/**
* 添加控件(或组合控件)
* @param view
*/
public void addActionsView(View view) {
addView(view, mChildCount - 1);
mChildCount++;
}
private void toggle() {
if (mExpanded) {
collapse();
} else {
expand();
}
}
public void expand() {
if (!mExpanded) {
mExpanded = true;
mTouchDelegateGroup.setEnabled(true);
mCollapseAnimation.cancel();
mExpandAnimation.start();
if (mListener != null) {
mListener.onMenuExpanded();
}
}
}
public void collapse() {
collapse(false);
//collapse(true);//立刻收起(瞬间)
}
private void collapse(boolean immediately) {
if (mExpanded) {
mExpanded = false;
mTouchDelegateGroup.setEnabled(false);
mCollapseAnimation.setDuration(immediately ? 0 : ANIMATION_DURATION);
mCollapseAnimation.start();
mExpandAnimation.cancel();
if (mListener != null) {
mListener.onMenuCollapsed();
}
}
}
/**
* 测量
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
measureChildren(widthMeasureSpec, heightMeasureSpec);
int width = 0;
int height = 0;
mMaxHeight = 0;
mMaxnWidth = 0;
for (int i = 0; i < mChildCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
switch (mExpandDirection) {
case EXP