Custom View not responding to touches
Asked Answered
M

2

7

I've created a custom view which should change it's background image when pressed, highlighted or disabled. The app runs but the button doesn't change it's background.

here's my code:

public class CustomImageButton extends View {

public CustomImageButton(Context context) {
super(context);
setFocusable(true);
setClickable(true);
}

public CustomImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
setFocusable(true);
setClickable(true);
}
public CustomImageButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setFocusable(true);
setClickable(true);
}

protected Drawable background = super.getBackground();


@Override
public void setBackgroundDrawable(Drawable d) {
// Replace the original background drawable (e.g. image) with a LayerDrawable that
// contains the original drawable slightly edited.

CustomImageButtonBackgroundDrawable layer = new CustomImageButtonBackgroundDrawable(d);
super.setBackgroundDrawable(layer);
}

public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 int drawableWidth = super.getBackground().getMinimumWidth();
 int drawableHeight = super.getBackground().getMinimumHeight();
 setMeasuredDimension(drawableWidth, drawableHeight);
}

protected class CustomImageButtonBackgroundDrawable extends LayerDrawable { 

    protected Drawable lowerlayer;
    protected Drawable _highlightedDrawable;

    protected int _disabledAlpha = 100;
    protected Drawable _pressedDrawable;


    public CustomImageButtonBackgroundDrawable(Drawable d) {
          super(new Drawable[] { d });
    }

    @Override
    protected boolean onStateChange(int[] states) {
      boolean enabled = false;
      boolean highlighted = false;
      boolean pressed = false;

      for (int state : states) {
        if (state == android.R.attr.state_enabled)
            enabled = true;
        else if (state == android.R.attr.state_selected)
            highlighted = true;
        else if (state == android.R.attr.state_pressed)
            pressed = true;
      }

      mutate();
      if (enabled && highlighted) {
        ColorFilter colourFilter = new LightingColorFilter(Color.YELLOW, 1);
        ScaleDrawable resizedImage = new ScaleDrawable(background, 0, 1.25f, 1.25f);

        lowerlayer = resizedImage.getDrawable();
        lowerlayer.setColorFilter(colourFilter);

        Drawable[] aD = new Drawable[2];
        aD[0] = lowerlayer;
        aD[1] = background;
        LayerDrawable _highlightedDrawable = new LayerDrawable(aD);

        setBackgroundDrawable(_highlightedDrawable); // buttons need transparent backgrounds

      } else if (!enabled) {
        setColorFilter(null);
        setAlpha(_disabledAlpha);

      } else if (enabled && pressed){
        ScaleDrawable smaller = new ScaleDrawable(background, 0, 0.75f, 0.75f);

        setBackgroundDrawable(smaller.getDrawable());

      } else if(enabled){
        setBackgroundDrawable(background);  
        setColorFilter(null);
      }

      invalidateSelf();

      return super.onStateChange(states);
    }

}

}

Here's my xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff">

<ImageButton
    android:id="@+id/title"
    android:layout_width="250dp"
    android:layout_height="58dp"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:layout_margin ="25dp"
    android:background="@drawable/skintonetitle" />

<custombuttons.CustomImageButton
    android:id="@+id/skina1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/title"
    android:layout_below="@+id/title"
    android:layout_marginTop="35dp"
    android:background="@drawable/test_circle"
    android:clickable="true"
    android:focusable="true" />

</RelativeLayout>

Something I've missed?

Miletus answered 2/5, 2012 at 0:49 Comment(0)
A
6

It extends from View, not button, so it's not clickable or focusable by default. Adjust with

android:clickable="true"
android:focusable="true"

in your XML.

You can also set these in the constructor of your View class if you want to do it in java:

setFocusable(true);
setClickable(true);
Apodal answered 2/5, 2012 at 1:1 Comment(6)
Ah that makes sense. I'll try it after work. can I make the view clickable and focusable by default in my custom button class?Miletus
Yup- Those two lines in my answer are XML attributes. You would put them in your <custombuttons.CustomImageButton XML element just like android:background, android:id, etcApodal
oh sorry I mean can I override a method in my custom button src to make it clickable by default. so I don't need to add the lines in each of my xmls.Miletus
OH- Sorry. In the constructor for that View, you can call setFocusable(true) and setClickable(true).Apodal
Just tested it and still wont react...hmmm (sorry) added both to the xml and the java. Edited question to show changes. Is there some problem with the code to make the changes?Miletus
Don't know. Add some log statements to see if the view notices that it's being pressed. You probably need to add an OnClickListener and onFocusChangeListener if you haven't already.Apodal
R
6

in my case I was using a custom view with a constraint layout as the root .and I was not getting click events on setOnClickListener of my custom view,it turns out that I needed to set android:clickable="false" in the root of my xml for the custom view.apparently , the click event is dispatched to the root of my custom view xml rather than to the custom view it self (i.e setOnClickListener of the custom view )

Reber answered 4/3, 2021 at 14:12 Comment(2)
This has GOT to be a bug. It doesn't make sense to make your root clickable='false' to what...make it clickable. But thank you for getting it working for meFolacin
still actual. faced with same situation. thanks a lotLuby

© 2022 - 2024 — McMap. All rights reserved.