Reputation: 632
I need to track an event each time user clicks on any clickable view in my app. I want to do this generally so e.g. in my main activity.
I know I can override onUserInteraction()
or dispatchTouchEvent()
but these are running even for the clicks which are not clickable views.
I don't need to differ between clickable views, just the fact it is clickable is enough.
In an ideal case, I would also differentiate the Up button from other clicks.
Is this possible?
Upvotes: 6
Views: 2703
Reputation: 237
In my opinion, there's no flawless implementation for what you want to achieve.
One possible way is using a OnClickListener wrapper. This needs you or your team to enforce using this wrapper on any clickable views' OnClickListener. But you cannot cover the views in third party library.
public class OnClickListenerWrapper implements OnClickListener {
private OnClickListener listener
public OnClickListenerWrapper (OnClickListener listener) {
this.listener = listener;
}
public void onClick(View view) {
// Logic of tracking
listener.onClick(view);
}
}
Upvotes: 2
Reputation: 2299
To track all the clickable view use this approach :
Create an interface for click events
package com.gethello.interfaces;
import android.view.View;
public interface OnItemClickInterfaceTesting {
void onItemClick(View view,int id);
}
Create a method in Base activity so that you can access in every activity .
public void setClickListener(Context context, View view, int id) {
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.e("TAG", "Track your click events here");
OnItemClickInterfaceTesting itemController = (OnItemClickInterfaceTesting) context;
itemController.onItemClick(view, id);
}
});
}
Implement OnItemClickInterfaceTesting and methods of interface in your activity.
@Override
public void onItemClick(View view, int id) {
switch (id){
case R.id.id_of_your_view:
Log.e(TAG, "Your view clicked. Add your code to handle click of view.");
break;
}
}
Call method in onCreate like this :
Upvotes: 0
Reputation: 300
I'd go for OOP.
Repeat for other types of controls.
In general, it's not a bad idea to create Base Classes for all elements you will be using, as things like this come up all the time.
Upvotes: 0
Reputation: 14670
Track any click occurring on any clickable View
in the app.
This solution is a bit heavy and requires certain discipline from your side (do not use setOnClickListener()
for other purposes but tracking clicks).
Add a View.OnClickListener
to any View
in your base Activity
or any Activity
, for which you would like to track down click events. Start doing this only when the global layout has finished loading (by adding an OnGlobalLayoutListener
) to the root view. So, the code look could look as follows:
...
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
...
View decorView = getWindow().getDecorView();
decorView.getViewTreeObserver().addOnGlobalLayoutListener(() ->
printClickedViews(getWindow().getDecorView())
);
}
private void printClickedViews(View currentView) {
if (currentView == null) {
return;
}
currentView.setOnClickListener(v -> {
Toast.makeText(v.getContext(), "Clicked on " + v.getClass().getSimpleName(),
Toast.LENGTH_LONG).show();
});
if (currentView instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) currentView;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
printClickedViews(viewGroup.getChildAt(i));
}
}
}
...
Please note that even if you add/remove a new View
, your OnGlobalLayoutListener
will get notified, and that's good.
The most obvious limitation is that setting a View.OnClickListener
will have to be reserved for tracking clicks only. However, you can always use OnTouchListener
for the same purpose as follows:
view.setOnTouchListener((v, event) -> {
if (event.getAction() == MotionEvent.ACTION_UP) {
// handle your click event here
}
return false;
});
Upvotes: 0