- Repeat One.
- Repeat All.
- Repeat Off.
So we need to define xml attributes for:
- src_repeat_one => Source drawable to be shown for Repeat One.
- src_repeat_all => Source drawable to be shown for Repeat All.
- src_repeat_off => Source drawable to be shown for Repeat Off.
plus, we also need another xml attribute to set the current state:
repeat_state => which can be 0, 1 or 2 (off, on , all).
So lets create attr.xml in values folder of our android project.
Now, we will make Repeat button by extending the imageButton:
RepeatButton.xml:
public class RepeatButton extends ImageButton { private final int MAX_STATES=3;
int state;
Drawable srcRepeatOff;
Drawable srcRepeatOne;
Drawable srcRepeatAll;
int repeatState;
Context context;public RepeatButton(Context context) {
super(context);
this.context=context;}
public RepeatButton(Context context, AttributeSet attrs) {
super(context, attrs);
this.context=context;TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.RepeatButton);try {
repeatState = a
.getInteger(R.styleable.RepeatButton_repeat_state, 0);
srcRepeatOff = a
.getDrawable(R.styleable.RepeatButton_src_repeat_off);
srcRepeatOne = a
.getDrawable(R.styleable.RepeatButton_src_repeat_one);
srcRepeatAll = a
.getDrawable(R.styleable.RepeatButton_src_repeat_all);} catch (Exception e) {
} finally {
a.recycle();
}switch (repeatState) {
case 0:
this.setBackground(srcRepeatOff);
break;
case 1:
this.setBackground(srcRepeatOne);
break;
case 2:
this.setBackground(srcRepeatAll);
break;
default:
break;}
}@Override
public boolean performClick() {
super.performClick();
nextState();
setStateBackground();
return true;}
private void nextState() {
state++;if (state == MAX_STATES) {
state = 0;
}
}private void setStateBackground() {
switch (state) {
case 0:
this.setBackground(srcRepeatOff);
showButtonText(“Repeat Off”);
break;
case 1:
this.setBackground(srcRepeatOne);
showButtonText(“Repeat One”);
break;
case 2:
this.setBackground(srcRepeatAll);
showButtonText(“Repeat All”);break;
default:
break;}
}
public void showButtonText(String text) {Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
}
public REPEAT getRepeatState() {switch (state) {
case 0:
return REPEAT.OFF;
case 1:
return REPEAT.ONE;
case 2:
return REPEAT.ALL;
default:
return REPEAT.OFF;}
}public void setRepeatState(REPEAT repeatState) {
switch (repeatState) {
case OFF:
state=0;break;
case ONE:
state=1;
break;
case ALL:
state=2;
break;
default:
break;
}setStateBackground();
}
}
We retrieve xml attributes and set the imageButton values accordingly. PerformClick is called whenever user press the button, so we change the button state here. REPEAT is an enum define like this:
public enum REPEAT { OFF,ONE,ALL; }
getRepeatState and setRepeatState methods are not necessary and provided only to change button state programatically.
We have created all the necessary components of our custom button. Now lets use it in our layout, activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <sohail.aziz.samplebutton.RepeatButton android:id="@+id/btRepeat" android:layout_width="60dp" android:layout_height="40dp" android:layout_marginRight="100dp" android:padding="5dp" app:repeat_state="off" app:src_repeat_all="@drawable/repeat_enable" app:src_repeat_off="@drawable/repeat_disable" app:src_repeat_one="@drawable/repeat_enable_1" /> . . . . .
Pay attention to xmlns:app=”http://schemas.android.com/apk/res-auto” this is necessary for using custom attributes in your layouts. The layout (with three buttons, different states) will look like this:
Complete source code can be found here three-state-button .