3
I need to log all the actions of a user in an Activity:
For example:
click on R.id.btn_ok view
longclick on R.id.listview-item
3
I need to log all the actions of a user in an Activity:
For example:
click on R.id.btn_ok view
longclick on R.id.listview-item
3
I found the challenge interesting so I made two small classes, Toucheventlogger to log "Touch Events" and Gestureeventlogger for the "Gesture Events".
Both inherit from Motioneventlogger.
Motioneventlogger.java
public abstract class MotionEventLogger {
public interface Logger{
public void log(String text);
}
protected Logger logger;
private String TAG = MotionEventLogger.class.getSimpleName();;
public MotionEventLogger(Logger logger) {
if(logger == null){
this.logger = new DefaultLogger(TAG);
}else{
this.logger = logger;
}
}
abstract void log(MotionEvent event);
protected static class DefaultLogger implements Logger{
final String TAG;
public DefaultLogger(String TAG) {
this.TAG = TAG;
}
@Override
public void log(String text) {
Log.i(TAG, text);
}
}
//Fonte: http://stackoverflow.com/a/14985355/2556111
protected View findViewAtPosition(View parent, int x, int y) {
if (parent instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup)parent;
for (int i=0; i<viewGroup.getChildCount(); i++) {
View child = viewGroup.getChildAt(i);
View viewAtPosition = findViewAtPosition(child, x, y);
if (viewAtPosition != null) {
return viewAtPosition;
}
}
return parent;// null;
} else {
Rect rect = new Rect();
parent.getGlobalVisibleRect(rect);
if (rect.contains(x, y)) {
return parent;
} else {
return null;
}
}
}
protected String getViewIdText(View viewTouched) {
String viewIdText;
if(viewTouched.getId() == View.NO_ID){
viewIdText = viewTouched.getClass().getSimpleName() + " sem id";
}else{
viewIdText = viewTouched.getResources().getResourceEntryName(viewTouched.getId());
}
return viewIdText;
}
}
Toucheventlogger.java
public class TouchEventLogger extends MotionEventLogger {
private ViewGroup contentView;
private int touchSlop;
private boolean canLogMove = false;
public TouchEventLogger(ViewGroup viewGroup, Logger logger) {
super(logger);
contentView = viewGroup;
touchSlop = getTouchSlop(viewGroup);
}
public TouchEventLogger(ViewGroup viewGroup) {
this(viewGroup, null);
}
public TouchEventLogger(Activity activity, Logger loger) {
super(loger);
contentView = (ViewGroup)((ViewGroup)activity.findViewById(android.R.id.content)).getChildAt(0);
touchSlop = getTouchSlop(contentView);
}
public TouchEventLogger(Activity activity) {
this(activity, null);
}
@Override
public void log(MotionEvent event){
float initialX = 0, initialY = 0;
int action = event.getActionMasked();
int eventX = (int) event.getX();
int eventY = (int) event.getY();
View viewTouched= findViewAtPosition(contentView, eventX, eventY);
if(viewTouched == null)return;
String viewIdText = getViewIdText(viewTouched);
switch (action) {
case MotionEvent.ACTION_DOWN:
initialX = eventX;
initialY = eventY;
canLogMove = true;
logger.log(viewIdText + " Action DOWN");
break;
case MotionEvent.ACTION_MOVE:
float xDiff = initialX - eventX;
float yDiff = initialY - eventY;
if(canLogMove && (Math.abs(xDiff) > touchSlop || Math.abs(yDiff) > touchSlop)) {
logger.log(viewIdText + " Action Move");
canLogMove = false;
}
break;
case MotionEvent.ACTION_UP:
logger.log(viewIdText + " Action UP");
break;
case MotionEvent.ACTION_CANCEL:
logger.log(viewIdText + " Action CANCEL");
break;
case MotionEvent.ACTION_OUTSIDE:
logger.log(viewIdText + " Movement occurred outside bounds of current screen element");
break;
}
}
private int getTouchSlop(View view){
ViewConfiguration vc = ViewConfiguration.get(view.getContext());
return vc.getScaledTouchSlop();
}
}
Gestureeventlogger.java
public class GestureEventLogger extends MotionEventLogger implements
GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener{
private GestureDetector gestureDetector;
private String viewIdText;
protected ViewGroup contentView;
public GestureEventLogger(Activity activity, Logger loger) {
super(loger);
contentView = (ViewGroup)((ViewGroup)activity.findViewById(android.R.id.content)).getChildAt(0);
setDetector(activity);
}
public GestureEventLogger(Activity activity) {
this(activity, (Logger)null);
}
public GestureEventLogger(Context context, ViewGroup viewGroup, Logger logger) {
super(logger);
contentView = viewGroup;
setDetector(context);
}
public GestureEventLogger(Context context, ViewGroup viewGroup) {
this(context, viewGroup, null);
setDetector(context);
}
@Override
public void log(MotionEvent event) {
View viewTouched= findViewAtPosition(contentView, (int)event.getX(), (int)event.getY());
if(viewTouched != null){
viewIdText = getViewIdText(viewTouched);
gestureDetector.onTouchEvent(event);
}
}
@Override
public boolean onDoubleTap(MotionEvent arg0) {
logger.log(viewIdText + " DoubleTap");
return true;
}
@Override
public boolean onDoubleTapEvent(MotionEvent arg0) {
//logger.log(viewIdText + " DoubleTapEvent");
return false;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent arg0) {
logger.log(viewIdText + " SingleTap");
return true;
}
@Override
public boolean onDown(MotionEvent arg0) {
//logger.log(viewIdText + " Down");
return false;
}
@Override
public boolean onFling(MotionEvent arg0, MotionEvent arg1, float arg2,
float arg3) {
logger.log(viewIdText + " Fling");
return true;
}
@Override
public void onLongPress(MotionEvent arg0) {
logger.log(viewIdText + " LongPress");
}
@Override
public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2,
float arg3) {
//logger.log(viewIdText + " Scroll");
return false;
}
@Override
public void onShowPress(MotionEvent arg0) {
//logger.log(viewIdText + " ShowPress");
}
@Override
public boolean onSingleTapUp(MotionEvent arg0) {
//logger.log(viewIdText + " SingleTapUp");
return false;
}
private void setDetector(Context context) {
gestureDetector = new GestureDetector(context, this);
gestureDetector.setOnDoubleTapListener(this);
}
}
Use them as follows:
Declare a private variable to Activity:
private MotionEventLogger eventLogger;
In the method onCreate()
create an instance of Toucheventlogger or of Gestureeventlogger:
eventLogger = new TouchEventLogger(this);
//ou
//eventLogger = new GestureEventLogger(this);
Do the override of the method dispatchTouchEvent()
and call eventLogger.log(event);
:
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
eventLogger.log(event);
return super.dispatchTouchEvent(event);
}
By default the log is done in Logcat.
You can make your own logger, make him implement the interface MotionEventLogger.Logger
and pass it on the constructor.
0
onCreate(){
setContentView(R.layout.activity_main);
View view = findViewById(R.id.main);
view.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view,MotionEvent event) {
return true; }
});
didn’t work..
edited, try it this way.
I took the root view from Activity... but it doesn’t take the events.. getWindow().getDecorView().setOnTouchListener
Browser other questions tagged android
You are not signed in. Login or sign up in order to post.
Perfect.. was only missing when the element is inflated in Activity. And when widgets are created in Runtime, some hint?
– user155542
I believe that such situations will be considered if the Toucheventlogger is created after they happened. I will edit the answer as I have been making some changes and also made a class to log Gestures
– ramaral
Note that in addition to the constructor that receives a Activity there is also one who receives a Viewgroup.
– ramaral
perfect, so I create a logger for these situations tbm, thank you very much.
– user155542
The Gestureeventlogger.java does what it asks in the question: identifies the click and the longClick.
– ramaral