闲时整理(2)------FloatActionButton

这个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,别人的代码我们拿来使用也容易,没事闲了学学人家里边是怎么实现的。

点击下载所有demo

284568173 欢迎加入讨论群

时间: 2024-10-10 22:56:14

闲时整理(2)------FloatActionButton的相关文章

闲时整理(5)--圆形标签

结合闲时整理(3)------消息提示标签 BadgeView和闲时整理(4)--圆形TextView修改整理了CircleBadgeView这个类,标签是圆形的了,以前的标签是圆角矩形. package com.glory.room.view; import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.

闲时整理(1)------SnackBar

展示的效果就这样简单就看你是有那个需求了.SnackBar的创建过程使用了Builder设计模式,有不同需求的可以更具需求结合代码创建出需要的效果. public class MainActivity extends Activity { private SnackBar mSnackBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); set

vos忙时闲时费率不一样怎么设置

问题: 现有一客户要求上午闲时由原来的9:00追加到9:30 即: 9:30--12:00为忙时 14:00--18:00为忙时 其他为闲时 忙时费率为0.04元即4分 闲时费率为0.025元即2分5 具体案例:

闲时学习要有一个的大方向

否则一闲下来,就像个没头的苍蝇一样 应该明确一个大的方向,要有一个记录 现如今我比较熟悉微软体系的开发,C#,VB,原来的Delphi,等,C++,C也,android都有涉猎,但这些都不精 目前最熟悉的C# 下一步的大目标确立: 逐渐向开源的框架以及python,以及web开发迁移, 当然未来兼顾暂时的工作内容:需要解决几个方面的问题: 1.数据库要用开源的免费的数据库MySql 2.操作系统逐渐要向linux迁移 3.Python制作后台代码,局域网通讯通过zeromq,或者http协议,

[闲时收藏急时用,急时要找难得碰] RedHat下如何刷新磁盘

------老朱  2015.3.5 在新加硬盘或磁盘离线要恢复时,通常要执行刷新,不然你只有重启服务器 命令如下: echo"1" > /sys/class/fc_host/hostx/issue_lip 上面的x用相应的数字替换,要知道数字如何,请进入/sys/class/fc_host目录,ls显示.有几个x值,执行几次(hostx代表HBA卡)上面 这个命令会产生一个LIP操作(Loop Initialization Protocol)实现刷新.

闲时杂谈之docker安装

虚拟化技术相信现在已经不是很陌生了,更被大众所熟知的应该是"云"这个词,但是并不是一说起云就是openstack,这是我所遇到很多客户的误区,而这误区也经常被厂商所利用去忽悠客户.在之前所做的Red Hat 的RHEV产品(现叫RHV)和VMware vSphere产品项目,从客户领导嘴里说出来全是高大上的云什么什么,然后汇报的连我都觉得"卧槽,这个项目名称听起来好唬人".而真正做的openstack的项目只有一个而已,而且客户抱着利旧的目的,当时我的内心是拒绝的,

闲时训练一

最近觉得数论挺有意思,想多了解一下数论了,然后Dp能力依然很弱,保持一下Dp的做题 而且为了提高思维的能力,一周在没其它额外的比赛情况下,最起码补两场CF 还有就是最近回去看 1->hash&&字符串hash 2->网络流的基础题 3->掌握数论的基本公式和定理

闲时训练二

临近期末考,没什么时间做题了.最近玩了一下数位dp的记忆化写法,感觉就是一种套路了,还有最需要反省的就是bc和cf每次都是做完前面的2个或3个水题就不想做了, 都是等到比赛完补题后才觉得不应该没做出来! 1->后缀数组的各种经典题 2->上次的网络流基础根本就没去弄懂,囧 3->往前补codeforces

闲时杂谈之系统安装

自工作一以来一直与Redhat打交道,但作为desktop,我深知它的短板,因为我的个人需求,既可以作为办公桌面又可以在系统中进行一些测验,故经考虑选择了Ubuntu. 版本:(x86_64) 链接:http://releases.ubuntu.com/16.04/ubuntu-16.04-desktop-amd64.iso 因为网上很多帖子已经对系统安装这块写的很详细,故随便从网上搜了一个安装链接,供大家参考,我看了下基本和我安装的步骤一致. 系统安装链接:http://jingyan.bai