美文网首页
仿ios辅助按钮效果(就是那个一直在桌面的...)

仿ios辅助按钮效果(就是那个一直在桌面的...)

作者: gu_jingli | 来源:发表于2017-06-08 14:13 被阅读0次

    参考https://github.com/Sbingo/FreeRadioGroup
    本文主要是根据自己的需求进行重新定义了一下,并且指出使用时的注意事项
    demo下载链接:http://pan.baidu.com/s/1hrRoLla 密码:iuxi

    效果图

    效果.gif

    使用时根布局使用FramLayout

    布局

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="sbingo.demo.Main2Activity">
    
        <demo.kotlin.freelayout.FreeLayout
            android:id="@+id/group"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:autoBack="true"
            app:iconButton="@mipmap/open_door"
            app:millisInFuture="500"
            app:moveable="true" />
    </FrameLayout>
    

    控件代码

    package demo.kotlin.freelayout;
    
    import android.animation.ObjectAnimator;
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.os.CountDownTimer;
    import android.util.AttributeSet;
    import android.util.DisplayMetrics;
    import android.view.MotionEvent;
    import android.view.ViewGroup;
    import android.widget.ImageButton;
    import android.widget.LinearLayout;
    
    /**
     * Created by gjl on 2017/6/8.
     */
    
    public class FreeLayout extends LinearLayout {
    
        /**
         * 倒计时过程中
         * 回调{@link CountDownTimer#onTick(long)}的间隔时间
         */
        private MyCountDownTimer countDownTimer;
        /**
         * 倒计时时间
         */
        private long millisInFuture;
        private long countDownInterval = 500;
        private boolean moveable, autoBack;
        private float toAlpha,
                startX, startY,
                currentX, currentY;
        private int iconButton,
                currentLeft, currentTop,
                screenWidth, screenHeight,
                parentWidth, parentHeight,
                viewWidth, viewHight,
                minLeftMargin, maxLeftMargin,
                minTopMargin, maxTopMargin,
                bottomDistance, rightDistance,
                leftPadding, topPadding;
    
        public FreeLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context, attrs);
        }
    
        private void init(Context context, AttributeSet attrs) {
            DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
            screenWidth = displayMetrics.widthPixels;
            screenHeight = displayMetrics.heightPixels - getStatusBarHeight();
            TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.free);
            millisInFuture = ta.getInt(R.styleable.free_millisInFuture, 3 * 1000);
            toAlpha = ta.getFloat(R.styleable.free_toAlpha, 0.2f);
            moveable = ta.getBoolean(R.styleable.free_moveable, false);
            autoBack = ta.getBoolean(R.styleable.free_autoBack, false);
            iconButton = ta.getResourceId(R.styleable.free_iconButton, -1);
            ta.recycle();
            //如果作为单一控件使用(没有子控件),手动添加一个子控件,并添加按钮图片
            //注:这里使用ImageButton,如果需要文字,建议使用CheckBox,RadioButton,否则会导致拖动失灵(希望知道原理的大神可以回复指点)
            if (getChildCount() == 0) {
                ImageButton imageButton = new ImageButton(context);
                imageButton.setBackgroundResource(iconButton);
                addView(imageButton);
            }
            countDownTimer = new MyCountDownTimer(millisInFuture, countDownInterval);
            countDownTimer.start();
            //设置默认位置
            post(new Runnable() {
                @Override
                public void run() {
                    MarginLayoutParams layoutParams = (MarginLayoutParams) getLayoutParams();
                    layoutParams.topMargin = screenHeight / 2 - getHeight();
                    layoutParams.leftMargin = screenWidth - getWidth();
                    setLayoutParams(layoutParams);
                }
            });
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            if (moveable) {
                ViewGroup parentView = ((ViewGroup) getParent());
                MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
                viewWidth = getRight() - getLeft();
                viewHight = getBottom() - getTop();
                parentWidth = parentView.getMeasuredWidth();
                parentHeight = parentView.getMeasuredHeight();
                minLeftMargin = lp.leftMargin;
                leftPadding = parentView.getPaddingLeft();
                rightDistance = lp.rightMargin + parentView.getPaddingRight();
                maxLeftMargin = parentWidth - rightDistance - viewWidth - leftPadding;
                minTopMargin = lp.topMargin;
                topPadding = parentView.getPaddingTop();
                bottomDistance = lp.bottomMargin + parentView.getPaddingBottom();
                maxTopMargin = parentHeight - bottomDistance - viewHight - topPadding;
            }
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    startX = ev.getRawX();
                    startY = ev.getRawY();
                    setAlpha(1f);
                    countDownTimer.cancel();
                    if (moveable) {
                        MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
                        currentX = ev.getRawX();
                        currentY = ev.getRawY();
                        currentLeft = lp.leftMargin;
                        currentTop = lp.topMargin;
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (moveable) {
                        currentLeft += ev.getRawX() - currentX;
                        currentTop += ev.getRawY() - currentY;
                        //判断左边界
                        currentLeft = currentLeft < minLeftMargin ? minLeftMargin : currentLeft;
                        //判断右边界
                        currentLeft = (leftPadding + currentLeft + viewWidth + rightDistance) > parentWidth ? maxLeftMargin : currentLeft;
                        //判断上边界
                        currentTop = currentTop < minTopMargin ? minTopMargin : currentTop;
                        //判断下边界
                        currentTop = (topPadding + currentTop + viewHight + bottomDistance) > parentHeight ? maxTopMargin : currentTop;
                        MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
                        lp.leftMargin = currentLeft;
                        lp.topMargin = currentTop;
                        setLayoutParams(lp);
                        currentX = ev.getRawX();
                        currentY = ev.getRawY();
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    float endX = ev.getRawX();
                    float endY = ev.getRawY();
                    countDownTimer.start();
                    if (moveable && autoBack) {
                        MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
                        int fromLeftMargin = lp.leftMargin;
                        if (getLeft() < (parentWidth - getLeft() - viewWidth)) {
                            lp.leftMargin = minLeftMargin;
                        } else {
                            lp.leftMargin = maxLeftMargin;
                        }
                        ObjectAnimator marginChange = ObjectAnimator.ofInt(new Wrapper(this), "leftMargin", fromLeftMargin, lp.leftMargin);
                        marginChange.setDuration(500);
                        marginChange.start();
                    }
                    //滑动距离比较小,当作点击事件处理
                    if (Math.abs(startX - endX) < 1 && Math.abs(startY - endY) < 1 && mLister != null) {
                        mLister.onViewClick();
                    }
                    break;
                default:
            }
            return super.dispatchTouchEvent(ev);
        }
    
        /**
         * 点击事件
         */
    
        private OnViewClickListener mLister;
    
        public interface OnViewClickListener {
            void onViewClick();
        }
    
        public void setOnViewClickListener(OnViewClickListener listener) {
            this.mLister = listener;
        }
    
        /**
         * 包装类
         */
        class Wrapper {
            private ViewGroup mTarget;
    
            public Wrapper(ViewGroup mTarget) {
                this.mTarget = mTarget;
            }
    
            public int getLeftMargin() {
                MarginLayoutParams lp = (MarginLayoutParams) mTarget.getLayoutParams();
                return lp.leftMargin;
            }
    
            public void setLeftMargin(int leftMargin) {
                MarginLayoutParams lp = (MarginLayoutParams) mTarget.getLayoutParams();
                lp.leftMargin = leftMargin;
                mTarget.requestLayout();
            }
        }
    
        public class MyCountDownTimer extends CountDownTimer {
    
            public MyCountDownTimer(long millisInFuture, long countDownInterval) {
                super(millisInFuture, countDownInterval);
            }
    
            @Override
            public void onTick(long millisUntilFinished) {
            }
    
            @Override
            public void onFinish() {
                setAlpha(toAlpha);
            }
        }
    
        /**
         *   * 获取状态栏的高度
         *   * @return 状态栏高度
         *   
         */
        public int getStatusBarHeight() {
            int result = 0;
            int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
            if (resourceId > 0) {
                result = getResources().getDimensionPixelSize(resourceId);
            }
            return result;
        }
    }
    

    相关文章

      网友评论

          本文标题:仿ios辅助按钮效果(就是那个一直在桌面的...)

          本文链接:https://www.haomeiwen.com/subject/twwzfxtx.html