Instantly share code, notes, and snippets.
gipi/SegmentedButton.java
Created Oct 7, 2011
Customized Segmented button
/** | |
* Customization of the RadioButton in order to allow behaviour | |
* and appearance like the iOS ones. | |
* | |
* Inspired from http://blog.bookworm.at/2010/10/segmented-controls-in-android.html | |
*/ | |
import android.content.Context; | |
import android.content.res.TypedArray; | |
import android.graphics.drawable.GradientDrawable; | |
import android.graphics.Canvas; | |
import android.graphics.Color; | |
import android.graphics.Paint; | |
import android.graphics.Rect; | |
import android.graphics.Paint.Style; | |
import android.graphics.drawable.GradientDrawable; | |
import android.graphics.drawable.GradientDrawable.Orientation; | |
import android.util.AttributeSet; | |
import android.widget.RadioButton; | |
// a day read this | |
// http://kahdev.wordpress.com/2008/09/13/making-a-custom-android-button-using-a-custom-view/ | |
// copy from LabelView custom view example from sample code | |
public class SegmentedButton extends RadioButton { | |
private float mX; | |
private float mTextWidth; | |
private float mCurrentWidth; | |
private float mCurrentHeight; | |
private int mAscent; | |
private String mText; | |
private Paint mTextPaint; | |
private GradientDrawable mGradient = new GradientDrawable(Orientation.TOP_BOTTOM, new int[] { 0xffdcdcdc, 0xff111111 });; | |
private GradientDrawable mGradientChecked = new GradientDrawable(Orientation.TOP_BOTTOM, new int[] { 0xffa5a5a5, 0xff000000 });; | |
public SegmentedButton(Context context) { | |
super(context); | |
init(context, null, 0); | |
} | |
public SegmentedButton(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
init(context, attrs, 0); | |
} | |
/** | |
* This methods inits the style configuration. | |
* | |
* For some reason if not called explicitely the checking doesn't work. | |
*/ | |
protected void init(Context context, AttributeSet attrs, int defStyle) { | |
// retrieve text for the button | |
mText = getText().toString(); | |
mTextPaint = new Paint(); | |
mTextPaint.setAntiAlias(true); | |
mTextPaint.setTextSize(14); | |
mTextPaint.setColor(0xFF000000); | |
setPadding(3, 3, 3, 3); | |
TypedArray a = | |
context.obtainStyledAttributes( | |
attrs, | |
R.styleable.SegmentedButton, | |
defStyle, | |
0); | |
/* | |
* TODO: text align, padding, margin, text color etc... | |
*/ | |
final int N = a.getIndexCount(); | |
for (int i = 0; i < N; i++) { | |
int attr = a.getIndex(i); | |
switch (attr) { | |
case R.styleable.SegmentedButton_gradientNormal: | |
mGradient = (GradientDrawable)a.getDrawable(attr); | |
break; | |
case R.styleable.SegmentedButton_gradientChecked: | |
mGradientChecked = (GradientDrawable)a.getDrawable(attr); | |
break; | |
} | |
} | |
} | |
public SegmentedButton(Context context, AttributeSet attrs, int defStyle) { | |
super(context, attrs, defStyle); | |
init(context, attrs, defStyle); | |
} | |
@Override | |
public void onDraw(Canvas canvas) { | |
if (isChecked()) { | |
GradientDrawable grad = mGradient; | |
grad.setBounds(0, 0, this.getWidth(), this.getHeight()); | |
grad.draw(canvas); | |
} else { | |
GradientDrawable grad = mGradientChecked; | |
grad.setBounds(0, 0, this.getWidth(), this.getHeight()); | |
grad.draw(canvas); | |
} | |
Rect bounds = new Rect(); | |
mTextPaint.getTextBounds(mText, 0, mText.length(), bounds); | |
canvas.drawText(mText, -bounds.width()/2 + getWidth()/2, getPaddingTop() - mAscent, mTextPaint); | |
Paint paint = new Paint(); | |
paint.setColor(Color.BLACK); | |
paint.setStyle(Style.STROKE); | |
Rect rect = new Rect(0, 0, this.getWidth(), this.getHeight()); | |
canvas.drawRect(rect, paint); | |
} | |
/* | |
@Override | |
protected void onSizeChanged(int w, int h, int ow, int oh) { | |
android.util.Log.i("onSizeChanged", "miao"); | |
super.onSizeChanged(w, h, ow, oh); | |
mX = w * 0.5f; // remember the center of the screen | |
}*/ | |
@Override | |
public void onMeasure(int width, int height) { | |
android.util.Log.i("onMeasure", "width: " + width + " height: " + height); | |
mAscent = (int)mTextPaint.ascent(); | |
//setMeasuredDimension(getMeasurement(width, bounds.width()), getMeasuredHeight()); | |
setMeasuredDimension( | |
getMeasurement(width, (int)mTextPaint.measureText(mText)), | |
getMeasurement( | |
height, | |
(int)mTextPaint.descent()-mAscent+getPaddingTop() + getPaddingBottom()) | |
); | |
//setMeasuredDimension((int)mCurrentWidth, (int)mCurrentHeight); | |
//super.onMeasure(width, height); | |
} | |
private int getMeasurement(int measureSpec, int preferred) { | |
int specSize = MeasureSpec.getSize(measureSpec); | |
int measurement = 0; | |
switch(MeasureSpec.getMode(measureSpec)) { | |
case MeasureSpec.EXACTLY: | |
// This means the width of this view has been given. | |
measurement = specSize; | |
break; | |
case MeasureSpec.AT_MOST: | |
// Take the minimum of the preferred size and what | |
// we were told to be. | |
measurement = Math.min(preferred, specSize); | |
break; | |
default: | |
measurement = preferred; | |
break; | |
} | |
return measurement; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment