android拖动控件 父布局刷新 返回原点问题解决

原理:

         在大部分情况下都会出现父容器重绘,当视图位置发生改变时,需要相应更新其相对于父布局的当前所在位置,否则父布局重绘时,由于没有在父布局中更新视图位置,导致重绘的时候视图会回到初始位置,所以在拖动视图控件位置的同时,还需设置其layoutparams参数。

 

代码:

 

核心代码:

//拖动完毕,更新view在父布局中的位置参数,避免刷新父布局view又回到原点
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)getLayoutParams();
                params.setMargins(mLeft,mTop,0,0);

//这里指定下宽高,否则如果布局文件指定了match_parent/wrap_content,会导致自动伸缩宽高
params.width = getMeasuredWidth();
params.height = getMeasuredHeight();

setLayoutParams(params);

 

自定义控件示例:

/**
 * 可拖拽LinearLayout
 */
public class DragLinearLayout extends LinearLayout {

    /*
    private boolean
            onlyX,//仅X轴可移动
            onlyY;//仅Y轴可移动*/
    private int
            lastX,lastY,//记录上一次的x,y坐标
            mLeft,mTop,mRight,mBottom,//记录当前元素的的上下左右(相对于父元素)
            startX,startY,//记录初始x,y坐标
            endX,endY;//移动结束x,y坐标,用于计算是否点击事件

    //用于点击事件触发
    public interface OnClickListener
    {
        void onClick(View view);
    }

    OnClickListener clickListener = null;

    public DragLinearLayout(Context context) {
        super(context);
    }

    public void setOnClickListener(OnClickListener listener)
    {
        clickListener = listener;
    }

    public DragLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);

        /*
        //获取属性值
        TypedArray type = context.obtainStyledAttributes(attrs, R.styleable.DragLinearLayout);

        onlyX = type.getBoolean(R.styleable.DragLinearLayout_onlyX,false);
        onlyY = type.getBoolean(R.styleable.DragLinearLayout_onlyY,false);

        type.recycle();*/
    }

    public DragLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int action = event.getAction();
        int rawX = (int)event.getRawX();
        int rawY = (int)event.getRawY();

        switch (action)
        {
            case MotionEvent.ACTION_DOWN://按下记录初始坐标
                startX = lastX = rawX;
                startY = lastY = rawY;
                break;
            case MotionEvent.ACTION_MOVE:

                //计算偏移量
                int dx = rawX - lastX;
                int dy = rawY - lastY;

                /*
                //限制只能x轴方向拖动
                if (onlyX)
                {
                    dy = 0;

                //限制只能y轴方向拖动
                }else if (onlyY)
                {
                    dx = 0;
                }*/

                //计算控件坐标距离父控件原点各方向距离
                mLeft = getLeft() + dx;
                mRight = getRight() + dx;
                mTop = getTop() + dy;
                mBottom = getBottom() + dy;

                layout(mLeft,mTop,mRight,mBottom);

                //拖动时背景半透明
                //setBackground(getResources().getDrawable(R.drawable.draglinearlayout_press));

                lastX = rawX;
                lastY = rawY;

                break;
            case MotionEvent.ACTION_UP:

                endX = rawX;
                endY = rawY;

                //拖动完毕背景恢复
                //setBackground(getResources().getDrawable(R.drawable.draglinearlayout_up));

                //点击事件
                if (Math.abs(endX - startX) < 3 || Math.abs(endY - startY) < 3) {
                    this.performClick();
                }

                //拖动完毕,更新view在父布局中的位置参数,避免刷新父布局view又回到原点
                LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)getLayoutParams();
                params.setMargins(mLeft,mTop,0,0);

                //这里指定下宽高,否则如果布局文件指定了match_parent/wrap_content,会导致自动伸缩宽高
                params.width = getMeasuredWidth();
                params.height = getMeasuredHeight();

                setLayoutParams(params);

                break;
        }

        return true;
    }

}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值