android 悬浮按钮 FloatActionButton

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

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.faizmalkani.floatingactionbutton;  
  2.   
  3. import com.nineoldandroids.animation.ObjectAnimator;  
  4. import com.nineoldandroids.view.ViewHelper;  
  5. import android.annotation.SuppressLint;  
  6. import android.content.Context;  
  7. import android.content.res.TypedArray;  
  8. import android.graphics.Bitmap;  
  9. import android.graphics.Canvas;  
  10. import android.graphics.Color;  
  11. import android.graphics.Paint;  
  12. import android.graphics.Point;  
  13. import android.graphics.Rect;  
  14. import android.graphics.drawable.BitmapDrawable;  
  15. import android.graphics.drawable.Drawable;  
  16. import android.os.Build;  
  17. import android.util.AttributeSet;  
  18. import android.view.Display;  
  19. import android.view.MotionEvent;  
  20. import android.view.View;  
  21. import android.view.WindowManager;  
  22. import android.view.animation.AccelerateDecelerateInterpolator;  
  23. import android.view.animation.Interpolator;  
  24. import android.widget.AbsListView;  
  25.   
  26. //import com.nineoldandroids.animation.ObjectAnimator;  
  27. //import com.nineoldandroids.view.ViewHelper;  
  28.   
  29. public class FloatingActionButton extends View {  
  30.   
  31.     private final Interpolator mInterpolator = new AccelerateDecelerateInterpolator();  
  32.     private final Paint mButtonPaint = new Paint(Paint.ANTI_ALIAS_FLAG);  
  33.     private final Paint mDrawablePaint = new Paint(Paint.ANTI_ALIAS_FLAG);  
  34.     private Bitmap mBitmap;  
  35.     private int mColor;  
  36.     private boolean mHidden = false;  
  37.     private Rect rect;  
  38.     private int mLeftDisplayed = -1;  
  39.     private int mRightDisplayed = -1;  
  40.     private int mTopDisplayed = -1;  
  41.     private int mBottomDisplayed = -1;  
  42.     /** 
  43.      * The FAB button's Y position when it is displayed. 
  44.      */  
  45.     private float mYDisplayed = -1;  
  46.     /** 
  47.      * The FAB button's Y position when it is hidden. 
  48.      */  
  49.     private float mYHidden = -1;  
  50.   
  51.     public FloatingActionButton(Context context) {  
  52.         this(context, null);  
  53.     }  
  54.   
  55.     public FloatingActionButton(Context context, AttributeSet attributeSet) {  
  56.         this(context, attributeSet, 0);  
  57.     }  
  58.   
  59.   
  60.     @SuppressLint("NewApi")  
  61.     public FloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) {  
  62.         super(context, attrs, defStyleAttr);  
  63.   
  64.         TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.FloatingActionButton);  
  65.         mColor = a.getColor(R.styleable.FloatingActionButton_color, Color.WHITE);  
  66.         mButtonPaint.setStyle(Paint.Style.FILL);  
  67.         mButtonPaint.setColor(mColor);  
  68.         float radius, dx, dy;  
  69.         radius = a.getFloat(R.styleable.FloatingActionButton_shadowRadius, 10.0f);  
  70.         dx = a.getFloat(R.styleable.FloatingActionButton_shadowDx, 0.0f);  
  71.         dy = a.getFloat(R.styleable.FloatingActionButton_shadowDy, 3.5f);  
  72.         int color = a.getInteger(R.styleable.FloatingActionButton_shadowColor, Color.argb(100000));  
  73.         mButtonPaint.setShadowLayer(radius, dx, dy, color);  
  74.   
  75.         Drawable drawable = a.getDrawable(R.styleable.FloatingActionButton_drawable);  
  76.         if (null != drawable) {  
  77.             mBitmap = ((BitmapDrawable) drawable).getBitmap();  
  78.         }  
  79.         setWillNotDraw(false);  
  80.         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)  
  81.             setLayerType(View.LAYER_TYPE_SOFTWARE, null);  
  82.   
  83.         WindowManager mWindowManager = (WindowManager)  
  84.                 context.getSystemService(Context.WINDOW_SERVICE);  
  85.         Display display = mWindowManager.getDefaultDisplay();  
  86.         Point size = new Point();  
  87.         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {  
  88.             display.getSize(size);  
  89.             mYHidden = size.y;  
  90.         } else mYHidden = display.getHeight();  
  91.     }  
  92.   
  93.     public static int darkenColor(int color) {  
  94.         float[] hsv = new float[3];  
  95.         Color.colorToHSV(color, hsv);  
  96.         hsv[2] *= 0.8f;  
  97.         return Color.HSVToColor(hsv);  
  98.     }  
  99.   
  100.     public void setColor(int color) {  
  101.         mColor = color;  
  102.         mButtonPaint.setColor(mColor);  
  103.         invalidate();  
  104.     }  
  105.   
  106.     public void setDrawable(Drawable drawable) {  
  107.         mBitmap = ((BitmapDrawable) drawable).getBitmap();  
  108.         invalidate();  
  109.     }  
  110.   
  111.     public void setShadow(float radius, float dx, float dy, int color) {  
  112.         mButtonPaint.setShadowLayer(radius, dx, dy, color);  
  113.         invalidate();  
  114.     }  
  115.   
  116.     @Override  
  117.     protected void onDraw(Canvas canvas) {  
  118.         canvas.drawCircle(getWidth() / 2, getHeight() / 2, (float) (getWidth() / 2.6), mButtonPaint);  
  119.         if (null != mBitmap) {  
  120.             canvas.drawBitmap(mBitmap, (getWidth() - mBitmap.getWidth()) / 2,  
  121.                     (getHeight() - mBitmap.getHeight()) / 2, mDrawablePaint);  
  122.         }  
  123.     }  
  124.   
  125.     @Override  
  126.     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {  
  127.         // Perform the default behavior  
  128.         super.onLayout(changed, left, top, right, bottom);  
  129.         if (mLeftDisplayed == -1) {  
  130.             mLeftDisplayed = left;  
  131.             mRightDisplayed = right;  
  132.             mTopDisplayed = top;  
  133.             mBottomDisplayed = bottom;  
  134.         }  
  135.   
  136.         // Store the FAB button's displayed Y position if we are not already aware of it  
  137.         if (mYDisplayed == -1) {  
  138.             mYDisplayed = ViewHelper.getY(this);  
  139.         }  
  140.     }  
  141.   
  142.     @Override  
  143.     public boolean onTouchEvent(MotionEvent event) {  
  144.         int color;  
  145.         if (event.getAction() == MotionEvent.ACTION_UP) {  
  146.             color = mColor;  
  147.         } else {  
  148.             color = darkenColor(mColor);  
  149.             rect = new Rect(mLeftDisplayed, mTopDisplayed, mRightDisplayed, mBottomDisplayed);  
  150.         }  
  151.         if (event.getAction() == MotionEvent.ACTION_MOVE){  
  152.             if (!rect.contains(mLeftDisplayed + (int) event.getX(), mTopDisplayed + (int) event.getY())){  
  153.                 color = mColor;  
  154.             }  
  155.         }  
  156.         mButtonPaint.setColor(color);  
  157.         invalidate();  
  158.         return super.onTouchEvent(event);  
  159.     }  
  160.   
  161.     public void hide(boolean hide) {  
  162.         // If the hidden state is being updated  
  163.         if (mHidden != hide) {  
  164.   
  165.             // Store the new hidden state  
  166.             mHidden = hide;  
  167.   
  168.             // Animate the FAB to it's new Y position  
  169.             ObjectAnimator animator = ObjectAnimator.ofFloat(this"y", mHidden ? mYHidden : mYDisplayed).setDuration(500);  
  170.             animator.setInterpolator(mInterpolator);  
  171.             animator.start();  
  172.         }  
  173.     }  
  174.   
  175.     public void listenTo(AbsListView listView) {  
  176.         if (null != listView) {  
  177.             listView.setOnScrollListener(new DirectionScrollListener(this));  
  178.         }  
  179.     }  
  180. }  

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.faizmalkani.floatingactionbutton;  
  2.   
  3. import android.view.View;  
  4. import android.widget.AbsListView;  
  5.   
  6. class DirectionScrollListener implements AbsListView.OnScrollListener {  
  7.   
  8.     private static final int DIRECTION_CHANGE_THRESHOLD = 1;  
  9.     private final FloatingActionButton mFloatingActionButton;  
  10.     private int mPrevPosition;  
  11.     private int mPrevTop;  
  12.     private boolean mUpdated;  
  13.   
  14.     DirectionScrollListener(FloatingActionButton floatingActionButton) {  
  15.         mFloatingActionButton = floatingActionButton;  
  16.     }  
  17.   
  18.     @Override  
  19.     public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {  
  20.         final View topChild = view.getChildAt(0);  
  21.         int firstViewTop = 0;  
  22.         if (topChild != null) {  
  23.             firstViewTop = topChild.getTop();  
  24.         }  
  25.         boolean goingDown;  
  26.         boolean changed = true;  
  27.         if (mPrevPosition == firstVisibleItem) {  
  28.             final int topDelta = mPrevTop - firstViewTop;  
  29.             goingDown = firstViewTop < mPrevTop;  
  30.             changed = Math.abs(topDelta) > DIRECTION_CHANGE_THRESHOLD;  
  31.         } else {  
  32.             goingDown = firstVisibleItem > mPrevPosition;  
  33.         }  
  34.         if (changed && mUpdated) {  
  35.             mFloatingActionButton.hide(goingDown);  
  36.         }  
  37.         mPrevPosition = firstVisibleItem;  
  38.         mPrevTop = firstViewTop;  
  39.         mUpdated = true;  
  40.     }  
  41.   
  42.     @Override  
  43.     public void onScrollStateChanged(AbsListView view, int scrollState) {  
  44.     }  
  45. }  
button的实现类就这么两个类,但是里边也依赖了大牛写的动画类NineOldAndroids,别人的代码我们拿来使用也容易,没事闲了学学人家里边是怎么实现的。

点击下载所有demo        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值