Search code examples
androidandroid-layoutandroid-custom-view

Android: Issue creating Custom 3 state toggle button


I'm trying to create a 3 state toggle button by overriding the Button class.

Although, there is no error in the code, but Eclipse is showing following issue in layout xml.

The following classes could not be instantiated:

- com.example.threewaytoggle.TriToggleButton (Open Class, Show Error Log)
See the Error Log (Window > Show View) for more details.
Tip: Use View.isInEditMode() in your custom views to skip code when shown in Eclipse

And in the error log, this is coming:

com.example.threewaytoggle.TriToggleButton failed to instantiate.

java.lang.NullPointerException
at android.view.View.mergeDrawableStates(View.java:7506)
at com.example.threewaytoggle.TriToggleButton.onCreateDrawableState(TriToggleButton.java:42)
at android.view.View.getDrawableState(View.java:7410)
at android.view.View.setBackgroundDrawable(View.java:7583)....

Following is the code: Layout xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <com.example.threewaytoggle.TriToggleButton
        android:id="@+id/triToggleButton1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TriToggleButton" />
</LinearLayout>

Custom Button Class:

package com.example.threewaytoggle;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.Button;

public class TriToggleButton extends Button {

    int _state = 0;
    public TriToggleButton(Context context) {
        super(context);
        _state = 0;
        this.setText("1");
    }

    public TriToggleButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        _state = 0;
        this.setText("1");
    }

    public TriToggleButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        _state = 0;
        this.setText("1");
    }

    private final int[] STATE_ONE_SET = { R.attr.state_one };
    private final int[] STATE_TWO_SET = { R.attr.state_two };
    private final int[] STATE_THREE_SET = { R.attr.state_three };

    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        final int[] drawableState = super.onCreateDrawableState(extraSpace + 3);

        if (_state == 0) {
            mergeDrawableStates(drawableState, STATE_ONE_SET);
        } else if (_state == 1) {
            mergeDrawableStates(drawableState, STATE_TWO_SET);
        } else if (_state == 2) {
            mergeDrawableStates(drawableState, STATE_THREE_SET);
        }

        return drawableState;
    }

    @Override
    public boolean performClick() {
        nextState();
        return super.performClick();
    }

    private void nextState() {
        _state++;
        if (_state > 2) {
            _state = 0;
        }
        setButtonText();
    }

    private void setButtonText() {
        //TODO      
    }

    public int getState() {
        return _state;
    }
}

Solution

  • Found it....Only static was missing in:

    private static final int[] STATE_ONE_SET = { R.attr.state_one };
    private static final int[] STATE_TWO_SET = { R.attr.state_two };
    private static final int[] STATE_THREE_SET = { R.attr.state_three };
    

    But how come this creates a problem...?