在Android中的Horizo​​ntalScrollView中捏变焦无法正常工作

时间:2014-04-14 17:18:29

标签: android android-layout android-listview android-canvas

我在Horizo​​ntalScrollView中安排我的视图,我的每个视图(DrawView.java)都包含矩形。当活动仅包含此视图时,捏拉缩放功能正常工作(请参阅代码1和相应的图像1)但是当我在Horizo​​ntalScrollView中安排多个这些视图时,它无法正常工作,因为此视图的触摸事件是弄乱了Horizo​​ntalScrollView(代码2和图像2)的触摸事件。

有人请帮我解决这个问题。

这是捏缩放工作正常的活动代码。

    public class MainActivity extends Activity {
    DrawView drawView;


    public class DrawView extends View {
        Paint paint = new Paint();
        public int recog=-1;   // this variable will tell if onDraw is called for first time or is called by listener usinf invalidate()
        boolean listener=false;

        int data[] = new int[] {200,200,200,200,200,200,200,200,200,200,200,200};

        private  float MIN_ZOOM = 0.1f;
        private  float MAX_ZOOM = 10f;

        private float mPosX;
        private float mPosY;


        boolean zoom=false;    
        private ScaleGestureDetector detector;
        float  width=200;

        private float mLastTouchX;
        private float mLastTouchY;


        private ScaleGestureDetector mScaleDetector;
        private float mScaleFactor = 1.f;


        private static final int INVALID_POINTER_ID = -1;

     // The ‘active pointer’ is the one currently moving our object.
     private int mActivePointerId = INVALID_POINTER_ID;



        public DrawView(Context context) {
            this(context, null);            
        }

        public DrawView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }

        public DrawView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());

        }

        @Override
        public void onDraw(Canvas canvas) {

            paint.setColor(Color.GREEN);
            canvas.save();
            if(listener ==true)
                mScaleFactor+=0.4;
            Log.e("Ronak","Listener"+listener);

            Log.e("Ronak","ScaleFactor"+mScaleFactor);
            canvas.scale(mScaleFactor, 1);
            canvas.drawRect(0.0f, 0.0f, 300.0f, 100.0f, paint);
            makeLinesinRange(0,100,300,100,200, 5, canvas,100);
            width=mScaleFactor*300; 
            canvas.restore();
            requestLayout();

           }

        public boolean onTouchEvent(MotionEvent ev) {
            // Let the ScaleGestureDetector inspect all events.
            mScaleDetector.onTouchEvent(ev);

            final int action = ev.getAction();
            switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN: {
                final float x = ev.getX();
                final float y = ev.getY();

                mLastTouchX = x;
                mLastTouchY = y;
                mActivePointerId = ev.getPointerId(0);
                break;
            }

            case MotionEvent.ACTION_MOVE: {
                final int pointerIndex = ev.findPointerIndex(mActivePointerId);
                final float x = ev.getX(pointerIndex);
                final float y = ev.getY(pointerIndex);

                // Only move if the ScaleGestureDetector isn't processing a gesture.
                if (!mScaleDetector.isInProgress()) {
                    final float dx = x - mLastTouchX;
                    final float dy = y - mLastTouchY;

                    mPosX += dx;
                    mPosY += dy;

                    invalidate();
                }

                mLastTouchX = x;
                mLastTouchY = y;

                break;
            }

            case MotionEvent.ACTION_UP: {
                mActivePointerId = INVALID_POINTER_ID;
                break;
            }

            case MotionEvent.ACTION_CANCEL: {
                mActivePointerId = INVALID_POINTER_ID;
                break;
            }

            case MotionEvent.ACTION_POINTER_UP: {
                final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) 
                        >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
                final int pointerId = ev.getPointerId(pointerIndex);
                if (pointerId == mActivePointerId) {
                    // This was our active pointer going up. Choose a new
                    // active pointer and adjust accordingly.
                    final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                    mLastTouchX = ev.getX(newPointerIndex);
                    mLastTouchY = ev.getY(newPointerIndex);
                    mActivePointerId = ev.getPointerId(newPointerIndex);
                }
                break;
            }
            }

            return true;
        }

        @Override protected void onMeasure(int widthMeasureSpec,
                  int heightMeasureSpec) {
               // int width = MeasureSpec.getSize(widthMeasureSpec);
                //int height = (int)(width * 0.5f);
                setMeasuredDimension((int)width, 350);
              }


        private void makeLinesinRange(int x1, int y1, int x2, int y2, int size, int divisions, Canvas canvas,int width)
        {
            paint.setStrokeWidth(6);
            paint.setColor(Color.DKGRAY);
            float kk=(x2-x1)/(divisions-1);
            for(int i=0;i<divisions;i++)
            {
                canvas.drawLine(x1+i*kk, y1, x1+i*kk, y2+size, paint);
            }
        }

        private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
            @Override
            public boolean onScale(ScaleGestureDetector detector) {
                mScaleFactor *= detector.getScaleFactor();

                Log.e("Ronak","scale "+mScaleFactor);
                // Don't let the object get too small or too large.
                mScaleFactor = Math.max(0.3f, Math.min(mScaleFactor, 5.0f));


                invalidate();
                return true;
            }
        }



    }



    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        drawView = new DrawView(this);
        drawView.setBackgroundColor(Color.WHITE);
        setContentView(drawView);




    }
}

DrawView.java。这是单一视图的代码。我在Horizo​​ntalScrollView

中安排了多个这些视图
public class DrawView extends View {
    Paint paint = new Paint();
    public int recog=-1;   // this variable will tell if onDraw is called for first time or is called by listener usinf invalidate()
    boolean listener=false;
    int view_number=0;

    int data[] = new int[] {200,200,200,200,200,200,200,200,200,200,200,200};
    int lines[] = new int[] {4,5,7,8,2,6,6,3,2,1,1,6};
    String[] type=new String[]{"Song","Music","Magazine","Audible","Videos","Apps","Other"};


    private static float MIN_ZOOM = 0.1f;
    private static float MAX_ZOOM = 10f;

    private float mPosX;
    private float mPosY;


    boolean zoom=false;    
    private ScaleGestureDetector detector;
    float  width=700;
    float height=500;

    private float mLastTouchX;
    private float mLastTouchY;


    private ScaleGestureDetector mScaleDetector;
    private float mScaleFactor = 1.f;


    private static final int INVALID_POINTER_ID = -1;

 // The ‘active pointer’ is the one currently moving our object.
 private int mActivePointerId = INVALID_POINTER_ID;



    public DrawView(Context context) {
        this(context, null);            
    }

    public DrawView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DrawView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());

    }

    @Override
    public void onDraw(Canvas canvas) {

        paint.setColor(Color.BLUE);
        canvas.save();
        if(listener ==true)
            mScaleFactor+=0.4;
        Log.e("Ronak","Listener"+listener);

        Log.e("Ronak","ScaleFactor"+mScaleFactor);
        canvas.scale(mScaleFactor, 1);
        canvas.drawRect(0.0f, 0.0f, 300.0f, 70.0f, paint);
        makeLinesinRange(0,70,300,70,200, lines[view_number], canvas,100);


        width=mScaleFactor*300; 
        height=mScaleFactor*100;
        /*int start=0;
        int temp=(int)width/lines[view_number];
        for(int i=0;i<lines[view_number];i++)
        {
            canvas.drawText(type[i], 50, 100, paint);
            start=temp;
            temp+=temp;
        }*/
        canvas.restore();
        requestLayout();

       }

    public boolean onTouchEvent(MotionEvent ev) {
        // Let the ScaleGestureDetector inspect all events.
        mScaleDetector.onTouchEvent(ev);

        final int action = ev.getAction();
        switch (action & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN: {
            final float x = ev.getX();
            final float y = ev.getY();

            mLastTouchX = x;
            mLastTouchY = y;
            mActivePointerId = ev.getPointerId(0);
            break;
        }

        case MotionEvent.ACTION_MOVE: {
            final int pointerIndex = ev.findPointerIndex(mActivePointerId);
            final float x = ev.getX(pointerIndex);
            final float y = ev.getY(pointerIndex);

            // Only move if the ScaleGestureDetector isn't processing a gesture.
            if (!mScaleDetector.isInProgress()) {
                final float dx = x - mLastTouchX;
                final float dy = y - mLastTouchY;

                mPosX += dx;
                mPosY += dy;

               // invalidate();
            }

            mLastTouchX = x;
            mLastTouchY = y;

            break;
        }

        case MotionEvent.ACTION_UP: {
            mActivePointerId = INVALID_POINTER_ID;
            break;
        }

        case MotionEvent.ACTION_CANCEL: {
            mActivePointerId = INVALID_POINTER_ID;
            break;
        }

        case MotionEvent.ACTION_POINTER_UP: {
            final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) 
                    >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
            final int pointerId = ev.getPointerId(pointerIndex);
            if (pointerId == mActivePointerId) {
                // This was our active pointer going up. Choose a new
                // active pointer and adjust accordingly.
                final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                mLastTouchX = ev.getX(newPointerIndex);
                mLastTouchY = ev.getY(newPointerIndex);
                mActivePointerId = ev.getPointerId(newPointerIndex);
            }
            break;
        }
        }

        return true;
    }

    public boolean onInterceptTouchEvent(MotionEvent event) {
       /* switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                mIsBeingDragged = false;
                break;
            case MotionEvent.ACTION_MOVE:
                float x = event.getX();
                float y = event.getY();
                float xDelta = Math.abs(x - mLastX);
                float yDelta = Math.abs(y - mLastY);

                float yDeltaTotal = y - mStartY;
                if (yDelta > xDelta && Math.abs(yDeltaTotal) > mTouchSlop) {
                    mIsBeingDragged = true;
                    mStartY = y;
                    return true;
                }
                break;
        }*/
        Log.e("Ronak","Here");
        return false;
    }



    @Override protected void onMeasure(int widthMeasureSpec,
              int heightMeasureSpec) {
           // int width = MeasureSpec.getSize(widthMeasureSpec);
            //int height = (int)(width * 0.5f);
            setMeasuredDimension((int)width, 350);
          }


    private void makeLinesinRange(int x1, int y1, int x2, int y2, int size, int total_events, Canvas canvas,int width)
    {
        paint.setStrokeWidth(6);
        paint.setColor(Color.MAGENTA);

        if(total_events<1)
        {
            return;
        }
        if(total_events==1)
        {
            canvas.drawLine(((x1+x2)/2), y1, (x1+x2)/2, y2+size, paint);

        }
        else if(total_events==2)
        {
            canvas.drawLine(((x1+x2)/3), y1, (x1+x2)/3, y2+size, paint);
            canvas.drawLine((2*(x1+x2)/3), y1, 2*(x1+x2)/3, y2+size, paint);


        }
        else
        {
        paint.setStrokeWidth(6);
        paint.setColor(Color.MAGENTA);
        float kk=(x2-x1)/(total_events-1);
        for(int i=0;i<total_events;i++)
        {
            canvas.drawLine(x1+i*kk, y1, x1+i*kk, y2+size, paint);
        }
        }
    }

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            mScaleFactor *= detector.getScaleFactor();

            Log.e("Ronak","scale "+mScaleFactor);
            // Don't let the object get too small or too large.
            mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));


            invalidate();
            return true;
        }
    }



}

我还有一个扩展Horizo​​ntalScrollView的类,并调用上面的类(DrawView.java)来在水平滚动中拟合多个这些视图。是否有蚂蚁需要覆盖此类的onTouch函数?

enter image description here enter image description here

1 个答案:

答案 0 :(得分:1)

第一: YIKES!不要从onDraw()调用requestLayout() - 否则你将获得100%的负载,所有它将要做的就是重新布局并重绘自己。

第二步:从onInterceptTouchEvent()移除DrawView。由于它扩展View - 并且View没有这种方法 - 所以它不会被调用作为触摸调度过程的一部分。

第三:哪一个不起作用 - 滚动还是缩放?

阅读this thread,它对如何处理多个手势消耗组件有一些见解