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