可滑动的浮动按钮(FloatingActionButton)

概述

刚最近写了个浮动按钮和大家分享一下,只是在FloatingActionButton基础上做了点扩展,所以滑动范围仅限于父控件范围

使用效果

和正常用FloatingActionButton就可以了,加了个扩展属性scrollEnable,xml使用如下:

<com.zcx.www.scrollfloatingbuttonlib.ScrollFloatinigButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        app:scrollEnable="true"
        app:srcCompat="@android:drawable/ic_dialog_email" />

java代码都是自动生成的,还是贴一下吧

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

先看看效果
效果图

代码实现

主要是处理一下滑动就好了

/**
 * author:  zhouchaoxiang
 * date:    2019/4/25
 * explain:可滑动的floatActionButton
 */
public class ScrollFloatinigButton extends FloatingActionButton {
    private static final String TAG = "ScrollFloatinigButton";
    private float mX;
    private float mY;
    private int mParentWidth;
    private int mParentHeight;
    private boolean mScrollEnable = true;
    private int mScrollLeft;
    private int mScrollTop;
    private int mRight;
    private int mScrollRight;
    private int mScrollBottom;
    private boolean hasScroll;
    boolean isScroll = false;

    public ScrollFloatinigButton(Context context) {
        this(context, null);
    }

    public ScrollFloatinigButton(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ScrollFloatinigButton(Context context, AttributeSet attrs, final int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ScrollFloatinigButton);
        mScrollEnable = ta.getBoolean(R.styleable.ScrollFloatinigButton_scrollEnable, true);
        ta.recycle();
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        //防止布局重置时重置ScrollFloatinigButton的位置
        ViewParent parent = getParent();
        if (parent instanceof ViewGroup) {
            ((ViewGroup) getParent()).addOnLayoutChangeListener(new OnLayoutChangeListener() {
                @Override
                public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                    if (hasScroll && mScrollRight != 0 && mScrollBottom != 0)
                        layout(mScrollLeft, mScrollTop, mScrollRight, mScrollBottom);
                }
            });
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (getParent() instanceof ViewGroup) {
            mParentWidth = ((ViewGroup) getParent()).getWidth();
            mParentHeight = ((ViewGroup) getParent()).getHeight();
        }
        Log.i(TAG, "onSizeChanged: ");
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (!mScrollEnable) return super.onTouchEvent(ev);
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mX = ev.getX();
                mY = ev.getY();
                super.onTouchEvent(ev);
                return true;
            case MotionEvent.ACTION_MOVE:
                int scaledTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
                float x = ev.getX();
                float y = ev.getY();
                x = x - mX;
                y = y - mY;
                if (Math.abs(scaledTouchSlop) < Math.abs(x) || Math.abs(scaledTouchSlop) < Math.abs(y)) {
                    isScroll = true;
                }
                if (isScroll) {
                    mScrollLeft = (int) (getX() + x);
                    mScrollTop = (int) (getY() + y);
                    mScrollRight = (int) (getX() + getWidth() + x);
                    mScrollBottom = (int) (getY() + getHeight() + y);
                    //防止滑出父界面
                    if (mScrollLeft < 0 || mScrollRight > mParentWidth) {
                        mScrollLeft = (int) getX();
                        mScrollRight = (int) getX() + getWidth();
                    }
                    if (mScrollTop < 0 || mScrollBottom > mParentHeight) {
                        mScrollTop = (int) getY();
                        mScrollBottom = (int) getY() + getHeight();
                    }
                    layout(mScrollLeft, mScrollTop, mScrollRight, mScrollBottom);
                    hasScroll = true;
                    return true;
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if (isScroll) {
                    isScroll = false;
                    setPressed(false);//重置点击状态
                    return true;
                }
                break;
        }
        return super.onTouchEvent(ev);
    }

    public void setScrollEnable(boolean scrollEnable) {
        mScrollEnable = scrollEnable;
    }

    public boolean isScrollEnable() {
        return mScrollEnable;
    }
}

在values目录下创建attrs.xml文件,添加如下属性

<resources>
    <declare-styleable name="ScrollFloatinigButton">
        <attr name="scrollEnable" format="boolean" />
    </declare-styleable>
</resources>

大功告成.

总结

这里就总结一下滑动了几种方式吧.

  1. scrollTo和scrollBy
    可滑动view里面的内容,scrollTo为绝对坐标,scrollBy为相对于view的当前坐标
  2. LayoutParams
    可滑动view本身,范围限view的父控件范围,这种方式通过设置LayoutParams的margin值达到移动view的效果,可滑动view本身.
  3. view.layout()和offsetLeftAndRight或offsetTopAndBottom
    可滑动view本身,范围限view的父控件范围,重新设置view的四个顶点坐标来达到滑动view的效果
  4. 属性动画
    可滑动view到任意位置,具体如下
    view.setTranslationX();
    view.setTranslationY();
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值