您的位置:首页 > 移动开发 > Android开发

android 悬浮按钮 FloatActionButton

2015-07-15 13:59 691 查看
这个button已经在很多应用中都出现了,在android 5.0版本后这样的效果是很容易就能实现的,但对于老版本只能用代码来堆积了。


[java] view
plaincopy





package com.faizmalkani.floatingactionbutton;



import com.nineoldandroids.animation.ObjectAnimator;

import com.nineoldandroids.view.ViewHelper;

import android.annotation.SuppressLint;

import android.content.Context;

import android.content.res.TypedArray;

import android.graphics.Bitmap;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.Point;

import android.graphics.Rect;

import android.graphics.drawable.BitmapDrawable;

import android.graphics.drawable.Drawable;

import android.os.Build;

import android.util.AttributeSet;

import android.view.Display;

import android.view.MotionEvent;

import android.view.View;

import android.view.WindowManager;

import android.view.animation.AccelerateDecelerateInterpolator;

import android.view.animation.Interpolator;

import android.widget.AbsListView;



//import com.nineoldandroids.animation.ObjectAnimator;

//import com.nineoldandroids.view.ViewHelper;



public class FloatingActionButton extends View {



private final Interpolator mInterpolator = new AccelerateDecelerateInterpolator();

private final Paint mButtonPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

private final Paint mDrawablePaint = new Paint(Paint.ANTI_ALIAS_FLAG);

private Bitmap mBitmap;

private int mColor;

private boolean mHidden = false;

private Rect rect;

private int mLeftDisplayed = -1;

private int mRightDisplayed = -1;

private int mTopDisplayed = -1;

private int mBottomDisplayed = -1;

/**

* The FAB button's Y position when it is displayed.

*/

private float mYDisplayed = -1;

/**

* The FAB button's Y position when it is hidden.

*/

private float mYHidden = -1;



public FloatingActionButton(Context context) {

this(context, null);

}



public FloatingActionButton(Context context, AttributeSet attributeSet) {

this(context, attributeSet, 0);

}





@SuppressLint("NewApi")

public FloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);



TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.FloatingActionButton);

mColor = a.getColor(R.styleable.FloatingActionButton_color, Color.WHITE);

mButtonPaint.setStyle(Paint.Style.FILL);

mButtonPaint.setColor(mColor);

float radius, dx, dy;

radius = a.getFloat(R.styleable.FloatingActionButton_shadowRadius, 10.0f);

dx = a.getFloat(R.styleable.FloatingActionButton_shadowDx, 0.0f);

dy = a.getFloat(R.styleable.FloatingActionButton_shadowDy, 3.5f);

int color = a.getInteger(R.styleable.FloatingActionButton_shadowColor, Color.argb(100, 0, 0, 0));

mButtonPaint.setShadowLayer(radius, dx, dy, color);



Drawable drawable = a.getDrawable(R.styleable.FloatingActionButton_drawable);

if (null != drawable) {

mBitmap = ((BitmapDrawable) drawable).getBitmap();

}

setWillNotDraw(false);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)

setLayerType(View.LAYER_TYPE_SOFTWARE, null);



WindowManager mWindowManager = (WindowManager)

context.getSystemService(Context.WINDOW_SERVICE);

Display display = mWindowManager.getDefaultDisplay();

Point size = new Point();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {

display.getSize(size);

mYHidden = size.y;

} else mYHidden = display.getHeight();

}



public static int darkenColor(int color) {

float[] hsv = new float[3];

Color.colorToHSV(color, hsv);

hsv[2] *= 0.8f;

return Color.HSVToColor(hsv);

}



public void setColor(int color) {

mColor = color;

mButtonPaint.setColor(mColor);

invalidate();

}



public void setDrawable(Drawable drawable) {

mBitmap = ((BitmapDrawable) drawable).getBitmap();

invalidate();

}



public void setShadow(float radius, float dx, float dy, int color) {

mButtonPaint.setShadowLayer(radius, dx, dy, color);

invalidate();

}



@Override

protected void onDraw(Canvas canvas) {

canvas.drawCircle(getWidth() / 2, getHeight() / 2, (float) (getWidth() / 2.6), mButtonPaint);

if (null != mBitmap) {

canvas.drawBitmap(mBitmap, (getWidth() - mBitmap.getWidth()) / 2,

(getHeight() - mBitmap.getHeight()) / 2, mDrawablePaint);

}

}



@Override

protected void onLayout(boolean changed, int left, int top, int right, int bottom) {

// Perform the default behavior

super.onLayout(changed, left, top, right, bottom);

if (mLeftDisplayed == -1) {

mLeftDisplayed = left;

mRightDisplayed = right;

mTopDisplayed = top;

mBottomDisplayed = bottom;

}



// Store the FAB button's displayed Y position if we are not already aware of it

if (mYDisplayed == -1) {

mYDisplayed = ViewHelper.getY(this);

}

}



@Override

public boolean onTouchEvent(MotionEvent event) {

int color;

if (event.getAction() == MotionEvent.ACTION_UP) {

color = mColor;

} else {

color = darkenColor(mColor);

rect = new Rect(mLeftDisplayed, mTopDisplayed, mRightDisplayed, mBottomDisplayed);

}

if (event.getAction() == MotionEvent.ACTION_MOVE){

if (!rect.contains(mLeftDisplayed + (int) event.getX(), mTopDisplayed + (int) event.getY())){

color = mColor;

}

}

mButtonPaint.setColor(color);

invalidate();

return super.onTouchEvent(event);

}



public void hide(boolean hide) {

// If the hidden state is being updated

if (mHidden != hide) {



// Store the new hidden state

mHidden = hide;



// Animate the FAB to it's new Y position

ObjectAnimator animator = ObjectAnimator.ofFloat(this, "y", mHidden ? mYHidden : mYDisplayed).setDuration(500);

animator.setInterpolator(mInterpolator);

animator.start();

}

}



public void listenTo(AbsListView listView) {

if (null != listView) {

listView.setOnScrollListener(new DirectionScrollListener(this));

}

}

}

[java] view
plaincopy





package com.faizmalkani.floatingactionbutton;



import android.view.View;

import android.widget.AbsListView;



class DirectionScrollListener implements AbsListView.OnScrollListener {



private static final int DIRECTION_CHANGE_THRESHOLD = 1;

private final FloatingActionButton mFloatingActionButton;

private int mPrevPosition;

private int mPrevTop;

private boolean mUpdated;



DirectionScrollListener(FloatingActionButton floatingActionButton) {

mFloatingActionButton = floatingActionButton;

}



@Override

public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

final View topChild = view.getChildAt(0);

int firstViewTop = 0;

if (topChild != null) {

firstViewTop = topChild.getTop();

}

boolean goingDown;

boolean changed = true;

if (mPrevPosition == firstVisibleItem) {

final int topDelta = mPrevTop - firstViewTop;

goingDown = firstViewTop < mPrevTop;

changed = Math.abs(topDelta) > DIRECTION_CHANGE_THRESHOLD;

} else {

goingDown = firstVisibleItem > mPrevPosition;

}

if (changed && mUpdated) {

mFloatingActionButton.hide(goingDown);

}

mPrevPosition = firstVisibleItem;

mPrevTop = firstViewTop;

mUpdated = true;

}



@Override

public void onScrollStateChanged(AbsListView view, int scrollState) {

}

}

button的实现类就这么两个类,但是里边也依赖了大牛写的动画类NineOldAndroids,别人的代码我们拿来使用也容易,没事闲了学学人家里边是怎么实现的。

点击下载所有demo
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: