根据开始拖动和结束拖动之间的距离调整视图的大小

时间:2018-06-29 16:26:03

标签: android drag

我正在一个有一个视图的项目中工作,单击该视图后,实例化一个类,将视图传递给构造函数,该构造函数在视图上创建4个锚点。这可以通过以下操作完成:

customView = new CustomView(MainActivity.this, viewCounter, 
        customView.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                Resizer resizer = new Resizer(MainActivity.this, MainActivity.this, container, customView, lblStatus);
            }
        });

大小调整器类如下:

public Resizer(Context context, AppCompatActivity activity, ViewGroup container, ViewGroup viewToBeResized, TextView lblStatus)
    {
        this.context = context;
        this.activity = activity;
        this.container = container;
        this.viewToBeResized = viewToBeResized;
        this.lblStatus = lblStatus;
        createAnchorPoints();
    }

    private void createAnchorPoints()
    {
        Drawable circle = ContextCompat.getDrawable(context, R.drawable.anchor);
        int circleSize = dpToPx(CIRCLE_SIZE_DP);

        Anchor topLeftAnchor = new Anchor(context, viewToBeResized, Anchor.ResizeMode.TOP_LEFT, lblStatus);
        topLeftAnchor.setImageDrawable(circle);
        RelativeLayout.LayoutParams topLeftParms = new RelativeLayout.LayoutParams(circleSize, circleSize);
        topLeftParms.addRule(RelativeLayout.ALIGN_PARENT_START, viewToBeResized.getId());
        topLeftParms.addRule(RelativeLayout.ALIGN_PARENT_TOP, viewToBeResized.getId());
        viewToBeResized.addView(topLeftAnchor, topLeftParms);

        Anchor topRightAnchor = new Anchor(context, viewToBeResized, Anchor.ResizeMode.TOP_RIGHT, lblStatus);
        topRightAnchor.setImageDrawable(circle);
        RelativeLayout.LayoutParams topRightParms = new RelativeLayout.LayoutParams(circleSize, circleSize);
        topRightParms.addRule(RelativeLayout.ALIGN_PARENT_END, viewToBeResized.getId());
        topRightParms.addRule(RelativeLayout.ALIGN_PARENT_TOP, viewToBeResized.getId());
        viewToBeResized.addView(topRightAnchor, topRightParms);

        Anchor bottomLeftAnchor = new Anchor(context, viewToBeResized, Anchor.ResizeMode.BOTTOM_RIGHT, lblStatus);
        bottomLeftAnchor.setImageDrawable(circle);
        RelativeLayout.LayoutParams bottomLeftParms = new RelativeLayout.LayoutParams(circleSize, circleSize);
        bottomLeftParms.addRule(RelativeLayout.ALIGN_PARENT_START, viewToBeResized.getId());
        bottomLeftParms.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, viewToBeResized.getId());
        viewToBeResized.addView(bottomLeftAnchor, bottomLeftParms);

        Anchor bottomRightAnchor = new Anchor(context, viewToBeResized, Anchor.ResizeMode.BOTTOM_RIGHT, lblStatus);
        bottomRightAnchor.setImageDrawable(circle);
        RelativeLayout.LayoutParams bottomRightParms = new RelativeLayout.LayoutParams(circleSize, circleSize);
        bottomRightParms.addRule(RelativeLayout.ALIGN_PARENT_END, viewToBeResized.getId());
        bottomRightParms.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, viewToBeResized.getId());
        viewToBeResized.addView(bottomRightAnchor, bottomRightParms);

    }

在每个角创建的锚点类中,使用触摸侦听器。我想要做的是随着用户拖动锚视图,传递到锚中的主视图将按照用户拖动的方向调整大小。

下面是我的触摸监听器

     public class AnchorTouchListener implements View.OnTouchListener
{
    private int _xDelta;
    private int _yDelta;
    private View viewToResize;
    private TextView lblStatus;
    private Anchor.ResizeMode resizeMode;

    public AnchorTouchListener(View viewToResize, TextView lblStatus, Anchor.ResizeMode resizeMode)
    {
        this.viewToResize = viewToResize;
        this.lblStatus = lblStatus;
        this.resizeMode = resizeMode;
    }

    @Override
    public boolean onTouch(View view, MotionEvent event)
    {
        final int X = (int) event.getRawX();
        final int Y = (int) event.getRawY();

        Log.d("Anchor", "Updating X & Y");

        int diff = 0;

        switch (event.getAction() & MotionEvent.ACTION_MASK)
        {
            case MotionEvent.ACTION_DOWN:
                lblStatus.setText("Moving down");
                RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
                _xDelta = X - lParams.leftMargin;
                _yDelta = Y - lParams.topMargin;
                break;
            case MotionEvent.ACTION_UP:
                lblStatus.setText("Drag finished");


                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                break;
            case MotionEvent.ACTION_POINTER_UP:

                break;
            case MotionEvent.ACTION_MOVE:
                lblStatus.setText("Moving around");
                RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
                layoutParams.leftMargin = X - _xDelta;
                layoutParams.topMargin = Y - _yDelta;
                layoutParams.rightMargin = _xDelta - X;
                layoutParams.bottomMargin = _yDelta - Y;
                view.setLayoutParams(layoutParams);

                //viewToResize.animate().scaleX(0.6f);

                if (resizeMode == Anchor.ResizeMode.BOTTOM_RIGHT)
                {
                    diff = diff - X - _xDelta;
                    Log.d("Anchor Touch", "Diff: " + diff);
                    if (diff > 0)
                    {
                        ((RelativeLayout.LayoutParams) viewToResize.getLayoutParams()).width = viewToResize.getLayoutParams().width + Math.abs(diff);
                    }
                    else
                    {
                        ((RelativeLayout.LayoutParams)viewToResize.getLayoutParams()).width = viewToResize.getLayoutParams().width - Math.abs(diff);
                    }
                }
                break;
        }
        return true;
    }
}

这是一种工作,除了它不能与锚点平滑移动外,调整视图的大小似乎比拖动视图更快,并且调整大小和缩小的方法也很不稳定。

是否有更好的方法来完成我要实现的目标,或者有人可以看到我可能在做错的事情。

更新

添加了视频,以显示我要实现的目标以及问题所在。 Video showing issue

2 个答案:

答案 0 :(得分:2)

由于锚点以RelativeLayout定位,因此无需编写代码来移动锚点。只需调整灰色框的大小,即可在布局时正确定位锚点。灰色框的大小可以通过捕获指针放置的初始条件和框的初始大小来确定,以实现以下目的。

enter image description here

我只实现了右下角的锚,并且对您的实现采取了一些自由,但是该概念对于您的代码和其他锚点仍然有效。

AnchorTouchListener.java

public class AnchorTouchListener implements View.OnTouchListener {
    private int _xDelta;
    private int _yDelta;
    private View viewToResize;
    private TextView lblStatus;
//    private Anchor.ResizeMode resizeMode;

    public AnchorTouchListener(View viewToResize, TextView lblStatus/*, Anchor.ResizeMode resizeMode*/) {
        this.viewToResize = viewToResize;
        this.lblStatus = lblStatus;
        //  this.resizeMode = resizeMode;
    }

    private int initialHeight;
    private int initialWidth;
    private int initialX;
    private int initialY;

    @Override
    public boolean onTouch(View view, MotionEvent event) {
        final int X = (int) event.getRawX();
        final int Y = (int) event.getRawY();

        Log.d("Anchor", "Updating X & Y");

        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                lblStatus.setText("Action down");
                // Capture initial conditions of the view to resize.
                initialHeight = viewToResize.getHeight();
                initialWidth = viewToResize.getWidth();
                // Capture initial touch point.
                initialX = X;
                initialY = Y;
                break;

            case MotionEvent.ACTION_UP:
                lblStatus.setText("Drag finished");
                break;

            case MotionEvent.ACTION_POINTER_DOWN:
                break;

            case MotionEvent.ACTION_POINTER_UP:
                break;

            case MotionEvent.ACTION_MOVE:
                lblStatus.setText("Moving around");
                RelativeLayout.LayoutParams lp =
                    (RelativeLayout.LayoutParams) viewToResize.getLayoutParams();
                // Compute how far we have moved in the X/Y directions.
                _xDelta = X - initialX;
                _yDelta = Y - initialY;
                // Adjust the size of the targeted view. Note that we don't have to position
                // the resize handle since it will be positioned correctly due to the layout.
                lp.width = initialWidth + _xDelta;
                lp.height = initialHeight + _yDelta;
                viewToResize.setLayoutParams(lp);
                break;
        }
        return true;
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Drawable circle = ContextCompat.getDrawable(this, R.drawable.circle);
        ImageView imageView = new ImageView(this);
        imageView.setImageDrawable(circle);
        int circleSize = dpToPx(CIRCLE_SIZE_DP);

        RelativeLayout viewToBeResized = findViewById(R.id.customView);

        ImageView bottomRightAnchor = new ImageView(this);
        bottomRightAnchor.setImageDrawable(circle);
        RelativeLayout.LayoutParams bottomRightParms =
            new RelativeLayout.LayoutParams(circleSize, circleSize);
        bottomRightParms.addRule(RelativeLayout.ALIGN_PARENT_END, viewToBeResized.getId());
        bottomRightParms.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, viewToBeResized.getId());
        viewToBeResized.addView(bottomRightAnchor, bottomRightParms);

        bottomRightAnchor.setOnTouchListener(
            new AnchorTouchListener(viewToBeResized, ((TextView) findViewById(R.id.status))));
    }

    private int dpToPx(int dp) {
        return (int) (dp * getResources().getDisplayMetrics().density);
    }

    private static final int CIRCLE_SIZE_DP = 20;
}

activity_main.xml

<RelativeLayout 
    android:id="@+id/relativeLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <RelativeLayout
        android:id="@+id/customView"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:background="@android:color/holo_green_light" />

    <TextView
        android:id="@+id/status"
        android:layout_width="wrap_content"
        tools:text="Status"
        android:layout_height="wrap_content" />

</RelativeLayout>

答案 1 :(得分:0)

RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();

在您的 AnchorTouchListener 类的上面的代码行中,您正在获取先前创建的视图端点的参数。

获取正确的LayourParams应该可以解决问题。