Android onClick method doesn't work on a custom view
Asked Answered
I

11

35

I've started working on an app. I build the menu yesterday but the onClick method doesn't work! I created a class that extends View and called her MainMenuObject - that class is for any object in the main menu (buttons, logos etc). I've created a special class for them because I'm doing an animation when the menu starts. After I've built the MainMenuObject class I've built another class (OpeningTimesView) that extends View and will have all the buttons of the main menu in it, and will function as the main activity's layout.

Everything was good, the animation went very well and I wanted to put listeners on my buttons, so I've added an implemention of onClickListener to the OpeningTimesView class, and overrided the onClick method. Then I've added the listener to the buttons with setOnClickListener(this) and setClickable(true), but it doesn't work! I've tried everything! Please help me figure out what I'm doing wrong. I've added a toast to the onClick method that doesn't depend on any "if" but it's won't show neither.

(BTW is there any way to define the screen width and height as variable that all classes can access? it can't be static because you get the height and width from a display object but there must be another way)

this is the code:

public class OpeningTimesView extends View implements OnClickListener{
    private MainMenuObjectView searchButton;
    private MainMenuObjectView supportButton;
    private MainMenuObjectView aboutButton;
    private int screenWidth;
    private int screenHeight;
    public OpeningTimesView(Context context, Display dis) {
        super(context);

        this.screenWidth = dis.getWidth();
        this.screenHeight = dis.getHeight();

        searchButton = new MainMenuObjectView(context, 200, MovingMode.RIGHT, R.drawable.search, dis);
        supportButton = new MainMenuObjectView(context, 400, MovingMode.LEFT, R.drawable.support, dis);
        aboutButton = new MainMenuObjectView(context, 600, MovingMode.RIGHT, R.drawable.about, dis);

        searchButton.setClickable(true);
        supportButton.setClickable(true);
        aboutButton.setClickable(true);

        searchButton.setOnClickListener(this);
        supportButton.setOnClickListener(this);
        aboutButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View view){
        Toast.makeText(getContext(), "Search button pressed", Toast.LENGTH_SHORT).show();
        if(view == searchButton){
            Toast.makeText(getContext(), "Search button pressed", Toast.LENGTH_SHORT).show();
        }
        else if(view == supportButton){
            Toast.makeText(getContext(), "Support button pressed", Toast.LENGTH_SHORT).show();
        }
        else Toast.makeText(getContext(), "About button pressed", Toast.LENGTH_SHORT).show();
    }
    @Override
    public void onDraw(Canvas canvas)
    {
        // Drawing the buttons
        this.searchButton.onDraw(canvas);
        this.aboutButton.onDraw(canvas);
        this.supportButton.onDraw(canvas);
    }

Thanks in advance, Elad!

Interlaminate answered 18/4, 2011 at 13:22 Comment(1)
Please check this link , i have come up with an solution #2827076Stannum
I
3

I've got a solution! It's not really a solution for this specific issue, but a whole new approach. I sent this thread to somebody I know and he told me to use the Animation SDK the android has (like Wireless Designs mentioned), so instead of doing the main menu page with 4 classes, I'm doing it only with one class that extends Activity, and the Animation class offers many animation options. I want to thank you both for helping me, you are great. I'm adding the code if someone will encounter this thread with the same problem or something:

package elad.openapp;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.HapticFeedbackConstants;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.Toast;

public class OpeningTimes extends Activity implements OnClickListener{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    // Disabling the title bar..
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.main);

    // Create the buttons and title objects
    ImageView title = (ImageView)findViewById(R.id.title_main);
    ImageView search = (ImageView)findViewById(R.id.search_button_main);
    ImageView support = (ImageView)findViewById(R.id.support_button_main);
    ImageView about = (ImageView)findViewById(R.id.about_button_main);

    // Setting the onClick listeners
    search.setOnClickListener(this);
    support.setOnClickListener(this);
    about.setOnClickListener(this);

    setButtonsAnimation(title, search, support, about);

}

@Override
public void onClick(View v) {
    if(v.getId()==R.id.search_button_main){
        v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
        startActivity(new Intent(this,SearchPage.class));
    }
    else if(v.getId()==R.id.support_button_main){
        v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
        Toast.makeText(this, "Coming soon...", Toast.LENGTH_LONG).show();
    }
    else if(v.getId()==R.id.about_button_main){

        v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
        Toast.makeText(this, "Coming soon...", Toast.LENGTH_LONG).show();
    }
}

// Setting the animation on the buttons
public void setButtonsAnimation(ImageView title, ImageView search, ImageView support, ImageView about){
    // Title animation (two animations - scale and translate)
    AnimationSet animSet = new AnimationSet(true);

    Animation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f);
    anim.setDuration(750);
    animSet.addAnimation(anim);

    anim = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
            Animation.RELATIVE_TO_SELF, -1.0f, Animation.RELATIVE_TO_SELF, 0.0f);
    anim.setDuration(750);
    animSet.addAnimation(anim);

    title.startAnimation(animSet);

    // Search button animation
    anim = new TranslateAnimation(Animation.RELATIVE_TO_SELF, -1.5f, Animation.RELATIVE_TO_SELF, 0.0f,
            Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f);
    anim.setDuration(750);

    search.startAnimation(anim);

    // Support button animation
    anim = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 1.5f, Animation.RELATIVE_TO_SELF, 0.0f,
            Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f);
    anim.setDuration(750);

    support.startAnimation(anim);

    // About button animation
    anim = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
            Animation.RELATIVE_TO_SELF, 3f, Animation.RELATIVE_TO_SELF, 0.0f);
    anim.setDuration(750);

    about.startAnimation(anim);
}
}
Interlaminate answered 19/4, 2011 at 21:10 Comment(0)
I
23

I just had the same Problem - I created a custom view and when I registered a new Listener for it in the activity by calling v.setOnClickListener(new OnClickListener() {...}); the listener just did not get called.

In my custom view I also overwrote the public boolean onTouchEvent(MotionEvent event) {...} method. The problem was that I did not call the method of the View class - super.onTouchEvent(event). That solved the problem. So if you are wondering why your listener does not get called you have probably forgotten to call the superclass'es onTouchEvent method

Here is a simple example:

private static class CustomView extends View implements View.OnClickListener {
    public CustomView(Context context) {
        super(context);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);   // this super call is important !!!
        // YOUR LOGIC HERE
        return true;
    }

    @Override
    public void onClick(View v) {
        // DO SOMETHING HERE
    }
}
Implied answered 28/1, 2012 at 15:33 Comment(2)
Huh please add code so we can understand. Where did you put call to the method ...Sandhog
Thanks for the comment - I added a simple example, hope that now it is clearerImplied
P
18

Creating custom controls in Android can be tricky if you aren't comfortable with how the UI Framework operates. If you haven't already, I would recommend reading these:

http://developer.android.com/guide/topics/ui/declaring-layout.html

http://developer.android.com/guide/topics/ui/custom-components.html

http://developer.android.com/guide/topics/ui/layout-objects.html

Notice that when layouts are declared in XML the elements are nested. This creates a layout hierarchy that you must create your self when customizing a component using only Java code.

Most likely you are getting caught up in Android's touch hierarchy. Unlike some other popular mobile platforms, Android delivers touch events starting at the top of the View hierarchy and works its way down. The classes that traditionally occupy the higher levels of the hierarchy (Activity and Layouts) have logic in them to forward touches they don't themselves consume.

So, what I would recommend doing is changing your OpeningTimesView to extend a ViewGroup (the superclass of all Android layouts) or a specific layout (LinearLayout, RelativeLayout, etc.) and add your buttons as children. Right now, there does not seem to be a defined hierarchy (the buttons aren't really "contained" in the container, they're just members) which may be confusing the issue as to where events are really going.

  1. The touches should more naturally flow down to the buttons, allowing your click events to trigger
  2. You can take advantage of Android's layout mechanisms to draw your view instead of relying on drawing code to do all of that.

Pick a layout class to start with that will help you place your buttons in their FINAL locations. You can use the animation framework in Android or custom drawing code (like you have now) to animate them anyway you like up to that point. The location of a button and where that button is currently drawn are allowed to be very different if necessary, and that's how the current Animation Framework works in Android (prior to 3.0)...but that's a separate issue. You also have AbsoluteLayout, which allows you to place and replace objects anywhere you like...but be careful of how your app looks on all Android devices with this one (given the different screen sizes).

As to your second point about display info. The simplest method is probably just to use Context.getResources().getDisplayMetrics() wherever you need it. Activity inherits from Context, so they can call this method directly. Views always have a Context you can access with getContext(). Any other classes you can just pass the Context as a parameter in construction (this is a common pattern in Android, you'll see many objects require a Context, mainly to access Resources).

Here's a skeleton example to jump start things. This just lines the three up horizontally once as a final location:

Public class OpeningTimesView extends LinearLayout implements OnClickListener {
    private MainMenuObjectView searchButton;
    private MainMenuObjectView supportButton;
    private MainMenuObjectView aboutButton;
    private int screenWidth;
    private int screenHeight;

    public OpeningTimesView(Context context) {
        this(context, null);
    }

    //Thus constructor gets used if you ever instantiate your component from XML
    public OpeningTimesView(Context context, AttributeSet attrs) {
        super(context, attrs);

        /* This is a better way to obtain your screen info
        DisplayMetrics display = context.getResources().getDisplayMetrics();
        screenWidth = display.widthPixels;
        screenHeight = display.heightPixels;
        */
        //This way works also, without needing to customize the constructor
        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
        Display dis = wm.getDefaultDisplay();
        screenWidth = dis.getWidth();
        screenHeight = dis.getHeight();

        searchButton = new MainMenuObjectView(context, 200, MovingMode.RIGHT, R.drawable.search, dis);
        supportButton = new MainMenuObjectView(context, 400, MovingMode.LEFT, R.drawable.support, dis);
        aboutButton = new MainMenuObjectView(context, 600, MovingMode.RIGHT, R.drawable.about, dis);

        //Even if they don't extend button, if MainMenuObjectView is always clickable
        // this should probably be brought into that class's constructor
        searchButton.setClickable(true);
        supportButton.setClickable(true);
        aboutButton.setClickable(true);

        searchButton.setOnClickListener(this);
        supportButton.setOnClickListener(this);
        aboutButton.setOnClickListener(this);

        //Add the buttons to the layout (the buttons are now children of the container)
        setOrientation(LinearLayout.HORIZONTAL);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        addView(searchButton, params);
        addView(supportButton, params);
        addView(aboutButton, params);       
    }

    @Override
    public void onClick(View view){
        Toast.makeText(getContext(), "Search button pressed", Toast.LENGTH_SHORT).show();
        if(view == searchButton){
            Toast.makeText(getContext(), "Search button pressed", Toast.LENGTH_SHORT).show();
        }
        else if(view == supportButton){
            Toast.makeText(getContext(), "Support button pressed", Toast.LENGTH_SHORT).show();
        }
        else Toast.makeText(getContext(), "About button pressed", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onDraw(Canvas canvas)
    {
        //Drawing the buttons
        // This may only be necessary until they are in place, then just call super.onDraw(canvas)
        this.searchButton.onDraw(canvas);
        this.aboutButton.onDraw(canvas);
        this.supportButton.onDraw(canvas);
    }    
}

You can customize this from there. Perhaps starting the buttons with visibility set to View.INVISIBLE until you animate them in with your drawing code or a custom Animation object, then making them visibile in their final resting place.

The key here, though, is the the layout is smart enough to know that when it receives a touch event it is supposed to forward it to the corresponding child. You can create a custom view without this, but you will have to intercept all touches on the container and do the math to determine which subview to manually forward the event to. If you truly can't make any layout manager work, this is your recourse.

Hope that Helps!

Progeny answered 18/4, 2011 at 13:43 Comment(3)
First of all thank you for your answer! I tried to extend ViewGroup but I need to implement the method onLayout() and I don't really know what it is, I tried to leave it blank but when I ran the app I got a black screen. I can't really use any specifix layout because I'm doing an animation and the buttons and title aren't static. I didn't understand how to make the buttons children and not just members. I would be happy if you could explain yourself more because I'm really new to Android :) And for the screen size, thank you, it helped me very much!Interlaminate
Tried to add some more information that will hopefully help clarify building components within the context (pun intended) of Android. Custom Android components aren't so troublesome once you get comfortable with how Android manages UI. Cheers.Progeny
Thanks man. It was like an small article. So useful for me. I am amazed why it is not upvoted so much.Gittens
W
11

You can just call performClick() in onTouchEvent of your custom view.

Use this in you custom view:

    @Override
    public boolean onTouchEvent(final MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_UP){
            return performClick();
        }
        return true;
    }
Wilmerwilmette answered 2/10, 2013 at 23:46 Comment(0)
S
9

I do this so:

public class YourView extends LinearLayout implements OnClickListener {
    OnClickListener listener;

    //... constructors

    public void setOnClickListener(OnClickListener listener) {
        this.listener = listener;
    }

    @Override
    public void onClick(View v) {
        if (listener != null)
             listener.onClick(v);
    }
}
Shem answered 1/9, 2016 at 11:53 Comment(1)
this seems to work well. When I was implementing my custom viewgroup, I was getting the onClick() to trigger inside of my viewgroup, but outside, in the activity it wouldn't trigger. So I used this approach. Works. Note: I couldn't get butterknife to work with this.Kiehl
M
9

You have to call setOnClickListener(this) in contructor(s) and implement View.OnClickListener on self.

In this way:

public class MyView extends View implements View.OnClickListener {

    public MyView(Context context) {
        super(context);
        setOnClickListener(this);
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        Toast.makeText(getContext(), "On click.", Toast.LENGTH_SHORT).show();
    }
}
Molnar answered 23/2, 2017 at 22:10 Comment(0)
E
8

I had the same problem. In my case I had a LinearLayout as a root element of my custom view, with clickable and focusable set to true, and the custom view tag itself (used in a fragment's layout) was also set to be clickable and focusable. Turns out that the only thing I had to do to get it working was to remove all the clickable and focusable attributes from within the XML :) Counter-intuitive, but it worked.

Enwomb answered 21/11, 2018 at 16:12 Comment(0)
C
3

Implement the onClickListener in the MainMenuObjectView class, since those are the objects that will respond to clicks.
Another alternative would be to extend Button instead of View, because you are using only buttons in there


Update: Full example


This is the idea to implement it directly into the clickable views. There is a TestView class that extends View and overrides onDraw, as you need it to, and also responds to clicks. I left out any animation implementation as you have that part and it's not relevant to the ClickListener discussion.
I tested it in an Eclair emulator and it works as expected (a Toast message after a click).

file: Test.java

package com.aleadam.test;

import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.TextView;

public class Test extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LinearLayout ll = new LinearLayout(this);
        ll.setOrientation(LinearLayout.VERTICAL);
        TextView label = new TextView(this);
        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
             LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        label.setText("Click the circle!");
        TestView testView = new TestView(this);
        ll.addView(label, layoutParams);
        ll.addView(testView, layoutParams);
        setContentView(ll);
    }
}

file: TestView.java

package com.aleadam.test;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;

public class TestView extends View implements OnClickListener {
    Context context;

    public TestView(Context context) {
        super(context);
        this.context = context;
        setOnClickListener(this);
    }

    public void onClick(View arg0) {
        Toast.makeText(context, "View clicked.", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onDraw (Canvas canvas) {
        super.onDraw(canvas);
        this.setBackgroundColor(Color.LTGRAY);
        Paint paint = new Paint (Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.RED);
        canvas.drawCircle(20, 20, 20, paint);
    }
}

If you need some clickable and some not clickable, you can add a constructor with a boolean argument to determine whether the ClickListener is attached or not to the View:

public TestView(Context context, boolean clickable) {
    super(context);
    this.context = context;
    if (clickable)
        setOnClickListener(this);
}
Cowling answered 18/4, 2011 at 13:44 Comment(10)
That won't really change the behavior here, and the whole point of a Listener design pattern is so the object generating the event is not required to be object that handles it.Progeny
@Wireless on the contrary, it would simplify the issue. I'm not saying it's the only option available, but for this example as I see it, it would eliminate the problem you mention yourself about View hierarchy and handling of the event.Cowling
@Cowling The click event in that code will never fire, because the overarching touch event that creates it isn't sent to the right view. This won't be solved by moving the click listener.Progeny
I believe that is incorrect if you either implement the listener is implemented in the same view (as it would be by doing it in the MainMenuObjectView class or extend Button instead of View. But, I don't have Eclipse and an emulator here, so I will do the formal test later this evening.Cowling
The MainMenuObjectView is not only for the buttons, I created it for everything in the main menu including the title, because I'm doing an animation when you open the app, so I need the onDraw method override and adding move() method, so implementing on click listener to this class would be wrong. To the other option of making it extend Button instead of view, I tried it, but it doesn't help, I guess it's like Wireless Designs said that the event is getting caught somewhere... But thanks anyway I really appreciate your help!Interlaminate
@Wireless I updated the response to include a complete, working example of what I meant. The listener works as expected. As I said above, I do not think this is the only way of doing it. But I do believe it's a simple way for a simple situation.Cowling
@Interlaminate please take a look at the updated response with the included example, to give you an idea of what I mean.Cowling
@Aleadam, I tried the way you suggested but it won't work. I don't have only activity and view classes, I have an activity class, a view class that represent the buttons and the title of the main menu, and a view class named OpeningTimesView that functions as the activity's layout: mainView = new OpeningTimesView(this); setContentView(mainView); Damn, such a simple thing, so much trouble.Interlaminate
@Elad I understand you might want to approach it differently, and that's perfectly fine. I added the complete example here mostly because of the comment saying that the click event would never fire. I even received a downvote for that and it is incorrect. It fires. Thus, the proof for it. I did try a more complicated test also with the same positive result. Now, I'm sure Wireless Design's approach will also work and it is probably more scalable and reusable than mine, so I encourage you to try it. I have been wrong and corrected many times, but this is not one of those.Cowling
Very nice solution... used this to implement onClickListener for an extended linear layout. Upvote!Olein
I
3

I've got a solution! It's not really a solution for this specific issue, but a whole new approach. I sent this thread to somebody I know and he told me to use the Animation SDK the android has (like Wireless Designs mentioned), so instead of doing the main menu page with 4 classes, I'm doing it only with one class that extends Activity, and the Animation class offers many animation options. I want to thank you both for helping me, you are great. I'm adding the code if someone will encounter this thread with the same problem or something:

package elad.openapp;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.HapticFeedbackConstants;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.Toast;

public class OpeningTimes extends Activity implements OnClickListener{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    // Disabling the title bar..
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.main);

    // Create the buttons and title objects
    ImageView title = (ImageView)findViewById(R.id.title_main);
    ImageView search = (ImageView)findViewById(R.id.search_button_main);
    ImageView support = (ImageView)findViewById(R.id.support_button_main);
    ImageView about = (ImageView)findViewById(R.id.about_button_main);

    // Setting the onClick listeners
    search.setOnClickListener(this);
    support.setOnClickListener(this);
    about.setOnClickListener(this);

    setButtonsAnimation(title, search, support, about);

}

@Override
public void onClick(View v) {
    if(v.getId()==R.id.search_button_main){
        v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
        startActivity(new Intent(this,SearchPage.class));
    }
    else if(v.getId()==R.id.support_button_main){
        v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
        Toast.makeText(this, "Coming soon...", Toast.LENGTH_LONG).show();
    }
    else if(v.getId()==R.id.about_button_main){

        v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
        Toast.makeText(this, "Coming soon...", Toast.LENGTH_LONG).show();
    }
}

// Setting the animation on the buttons
public void setButtonsAnimation(ImageView title, ImageView search, ImageView support, ImageView about){
    // Title animation (two animations - scale and translate)
    AnimationSet animSet = new AnimationSet(true);

    Animation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f);
    anim.setDuration(750);
    animSet.addAnimation(anim);

    anim = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
            Animation.RELATIVE_TO_SELF, -1.0f, Animation.RELATIVE_TO_SELF, 0.0f);
    anim.setDuration(750);
    animSet.addAnimation(anim);

    title.startAnimation(animSet);

    // Search button animation
    anim = new TranslateAnimation(Animation.RELATIVE_TO_SELF, -1.5f, Animation.RELATIVE_TO_SELF, 0.0f,
            Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f);
    anim.setDuration(750);

    search.startAnimation(anim);

    // Support button animation
    anim = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 1.5f, Animation.RELATIVE_TO_SELF, 0.0f,
            Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f);
    anim.setDuration(750);

    support.startAnimation(anim);

    // About button animation
    anim = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
            Animation.RELATIVE_TO_SELF, 3f, Animation.RELATIVE_TO_SELF, 0.0f);
    anim.setDuration(750);

    about.startAnimation(anim);
}
}
Interlaminate answered 19/4, 2011 at 21:10 Comment(0)
S
3

In my case I had a RelativeLayout as a parent in my custom view and the only way to make it work was to set focusable and clickable to true in the RelativeLayout and in the constructor of the custom view, after inflating the layout, add this:

View view = inflate(getContext(), R.layout.layout_my_custom_view, this);

view.findViewById(R.id.theparent).setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            performClick();
        }
    });
Snuggle answered 30/4, 2019 at 11:23 Comment(0)
D
2

It is this easy:

public class FancyButton
 extends FrameLayout
 implements View.OnClickListener { ..

    void yourSetupFunction(Context context, @Nullable AttributeSet attrs) {
        ..
        super.setOnClickListener(this); // NOTE THE SUPER
    }

    OnClickListener consumerListener = null;
    @Override
    public void setOnClickListener(@Nullable OnClickListener l) {
        consumerListener = l;
        // DO NOT CALL SUPER HERE
    }

    @Override
    public void onClick(View v) {
        Log.i("dev","perform my custom functions, and then ...");
        if (consumerListener != null) { consumerListener.onClick(v); }
    }
  1. implement View.OnClickListener, and hence have an
  2. onClick(View v)
  3. in setOnClickListener, "remember" the listener set from the outside world
  4. set the actual listener to be us (using "super." ...)
  5. in onClick do you custom stuff, and then call the outside world's onClick
Doerr answered 21/3, 2021 at 13:58 Comment(0)
C
0

just add callOnClick() to your onTouchEvent() method

public boolean onTouchEvent(MotionEvent event) {
        .....YOURCODE.....
        callOnClick();
        return boolean;
    }
Coagulase answered 26/12, 2018 at 3:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.