代码之家  ›  专栏  ›  技术社区  ›  Boardy

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

  •  3
  • Boardy  · 技术社区  · 6 年前

    我正在做一个项目,在那里我有一个视图,点击它,实例化一个类,将视图传递给构造函数,构造函数在视图上创建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);
                }
            });
    

    Resizer类如下:

    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 回复  |  直到 6 年前
        1
  •  2
  •   Cheticamp    6 年前

    因为锚的位置是 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;
        }
    }
    

    main活动.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;
    }
    

    活动\主.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>
    
        2
  •  0
  •   XmenR    6 年前
    RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
    

    在上面的代码行中 主持人 类获取先前创建的视图终结点的参数。

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