Android的多点触控!砍谁? [英] Android multitouch! hack anyone?
问题描述
我必须让这个滑现在作为一个纯粹的学术问题,但我非常希望看到在不久的时间内解决方案。
由于该机器人处理的多点触控,你可以(在我看来)的方式只捕获在一个单一的视图中的事件。我已经试过了黑客这个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屋!