Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
338 views
in Technique[技术] by (71.8m points)

multi touch - Android multitouch! hack anyone?

I have to let this slip for now as a purely academic issue but i would very much like to see a solution in near time.

Due to the way that Android handles multitouch you can (as i see it) only trap the event in a single view. I've tried an hack for this envolving a container layout that intercepts the events sees what View it belongs by seeing the coords and changing the action itself so that it seems to the component that it's a single touch event. I compose such events and then route it to the Views.

Does anyone have a better idea to do this?

If someone wants the code for what i described above just ask and i post it!

Have fun and good luck :D JQCorreia

public class Container extends LinearLayout
{      
        LinkedHashMap<Integer,View> pointers = new LinkedHashMap<Integer,View>();
        ArrayList<View> views  = new ArrayList<View>();

        public Container(Context context) {
                super(context);
                initialize(context);

        }

        public Container(Context context, AttributeSet attrs) {
                super(context, attrs);
                initialize(context);
        }

        private void initialize(Context context)
        {

        }
        @Override
        public void onLayout(boolean changed, int l, int t, int r, int b)
        {
                super.onLayout(changed, l, t, r, b);
                views = LayoutUtil.flattenLayout(this,false);
                for(View foo : views)
                {
                        Rect rect = new Rect();
                        foo.getGlobalVisibleRect(rect);
                }
        }

        @Override
        public boolean onInterceptTouchEvent(MotionEvent event)
        {
                return true;
        }
        @Override
        public boolean onTouchEvent(MotionEvent event)
        {
                int action = event.getAction() & MotionEvent.ACTION_MASK;
                if(action==MotionEvent.ACTION_DOWN)
                {
                        for(View v: views)
                        {
                                Rect r = new Rect();
                                v.getGlobalVisibleRect(r);
                                if (event.getX() > r.left && event.getX() < r.right
                                                && event.getY() > r.top
                                                && event.getY() < r.bottom) {
                                        pointers.put(event.getPointerId(0),v);
                                        pointers.get(event.getPointerId(0)).onTouchEvent(event);
                                        break;
                                }
                        }
                }
                if(action==MotionEvent.ACTION_POINTER_DOWN)
                {
                        int pid = event.getAction() >> MotionEvent.ACTION_POINTER_ID_SHIFT;
                        int index = event.findPointerIndex(pid);

                        for(View v: views)
                        {

                                Rect r = new Rect();
                                v.getGlobalVisibleRect(r);
                                if (event.getX(index) > r.left
                                                && event.getX(index) < r.right
                                                && event.getY(index) > r.top
                                                && event.getY(index) < r.bottom) {


                                        pointers.put(pid,v);
                                        MotionEvent copy = MotionEvent.obtain(event);
                                        copy.setAction(MotionEvent.ACTION_DOWN);
                                        copy.setLocation(event.getX(index), event.getY(index));
                                        pointers.get(pid).onTouchEvent(copy);
                                }
                        }
                }
                if(action==MotionEvent.ACTION_POINTER_UP)
                {
                        int pid = event.getAction() >> MotionEvent.ACTION_POINTER_ID_SHIFT;
                        int index = event.findPointerIndex(pid);

                        if(pointers.get(pid)!=null) // If the touch was outside any view
                        {
                                MotionEvent copy = MotionEvent.obtain(event);
                                copy.setAction(MotionEvent.ACTION_UP);
                                pointers.get(pid).onTouchEvent(copy);
                                pointers.remove(pid);
                        }
                }

                if(action==MotionEvent.ACTION_MOVE)
                {
                        for(int i = 0; i<event.getPointerCount();i++)
                        {
                                int pid = event.getPointerId(i);
                                MotionEvent copy = MotionEvent.obtain(event);
                                copy.setLocation(event.getX(i), event.getY(i));

                                if(pointers.get(pid)==null) continue; // If the touch was outside any view
                                pointers.get(pid).onTouchEvent(copy);
                        }
                }

                if(action==MotionEvent.ACTION_UP)
                {
                        if(pointers.get(event.getPointerId(0))!=null)
                        {
                                pointers.get(event.getPointerId(0)).onTouchEvent(event);
                                pointers.remove(event.getPointerId(0));
                        }
                }
                return true;
        }

}

// This is the LayoutUtil.flattenLayout method
        public static ArrayList<View> flattenLayout(View view, boolean addViewGroups)
        {
                ArrayList<View> viewList = new ArrayList<View>();
                if(view instanceof ViewGroup)
                {
                        if(((ViewGroup)view).getChildCount()==0)
                                viewList.add(view);
                        else
                        {
                                if(addViewGroups)
                                {
                                        viewList.add(view);
                                }
                                ViewGroup viewgroup = (ViewGroup) view;
                                for(int i = 0; i < viewgroup.getChildCount();i++)
                                {
                                        viewList.addAll(flattenLayout(viewgroup.getChildAt(i),false));
                                }
                        }      
                }
                else if(view instanceof View)
                {
                        viewList.add(view);
                }
                return viewList;
        }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The best solution here is to put

android:splitMotionEvents = false 

inside LinearLayout or any Layout your view (Button, TextView, etc) is.

-cheers happy codings


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...