2

I am trying to create a subclass of Button. The code is as below

package com.comnet.bookshelf;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.Button;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;

public class myButton extends Button implements OnClickListener{
    Paint mainPaint;
    int colorArray[];
    int colorArrayAlt[];
    boolean touch=false;
    Rect bound;
    public myButton(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
        mainPaint=new Paint();
        bound=new Rect();
        defaultColorIndexArray();
    }

    public myButton(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        mainPaint=new Paint();
        bound=new Rect();
        defaultColorIndexArray();
    }

    public myButton(Context context)
    {
        super(context);
        mainPaint=new Paint();
        bound=new Rect();
        defaultColorIndexArray();
    }
    private void defaultColorIndexArray(){
        colorArray=new int[]{
        0xFFd28181, //1
        0xFFd48787,     //2
        0xFFd68d8d, //3
        0xFFd89292, //4
        0xFFda9898, //5
        0xFFdc9e9e, //6
        0XFFdea2a2, //7
        0XFFe0a8a8,     //8
        0xFFe2adad, //9
        0XFFe3b1b1, //10
        0XFFe4b4b4, //11
        0XFFe6b9b9, //12
        0XFFe7bdbd, //13
        0XFFe9c0c0, //14
        0XFFeac3c3, //15
        0XFFebc6c6, //16
        0XFFebc7c7, //17
        0XFFecc9c9, //18
        0XFFeccaca, //19
        0XFFeccaca,     //20
        0XFFeccbcb, //21
        0XFFeccbcb      //22
        };
        colorArrayAlt=new int[]{
        0XFFeccbcb, //22
        0XFFeccbcb, //21
        0XFFeccaca, //20
        0XFFeccaca, //19
        0XFFecc9c9, //18
        0XFFebc7c7, //17
        0XFFebc6c6, //16
        0XFFeac3c3, //15
        0XFFe9c0c0, //14
        0XFFe7bdbd, //13
        0XFFe6b9b9, //12
        0XFFe4b4b4, //11
        0XFFe3b1b1, //10
        0xFFe2adad, //9
        0XFFe0a8a8, //8
        0XFFdea2a2, //7
        0xFFdc9e9e, //6
        0xFFda9898, //5
        0xFFd89292, //4
        0xFFd68d8d, //3
        0xFFd48787, //2
        0xFFd28181  //1
        };
    }
    public void setButtonColorIndexArray(int carray[], int carray_alt[]){
    }
    @Override 
    protected void onDraw(Canvas canvasObject) {
        super.onDraw(canvasObject);
        int draw_color[];
        if(touch==false)
        draw_color=colorArray;
        else
        draw_color=colorArrayAlt;
        int width=canvasObject.getWidth();
        int height=canvasObject.getHeight();
        double colorcount=44;
        double divheight=height;
        double f=colorcount/divheight;

        double step=0;
        for(int i=0;i<height;i++,step+=f){
        int next=(int) Math.round(step);
        if(next>43) next=43;
        else if(next<0)next=0;
        if(next<22){
        mainPaint.setColor(draw_color[next]);
        canvasObject.drawLine(0, i, width, i, mainPaint);
        }
        else{
        mainPaint.setColor(draw_color[43-next]);
        canvasObject.drawLine(0, i, width, i, mainPaint);
        }
        //int color=;
        mainPaint.setColor(getCurrentTextColor());

        String str=this.getText().toString();
        //mainPaint.setColor(Color.WHITE); 
        mainPaint.setStyle(Style.FILL); 
        //canvasObject.drawPaint(mainPaint); 

        mainPaint.setColor(Color.BLACK); 
        mainPaint.setTextSize(20); 
        mainPaint.getTextBounds(str, 0, str.length(), bound);
        int x=(width-(bound.right-bound.left))/2;
        int y=(height+(bound.bottom-bound.top))/2;

        canvasObject.drawText(str, x, y, mainPaint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev){
        if(ev.getAction()==MotionEvent.ACTION_DOWN){
        //Log.i("Click", "ACTION_DOWN");
        touch=true;
        this.invalidate();
        }
        else if(ev.getAction()==MotionEvent.ACTION_UP){
        touch=false;
        this.invalidate();
        }

        return true;
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        Log.i("Clicked", "Clicked");
    }
}

Everything but one is working as I expected.

onClick is not responding at all. The code is as below:

((myButton)inflatedLayout.findViewById(R.id.DeleteButton)).setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        DeleteTheEntireBook();
    }
}); 

The button with default class is working fine

If you have any further question, let me know.

Nikolay Kostov
  • 16,433
  • 23
  • 85
  • 123
Popeye
  • 365
  • 3
  • 13

3 Answers3

2

The problem is You have overridden onTouchEvent.

Mark these words:

You should return false in your OnTouchListener then your OnClickListener will be also handled.

So you might think, I will just do my thing there and return false so I can receive clicks too. If you do so, it will work, but you wont be subscribed to other upcoming touch events (ACTION_MOVE, ACTION_UP) Therefore only option is to return true there, but then you wont receive any click events as we said previously.

So you need to perform the click manually in the ACTION_UP with performClick()

Tested and working code :

@Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            // Log.i("Click", "ACTION_DOWN");
            touch = true;
            this.invalidate();

        } else if (ev.getAction() == MotionEvent.ACTION_UP) {
            touch = false;
            this.invalidate();
            // KEY LINE
            performClick();
        }
        return true;


    }

Hope it helps ツ

SweetWisher ツ
  • 7,296
  • 2
  • 30
  • 74
  • Hello ツ。Thank you for your response. Your suggestion worked. You asked a question about the reason of handling onTouchEvent. Well, I have handled it because I want to change the look of the button on touch. That is the best way I have found so far. If you know better way, can you suggest me! Thanks. – Popeye Feb 03 '15 at 00:34
  • Yaa.. you can use [selector](http://stackoverflow.com/a/14024007/2591002) fr that . Itz an easy way :) You just need to convert your java code to XML, though it might be difficult :) Then you don't need onDraw as well as onTouch – SweetWisher ツ Feb 03 '15 at 03:57
  • @SweetWisherツ Well, this is just a beginning of somework that I want to achieve :). It is part of my learning. – Popeye Feb 03 '15 at 04:03
0

in the constructor, add the onClickListener, and no need to ((myButton)inflatedLayout.findViewB...

public myButton(Context context, AttributeSet attrs, int defStyle)
{
    super(context, attrs, defStyle);
    mainPaint=new Paint();
    bound=new Rect();
    defaultColorIndexArray();
    setOnClickListener(this);
}

then the overridden onClick in myButton class should be called once the button is clicked.

Yazan
  • 6,074
  • 1
  • 19
  • 33
0

View.OnClickListener :Interface definition for a callback to be invoked when a view is clicked. Can you use this Code:

((myButton)inflatedLayout.findViewById(R.id.DeleteButton)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
    DeleteTheEntireBook();
}

});

  • Hello, Rajapandiyan JJ, that was exactly what I did. I have imported the View.OnCickListener that is why I didn't write View.OnclickListener. But thanks for taking your time. – Popeye Feb 03 '15 at 00:29