How to track every reasonable click in android app?
Asked Answered
H

4

6

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?

Homocentric answered 22/3, 2021 at 15:25 Comment(0)
R
2

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);
    }
}
Rotgut answered 31/3, 2021 at 15:41 Comment(0)
P
0

Problem

Track any click occurring on any clickable View in the app.

Possible solution

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.

Limitations

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;
    });
Portraitist answered 24/3, 2021 at 23:54 Comment(0)
A
0

To track all the clickable view use this approach :

  1. Create an interface for click events

     package com.gethello.interfaces;
    
     import android.view.View;
    
     public interface OnItemClickInterfaceTesting {
    
        void onItemClick(View view,int id);
    
    
     }
    
  2. 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);

            }
        });
    }
  1. 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;
    
     }
    }
    
  2. Call method in onCreate like this :

    setClickListener(this,ViewName,R.id.id_of_view); for example

Ape answered 25/3, 2021 at 8:6 Comment(0)
I
0

I'd go for OOP.

  1. Create a class that extends Button. In this class override the onClick listener and do whatever you need to do there. This SO seems helpful Creating custom control with overriding onclick
  2. Replace all in layouts.xml with <your.package.custombutton>.

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.

Irrelievable answered 26/3, 2021 at 22:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.