天天看點

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;
    }

}