|
/** |
|
* 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; |
|
} |
|
} |