Android的多点触控!砍谁? [英] Android multitouch! hack anyone?

查看:115
本文介绍了Android的多点触控!砍谁?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须让这个滑现在作为一个纯粹的学术问题,但我非常希望看到在不久的时间内解决方案。

由于该机器人处理的多点触控,你可以(在我看来)的方式只捕获在一个单一的视图中的事件。我已经试过了黑客这个envolving容器布局拦截事件看什么看它属于通过观察COORDS和不断变化的行动本身,使它看起来,这是一个单点触摸事件的组件。我撰写这样的事件,然后将其路由到视图。

有没有人有一个更好的主意来做到这一点?

如果有人想在code什么我上面只是问,我将它张贴!

有乐趣和好运:D JQCorreia

 公共类容器扩展的LinearLayout
{
        LinkedHashMap的<整数,视图>指针=新的LinkedHashMap<整数,视图>();
        ArrayList的<视图>意见=新的ArrayList<视图>();

        公共集装箱(上下文的背景下){
                超(上下文);
                初始化(上下文);

        }

        公共集装箱(上下文的背景下,ATTRS的AttributeSet){
                超(背景下,ATTRS);
                初始化(上下文);
        }

        私人无效初始化(上下文的背景下)
        {

        }
        @覆盖
        公共无效onLayout(布尔改变,诠释L,INT T,INT R,int b)在
        {
                super.onLayout(改变,L,T,R,B);
                意见= LayoutUtil.flattenLayout(这一点,假);
                对于(查看FOO:观点)
                {
                        矩形RECT =新的矩形();
                        foo.getGlobalVisibleRect(RECT);
                }
        }

        @覆盖
        公共布尔onInterceptTouchEvent(MotionEvent事件)
        {
                返回true;
        }
        @覆盖
        公共布尔的onTouchEvent(MotionEvent事件)
        {
                INT行动= event.getAction()及MotionEvent.ACTION_MASK;
                如果(动作== MotionEvent.ACTION_DOWN)
                {
                        对于(视图V:观点)
                        {
                                矩形R =新的矩形();
                                v.getGlobalVisibleRect(r)的;
                                如果(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(事件)。
                                        打破;
                                }
                        }
                }
                如果(动作== MotionEvent.ACTION_POINTER_DOWN)
                {
                        INT PID = event.getAction()>> MotionEvent.ACTION_POINTER_ID_SHIFT;
                        INT指数= event.findPointerIndex(PID);

                        对于(视图V:观点)
                        {

                                矩形R =新的矩形();
                                v.getGlobalVisibleRect(r)的;
                                如果(event.getX(指数)> r.left
                                                &功放;&安培; event.getX(指数)< r.right
                                                &功放;&安培; event.getY(指数)> r.top
                                                &功放;&安培; event.getY(指数)< r.bottom){


                                        pointers.put(PID,V);
                                        MotionEvent副本= MotionEvent.obtain(事件);
                                        copy.setAction(MotionEvent.ACTION_DOWN);
                                        copy.setLocation(event.getX(指数),event.getY(指数));
                                        pointers.get(PID).onTouchEvent(复印件);
                                }
                        }
                }
                如果(动作== MotionEvent.ACTION_POINTER_UP)
                {
                        INT PID = event.getAction()>> MotionEvent.ACTION_POINTER_ID_SHIFT;
                        INT指数= event.findPointerIndex(PID);

                        如果(pointers.get(PID)!= NULL)//如果触摸了任何视图之外
                        {
                                MotionEvent副本= MotionEvent.obtain(事件);
                                copy.setAction(MotionEvent.ACTION_UP);
                                pointers.get(PID).onTouchEvent(复印件);
                                pointers.remove(PID);
                        }
                }

                如果(动作== MotionEvent.ACTION_MOVE)
                {
                        的for(int i = 0; I< event.getPointerCount();我++)
                        {
                                INT PID = event.getPointerId(ⅰ);
                                MotionEvent副本= MotionEvent.obtain(事件);
                                copy.setLocation(event.getX(i)中,event.getY(ⅰ));

                                如果(pointers.get(PID)== NULL)继续; //如果触摸了任何视图之外
                                pointers.get(PID).onTouchEvent(复印件);
                        }
                }

                如果(动作== MotionEvent.ACTION_UP)
                {
                        如果(pointers.get(event.getPointerId(0))!= NULL)
                        {
                                pointers.get(event.getPointerId(0))的onTouchEvent(事件)。
                                pointers.remove(event.getPointerId(0));
                        }
                }
                返回true;
        }

}

//这是LayoutUtil.flattenLayout方法
        公共静态的ArrayList<视图> flattenLayout(查看视图,布尔addViewGroups)
        {
                ArrayList的<视图> viewList =新的ArrayList<视图>();
                如果(查看的instanceof的ViewGroup)
                {
                        如果(((ViewGroup中)查看).getChildCount()== 0)
                                viewList.add(视图);
                        其他
                        {
                                如果(addViewGroups)
                                {
                                        viewList.add(视图);
                                }
                                ViewGroup中的ViewGroup =(ViewGroup中)查看;
                                的for(int i = 0; I< viewgroup.getChildCount();我++)
                                {
                                        viewList.addAll(flattenLayout(viewgroup.getChildAt(i)中,假));
                                }
                        }
                }
                否则,如果(查看的instanceof查看)
                {
                        viewList.add(视图);
                }
                返回viewList;
        }
 

解决方案

这里最好的解决办法是把

 安卓splitMotionEvents = FALSE
 

里面的LinearLayout或任何版式视图(按钮,TextView的,等等)的。

-cheers快乐的编码

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;
        }

解决方案

The best solution here is to put

android:splitMotionEvents = false 

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

-cheers happy codings

这篇关于Android的多点触控!砍谁?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆