这个button已经在很多应用中都出现了,在android 5.0版本后这样的效果是很容易就能实现的,但对于老版本只能用代码来堆积了。
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)); } } }
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,别人的代码我们拿来使用也容易,没事闲了学学人家里边是怎么实现的。
284568173 欢迎加入讨论群
时间: 2024-10-10 22:56:14