最開始看到FloatView就想,爲啥使用float.。原來Float 有浮動,漂浮的意思- -。
一、FloatView的功能
二、主要代碼詳解
1. FloatingActionsMenu
(1) 樣式設計
<declare-styleable name="FloatingActionsMenu">
<attr name="fab_addButtonColorPressed" format="color"/>
<attr name="fab_addButtonColorNormal" format="color"/>
<attr name="fab_addButtonSize" format="enum"> // 調節第一個botton的大小
<enum name="normal" value="0"/>
<enum name="mini" value="1"/>
<enum name="large" value="2"/>
</attr>
<attr name="fab_addButtonPlusIconColor" format="color"/>
<attr name="fab_addButtonStrokeVisible" format="boolean"/>
<attr name="fab_labelStyle" format="reference"/>
<attr name="fab_labelsPosition" format="enum"> //文字描述的方向
<enum name="left" value="0"/>
<enum name="right" value="1"/>
</attr>
<attr name="fab_expandDirection" format="enum"> //展示圖標的方向
<enum name="up" value="0"/>
<enum name="down" value="1"/>
<enum name="left" value="2"/>
<enum name="right" value="3"/>
</attr>
</declare-styleable>
(2) 初始化
//初始化屬性值
private void init(Context context, AttributeSet attributeSet) {
mButtonSpacing = (int) (getResources().getDimension(R.dimen.fab_actions_spacing) - getResources().getDimension(R.dimen.fab_shadow_radius) - getResources().getDimension(R.dimen.fab_shadow_offset));
mLabelsMargin = getResources().getDimensionPixelSize(R.dimen.fab_labels_margin);
mLabelsVerticalOffset = getResources().getDimensionPixelSize(R.dimen.fab_shadow_offset);
mTouchDelegateGroup = new TouchDelegateGroup(this);
setTouchDelegate(mTouchDelegateGroup);
TypedArray attr = context.obtainStyledAttributes(attributeSet, R.styleable.FloatingActionsMenu, 0, 0);
mAddButtonPlusColor = attr.getColor(R.styleable.FloatingActionsMenu_fab_addButtonPlusIconColor, getColor(android.R.color.white));
mAddButtonColorNormal = attr.getColor(R.styleable.FloatingActionsMenu_fab_addButtonColorNormal, getColor(R.color.float_menu_default_color));
mAddButtonColorPressed = attr.getColor(R.styleable.FloatingActionsMenu_fab_addButtonColorPressed, getColor(R.color.float_menu_default_pressed_color));
mAddButtonSize = attr.getInt(R.styleable.FloatingActionsMenu_fab_addButtonSize, FloatingActionButton.SIZE_NORMAL);
mAddButtonStrokeVisible = attr.getBoolean(R.styleable.FloatingActionsMenu_fab_addButtonStrokeVisible, true);
mExpandDirection = attr.getInt(R.styleable.FloatingActionsMenu_fab_expandDirection, EXPAND_UP);
mLabelsStyle = attr.getResourceId(R.styleable.FloatingActionsMenu_fab_labelStyle, 0);
mLabelsPosition = attr.getInt(R.styleable.FloatingActionsMenu_fab_labelsPosition, LABELS_ON_LEFT_SIDE);
attr.recycle();
// if (mLabelsStyle != 0 && expandsHorizontally()) {
// throw new IllegalStateException("Action labels in horizontal expand orientation is not supported.");
// }
//創建一個空ImageView,並且給他一個點擊事件,用力展示,隱藏child
createAddButton(context);
}
//創建一個空ImageView,並且給他一個點擊事件,用力展示,隱藏child
private void createAddButton(Context context) {
mAddButton = new FloatingActionButton(context) {
@Override
void updateBackground() {
mColorNormal = mAddButtonColorNormal;
mColorPressed = mAddButtonColorPressed;
super.updateBackground();
}
};
mAddButton.setId(R.id.fab_expand_menu_button); //設置id
Drawable d = getResources().getDrawable(R.drawable.ic_arrow_white); //設置icon資源
mAddButton.setIconDrawable(d);
mAddButton.setSize(mAddButtonSize); //設置button的大小
mAddButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
toggle(); //打開,關閉菜單
}
});
addView(mAddButton, super.generateDefaultLayoutParams());
mButtonsCount++;
}
(3)onMeasure
//計算自身view的大小
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
measureChildren(widthMeasureSpec, heightMeasureSpec);
int width = 0;
int height = 0;
mMaxButtonWidth = 0;
mMaxButtonHeight = 0;
int maxLabelWidth = 0;
for (int i = 0; i < mButtonsCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() == GONE) { //如果內部view有隱藏的,直接return,不參加計算
continue;
}
switch (mExpandDirection) {
case EXPAND_UP:
case EXPAND_DOWN:
mMaxButtonWidth = Math.max(mMaxButtonWidth, child.getMeasuredWidth()); //計算寬度
height += child.getMeasuredHeight(); //計算高度
break;
case EXPAND_LEFT:
case EXPAND_RIGHT:
width += child.getMeasuredWidth();
mMaxButtonHeight = Math.max(mMaxButtonHeight, child.getMeasuredHeight());
break;
}
if (!expandsHorizontally()) {
TextView label = (TextView) child.getTag(R.id.fab_label);
if (label != null) {
maxLabelWidth = Math.max(maxLabelWidth, label.getMeasuredWidth());
}
}
}
if (!expandsHorizontally()) {
width = mMaxButtonWidth + (maxLabelWidth > 0 ? maxLabelWidth + mLabelsMargin : 0);
} else {
height = mMaxButtonHeight;
}
switch (mExpandDirection) { //將間隔添加上去
case EXPAND_UP:
case EXPAND_DOWN:
height += mButtonSpacing * (mButtonsCount - 1);
height = adjustForOvershoot(height);
break;
case EXPAND_LEFT:
case EXPAND_RIGHT:
width += mButtonSpacing * (mButtonsCount - 1);
width = adjustForOvershoot(width);
break;
}
setMeasuredDimension(width, height); //設置view的大小
}
(4) onLayout
case EXPAND_RIGHT:
boolean expandLeft = mExpandDirection == EXPAND_LEFT;
int addButtonX = expandLeft ? r - l - mAddButton.getMeasuredWidth() : 0;
// Ensure mAddButton is centered on the line where the buttons should be
int addButtonTop = b - t - mMaxButtonHeight + (mMaxButtonHeight - mAddButton.getMeasuredHeight()) / 2; //第一個button的位置
mAddButton.layout(addButtonX, addButtonTop, addButtonX + mAddButton.getMeasuredWidth(), addButtonTop + mAddButton.getMeasuredHeight());
int nextX = expandLeft ?
addButtonX - mButtonSpacing :
addButtonX + mAddButton.getMeasuredWidth() + mButtonSpacing;
//根據getChildAt 來確定child位置
for (int i = mButtonsCount - 1; i >= 0; i--) {
final View child = getChildAt(i);
if (child == mAddButton || child.getVisibility() == GONE) continue;
int childX = expandLeft ? nextX - child.getMeasuredWidth() : nextX;
int childY = addButtonTop + (mAddButton.getMeasuredHeight() - child.getMeasuredHeight()) / 2;
child.layout(childX, childY, childX + child.getMeasuredWidth(), childY + child.getMeasuredHeight());//通過第一個button的位置以及自身的大小確定位置
float collapsedTranslation = addButtonX - childX;
float expandedTranslation = 0f;
child.setTranslationX(mExpanded ? expandedTranslation : collapsedTranslation);
child.setAlpha(mExpanded ? 1f : 0f);
LayoutParams params = (LayoutParams) child.getLayoutParams();
params.mCollapseDir.setFloatValues(expandedTranslation, collapsedTranslation);
params.mExpandDir.setFloatValues(collapsedTranslation, expandedTranslation);
params.setAnimationsTarget(child);
View label = (View) child.getTag(R.id.fab_label);
if(label != null) {
label.setVisibility(GONE);
}
nextX = expandLeft ?
childX - mButtonSpacing :
childX + child.getMeasuredWidth() + mButtonSpacing;
}
break;
}
(5) 展開與閉合的操作
private void collapse(boolean immediately) {
if (mExpanded) {
mExpanded = false;
mTouchDelegateGroup.setEnabled(false);
mCollapseAnimation.setDuration(immediately ? 0 : ANIMATION_DURATION);
mCollapseAnimation.start(); //animation的改動
mExpandAnimation.cancel();
Drawable d = getResources().getDrawable(R.drawable.ic_arrow_white);
mAddButton.setIconDrawable(d); //改變第一個button的樣式
setAddButtonColor(getResources().getColor(R.color.float_menu_default_color), getResources().getColor(R.color.float_menu_default_pressed_color));
mAddButton.updateBackground();
if (mListener != null) {
mListener.onMenuCollapsed();
}
}
}
public void toggle() {
if (mExpanded) {
collapse();
} else {
expand();
}
}
//展示 並且改變第一個view的樣式
public void expand() {
if (!mExpanded) {
mExpanded = true;
mTouchDelegateGroup.setEnabled(true);
mCollapseAnimation.cancel();
mExpandAnimation.start();
Drawable d = getResources().getDrawable(R.drawable.ic_close_black);
mAddButton.setIconDrawable(d); //改變第一個button的樣式
setAddButtonColor(getResources().getColor(R.color.white), getResources().getColor(R.color.float_menu_exposed_pressed_color));
mAddButton.updateBackground();
if (mListener != null) {
mListener.onMenuExpanded();
}
}
}