1

I am making an app that is using HorizontalScrollView for showing list of items. So I have multiple views inside HorizontalScrollView for horizontal scrolling. I am changing the layout size of a view on detecting pinch zoom according to scaleFactor

I have implemented it at view level so when user pinch zoom having both finger inside a single view, that view is detecting pinch zoom and changing its size but when I pinch zoom with my fingers in different views this is not working.

I want to extend this so when user pinch zoom having fingers on different views, all the views which are between two fingers should change its size dynamically.

Can anyone suggest me on how to extend this idea and make it work.

    public CenterLockHorizontalScrollview(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        this.setSmoothScrollingEnabled(true);
        detector = new ScaleGestureDetector(context, new ScaleListener());


    }


    public boolean onTouchEvent(MotionEvent ev) {

        return super.onTouchEvent(ev);

    }



    public void setAdapter(Context context, CustomListAdapter mAdapter) {

        try {
            this.kk=mAdapter;
            fillViewWithAdapter(mAdapter);
        } catch (ZeroChildException e) {

            e.printStackTrace();
        }
    }

    private void fillViewWithAdapter(CustomListAdapter mAdapter)
            throws ZeroChildException {
        if (getChildCount() == 0) {
            throw new ZeroChildException(
                    "CenterLockHorizontalScrollView must have one child");
        }

        if (getChildCount() == 0 || mAdapter == null)
        {        Log.e("Ronak","Came at zero");
            return;
        }

         parent = (ViewGroup) getChildAt(0);

        for (int i = 0; i < mAdapter.getCount(); i++) {
            parent.addView(mAdapter.getView(i, null, parent));
        }

        //System.out.println("number of child is "+parent.getChildCount());
    }


    public ViewGroup takeparent()
    {
        return parent;
    }


    int start=0; //index of first child view
    int last=0;  //index of last child view

    float x1,x2,y1,y2;

    public boolean dispatchTouchEvent(MotionEvent ev) {


        boolean result = super.dispatchTouchEvent(ev);
        if (inDifferentView(ev)) {
             detector.onTouchEvent(ev);
        }

            return super.dispatchTouchEvent(ev);
        }





    //set the value of 'start' and 'last' variable
    private boolean inDifferentView(MotionEvent ev) {
        Rect outRect = new Rect();


        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            x1=ev.getX(0);
            y1=ev.getY(0);
            Log.e("Ronak","First finger Coordinates "+x1+" "+y1);
        }
        switch (ev.getAction() & MotionEvent.ACTION_MASK) {

        case MotionEvent.ACTION_POINTER_DOWN:

            visibleRect.clear();
            indices.clear();
            int left=0;

            x2=ev.getX(1);
            y2=ev.getY(1);
            Log.e("Ronak","Second finger Coordinates "+x2+" "+y2);

            ViewGroup parent=takeparent(); //parent viewGroup. This is of type HorizontalScrollView
            for(int i=0; i<parent.getChildCount(); i++)
            {
                View childview =parent.getChildAt(i);
                this.getHitRect(outRect);

                if (childview.getLocalVisibleRect(outRect)){  
                    Log.e("Ronak","Child number is "+i + "Coordinates are "+outRect.flattenToString());
                    visibleRect.add(new Rect(left,outRect.top,outRect.right-outRect.left+left,outRect.bottom));
                    left+=(outRect.right-outRect.left);
                    indices.add(i);
                }

            }

            for(int i=0;i<visibleRect.size();i++)
            {
                Log.e("Ronak","Original  rectangle "+visibleRect.get(i).flattenToString());
                Rect ar=visibleRect.get(i);
                if(x1>=ar.left && x1<=ar.right && y1>=ar.top && y1 <=ar.bottom);
                {
                    Log.e("Ronak","ALSO");
                    int temp=indices.get(i);
                    Log.e("ROnak","Found Index of rectangle "+temp);
                        start=temp;

                }
                if(x2>=ar.left && x2<=ar.right && y2>=ar.top && y2 <=ar.bottom)
                {
                    Log.e("Ronak","ALSO");
                    int temp=indices.get(i);
                    Log.e("ROnak","Second Found Index of rectangle "+temp);

                    last=temp;
                }
            }

        }
        //interchanging start and last
        if(start>last)
        {
            int temp=last;
            last=start;
            start=temp;
        }

        return true;
    } 



    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            mScaleFactor *= detector.getScaleFactor();
            mScaleFactor = Math.max(1.0f, Math.min(mScaleFactor, 5.0f));
            Log.e("Ronak","SF is "+mScaleFactor);
            ViewGroup pp=takeparent();
           /*for(int i=start;i<=last;i++)
            {
                LinearLayout ll=(LinearLayout)pp.getChildAt(i);
                DrawView view=(DrawView)ll.findViewById(R.id.drawview);
                view.width=mScaleFactor*(view.width);
                view.invalidate();
            }
            */

            return true;
        }
    }





}
user3265443
  • 535
  • 1
  • 8
  • 25
  • extend container HorizontalScrollView and override dispatchTouchEvent – pskink Apr 20 '14 at 21:41
  • @pskink I basically have to route touch events to all the child views which are between my fingers. But how do I know the indices of child which are currently visible on screen. I have edited the above code and added HorizontalScrollView subclass also. – user3265443 Apr 21 '14 at 07:01
  • iterate over all children and do some tests on Rect taken from child.getHitRect() – pskink Apr 21 '14 at 07:12
  • @pskink can you help me out to find the start and end index of child views which are currently between two fingers. Please help me in coding of this – user3265443 Apr 21 '14 at 07:20
  • as i said iterate over all children, use getChildCount and getChildAt – pskink Apr 21 '14 at 07:28
  • @pskink Sorry you get me wrong. As some child will be partially visible and some will be fully visible. So when touch event occur how do I translate touch event to find index. – user3265443 Apr 21 '14 at 07:33
  • 1
    i gave you all needed methods: ViewGroup.getChildCount, ViewGropu.getChildAt and View.getHitRect, the rest is sumple math with the Rect and the line between your two fingers – pskink Apr 21 '14 at 07:40
  • @pskink I have done as you said but I am always getting start and end index as 0 value always. See my dispatchTouchEvent code above. Please tell me where I am going wrong. – user3265443 Apr 21 '14 at 08:52
  • 1
    imagine a line between two points in 2D , then for each child get its Rect and simply check if that Rect has any common part with that line, thats all – pskink Apr 21 '14 at 09:06
  • @pskink I am following [this](http://stackoverflow.com/questions/4628800/android-how-to-check-if-a-view-inside-of-scrollview-is-visible) question to find out the views which are currently visible and I am getting it right. But the coordinates of rectangle is not right. For example when my visible child views are 0,1,2. I am getting this Child number is 0 Coordinates are 0 0 341 400 Child number is 1 Coordinates are 0 0 383 400 Child number is 2 Coordinates are 0 0 476 400 and my finger touch coordinates are First finger Coordinates 0 428 Second finger Coordinates 1030 388 So how to map this – user3265443 Apr 21 '14 at 10:32
  • I have added my code in the question – user3265443 Apr 21 '14 at 10:41
  • what is getLocalVisibleRect for? – pskink Apr 21 '14 at 10:49
  • I am following this http://stackoverflow.com/questions/4628800/android-how-to-check-if-a-view-inside-of-scrollview-is-visible and is showing correct child views which are visible – user3265443 Apr 21 '14 at 10:56
  • and using getLocalVisibleRect are left/top coords always zero? strange.... – pskink Apr 21 '14 at 11:08
  • @pskink It is not giving 0 always. Sometimes it is returning some unrelated coordinates. Could you tell me some different approach? – user3265443 Apr 21 '14 at 11:20
  • sometimes... i dont know what you are doing, so word "sometimes" doesnt say anything... – pskink Apr 21 '14 at 11:24
  • I got my mistake and now I am able to get the starting and end index of views. I want to zoom all the views between start and end. How to pass this information to all child views. Should I do it by calling onDraw() for all childs or there is some other way – user3265443 Apr 21 '14 at 11:40
  • so set the scale factor for all of these children – pskink Apr 21 '14 at 11:51
  • @pskink the child views inside the HorizontalScrollView is still getting the touch events. dispatchTouchEvent() is always returning true. Then why the child views are getting the events. Can you please check my code – user3265443 Apr 21 '14 at 14:10
  • @pskink I am getting very unexpected results for pinch zoom. It is expanding very fast and also I am not able to pinch back(zoom out) as it is confusing with scrolling event of HorizontalScrollView. Please see my above code and see if anything I can do to fix this. – user3265443 Apr 21 '14 at 17:52
  • @pskink Please help me in this question http://stackoverflow.com/questions/23358112/scaling-around-mid-point-of-two-fingers-in-android. I really want your help. – user3265443 Apr 29 '14 at 07:23

0 Answers0