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

如何在片段中的对象中实现onDragListener?

  •  4
  • Sharon  · 技术社区  · 6 年前

    我的应用程序有一个类, MarkedLine View . 这个类的一个实例显示在一个片段中。我希望用户能够做到以下三件事:

    1. 通过做“捏”和“伸”手势来扩大线条
    2. 触摸直线的任何一点并获得其坐标

    我有前两个工作,但不能想出第三个(拖动)。

    每个 标记线

    基本片段布局( fragment_marked_line )如下所示(我删除了不相关的位、填充、边距等):

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout   
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:res="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <packagepath.models.ToolboxButton
            android:id="@+id/toolbarNext"
            android:layout_width="@dimen/toolbar_icon_size"
            android:layout_height="@dimen/toolbar_icon_size"
            android:src="@drawable/next_line"
            res:layout_constraintTop_toTopOf="parent" />
    
        <packagepath.models.MarkedLine
            android:id="@+id/markedLine"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            res:layout_constraintStart_toStartOf="parent"
            res:layout_constraintEnd_toEndOf="parent"
            res:layout_constraintTop_toBottomOf="@+id/toolbarNext" />
    
    </android.support.constraint.ConstraintLayout>
    

    (所以基本上它是一个按钮,下面有一条全宽的线。这个按钮允许用户调出下一行)。

    MarkedLineFragment )如下所示(注意,线集基本上只是一个标记线数组,带有一些额外变量,如创建时的线尺寸等):

    public class MarkedLineFragment extends Fragment {
    
        LineSet       mLineSet
        MarkedLine    mMarkedLine;
        ToolboxButton btn_next;
    
        int     mItemNumber, mMaxItems;
    
        public MarkedLineFragment() {}
    
        @Override
        public View onCreateView(@NonNull LayoutInflater inflater,
                         ViewGroup container, Bundle savedInstanceState) {
            super.onCreateView(inflater, container, savedInstanceState);
    
            View rootView = inflater.inflate(
                    R.layout.fragment_marked_line, container, false);
    
            // Get view objects
            btn_next = rootView.findViewById(R.id.toolbarNext);
            mMarkedLine = rootView.findViewById(R.id.markedLine);
    
            // Initialise the button
            initialise_button();
    
            // If the LineSet has already been set, 
            //  pass it through to the MarkedLine
            if(mLineSet != null) {
                mMarkedLine.setLineSet(mLineSet);
                mMaxItems = mLineSet.getNum_items();
            }
    
            // Initialise at line 1
            mItemNumber = 1;
            mMarkedLine.setCurrentItem(mItemNumber);
    
            // Draw the MarkedLine
            drawLine();
    
            return rootView;
        }
    
        // Initialise the button so that it moves to the next line on clicking
        public void initialise_button() {
    
            btn_next.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(mItemNumber == mMaxItems) return;
                    else mItemNumber += 1;
                    set_new_item_number();
                }
            });
    
        }
    
        private void set_new_item_number() {
            mMarkedLine.setCurrentItem(mItemNumber);
        }
    
        public void drawChart() {
          if(mMarkedLine != null) mMarkedLine.postInvalidate();
        }
    
    }
    

    最后 标记线

    public class MarkedLine extends View {
    
        private LineSet mLineSet;
        private int currentItem;
        private int numBoxes;
        private float canvas_height, canvas_width;
        private float box_size;
        private float minX, maxX, minY, maxY;
    
        // Scaling (pinch & zoom) variables
        private float scaleFactor = 1.0f; // Current scale factor
        private ScaleGestureDetector detectorScale;// Detector for gestures
        private GestureDetector detectorTouch; // Detector for tap gestures
    
        public MarkedLine(Context thisContext, AttributeSet attrs) {
            super(thisContext, attrs);
    
            detectorScale = new ScaleGestureDetector(thisContext, new MarkedLine.ScaleListener());
            detectorTouch = new GestureDetector(thisContext, new MarkedLine.TouchListener());
    
        }
    
        public void setCallback(OnBoxTouched callback) { mCallback = callback; }
    
        public void setLineSet(LineSet lineSet) {
            mLineSet = lineSet;
            numBoxes = mLineSet.getNum_boxes();
            invalidate();
        }
    
        public void setCurrentItem(int newItemNumber) {
            currentItem = newItemNumber;
            invalidate();
        }
    
        protected void onDraw(Canvas canvas) {
    
            if (mLineSet == null) return;
    
            // Set up canvas
            canvas.save();
            canvas.scale(scaleFactor, scaleFactor);
            canvas.translate(translateX / scaleFactor, translateY / scaleFactor);
    
            // draw_boxes reads how many boxes make up the MarkedLine,
            //  calculates what size they need to be to fit on the canvas, 
            //  and then draws them
            draw_boxes();
    
            // fill_in_line adds in the appropriate colours to the 
            //  boxes in the line
            fill_in_line();
    
            canvas.restore();
        }
    
        // GRID EVENT FUNCTIONS - respond to User touching screen
    
        // onTouchEvent
        // User has touched the screen - trigger listeners
        @Override
        public boolean onTouchEvent(MotionEvent event) {
    
            detectorScale.onTouchEvent(event);
            detectorTouch.onTouchEvent(event);
            invalidate();
    
            return true;
    
        }
    
        // LISTENERS
    
        /*
         * Respond to user touching the screen
         */
        private class TouchListener extends GestureDetector.SimpleOnGestureListener {
    
            public boolean onSingleTapUp(MotionEvent event) {
    
                // Determine where the screen was touched
                float xTouch = event.getX();
                float yTouch = event.getY();
    
                // Check that the touch was within the line; return if not
                if(!touch_in_line(xTouch, yTouch)) return false;
    
                // Figure out which Box was tapped
                int xCell = getTouchedBox(xTouch);
    
                // Now the box which was tapped is coloured in
                colour_box(xCell);
    
                return true;
            }
    
        }
    
        /*
         * Determine scale factor for zoom mode
         * This can be called in View and Edit Activities
         */
        private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
    
            @Override
            public boolean onScale(ScaleGestureDetector detector) {
    
                float MIN_ZOOM = 1f;     // Minimum zoom level
                float MAX_ZOOM = 5f;     // Maximum zoom level
    
                scaleFactor *= detector.getScaleFactor();
                scaleFactor = Math.max(MIN_ZOOM, Math.min(scaleFactor, MAX_ZOOM));
                return true;
            }
    
        }
    }
    

    我想我需要为某些内容添加一个onDragListener,但我不知道是什么。我试着用一个onDrag方法创建一个DragListener类,类似于ScaleListener和TouchListener类(我只有两个虚拟行,所以可以附加一个断点)。然后我声明了该类的一个实例(dragListener)。我尝试使用 this.onDragListener(dragListener)

    然后我在片段中尝试了类似的东西,将其附加到onCreateView中的mMarkedLine类,但当我尝试拖动时,它再次没有响应。

    1 回复  |  直到 6 年前
        1
  •  1
  •   AskNilesh    6 年前

    如果它对其他人有帮助,我通过在 onTouchEvent MarkedLine 类别:

    @Override
    public boolean onTouchEvent(MotionEvent event) {
    
        detectorScale.onTouchEvent(event);
        detectorTouch.onTouchEvent(event);
    
        // Check for drag gestures
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                startX = event.getX() - previousTranslateX;
                startY = event.getY() - previousTranslateY;
                break;
            case MotionEvent.ACTION_UP:
                previousTranslateX = translateX;
                previousTranslateY = translateY;
                break;
            case MotionEvent.ACTION_MOVE:
                translateX = event.getX() - startX;
                translateY = event.getY() - startY;
                break;
        }
    
        invalidate();
    
        return true;
    
    }