题目说的不是太清楚,具体说一下我的需求。
需求:做一个Android,SDK,被其他工程引用,不能重载View和实现OnClickListener或OnItemOClickListener,获取响应Click,onItemClick的控件。
两种思路:
1.使用AccessibilityService。
不可行的原因:
①只能获取点击事件,不能实现OnItemClick事件。
②用户必须手动到设置中允许用户使用,太繁琐。
2.在Activity中截获点击事件,根据MotionEvent,判断点击发生在屏幕中的那个控件上。
缺点:每点击一下,都要测算,会产生大量的冗余。手机性能好还没问题,手机如果垃圾就惨啦。那位大仙有别的方法,麻烦你告知小弟一下,在这里先谢谢了。
下面是实现的第二种方法的思路:
1.遍历根目录中的子控件,如果某个子控件区域包含点击坐标,停止根目录的子控件的判断,递归调用先前找的子控件,直到遍历结束。
2.如果遍历最后一层视图结束时,ViewGroup中没有找到子控件,就返回ViewGroup。
需要特别说明的是 MontionEvent 获取坐标有两种方式
1.event.getX(),event.getY().这种方法获取的是点击控件相对父控件的坐标,简言之就是视图坐标。
2.event.getRawX(),event.getRawY().获取的是绝对坐标,即是在屏幕上的坐标。
我们只能用第二种方法判断。
package com.alipay.tracker.click;
import android.os.AsyncTask;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import com.alipay.tracker.constant.TrackerLog;
import com.alipay.tracker.util.TrackerHelper;
public class GetClickAsyTask extends AsyncTask<Object, Void, Boolean> {
@Override
protected Boolean doInBackground(Object... params) {
View view = (View) params[0];
MotionEvent event = (MotionEvent) params[1];
View view2 = isClicked(view, event);
view.setTag(view2);
TrackerLog.e("ClickView",view2.getClass().getSimpleName());
return null;
}
private View isClicked(View view, MotionEvent event) {
View result = null;
if (inRangeOfView(view, event) && view.getVisibility() == View.VISIBLE) {
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
for (int i = 0; i < group.getChildCount(); i++) {
View chilView = group.getChildAt(i);
result = isClicked(chilView, event);
if (result != null) {
return result;
}
}
}
result = view;
}
return result;
}
}
public static boolean inRangeOfView(View view, MotionEvent ev) {
int[] location = new int[2];
view.getLocationOnScreen(location);
int x = location[0];
int y = location[1];
if (ev.getRawX() < x || ev.getRawX() > (x + view.getWidth()) || ev.getRawY() < y
|| ev.getRawY() > (y + view.getHeight())) {
return false;
}
return true;
}