hleinone
hleinone

Reputation: 4480

How to add preference-like summary to RadioButton?

I'd like to have a summary in my RadioButton, kind of like there is on the CheckBoxPreference.

GPS satellites checkbox

I've tried to extend the RadioButton and override the onDraw method with something like this, but I'm stuck with all the calculations to make it lay out nicely.

@Override
protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  Paint paint = new Paint();
  int textSize = 20;
  int horizontalStartPosition = getCompoundPaddingLeft() + getCompoundDrawablePadding();
  int verticalStartPosition = getBaseline() + getLineHeight();
  paint.setTextSize(textSize);
  paint.setColor(Color.GRAY);
  paint.setAntiAlias(true);
  canvas.drawText(summary, horizontalStartPosition, verticalStartPosition, paint);
}

Which renders something like this:

RadioButton with summary

Is this really the way to go (doesn't feel like it is) or should I try something completely different?

Upvotes: 3

Views: 603

Answers (1)

hleinone
hleinone

Reputation: 4480

The solution is indeed to override the onDraw method. Here's how I ended up doing it.

On the constructor obtain the correct style attributes for the summary text.

public SummaryRadioButton(Context context, AttributeSet attrs) {
  super(context, attrs);
  TypedArray a = getContext().getTheme()
    .obtainStyledAttributes(
      attrs,
      new int[] { android.R.attr.textSize,
        android.R.attr.textColor },
      android.R.attr.textAppearanceSmall, 0);
  textSize = a.getDimensionPixelSize(0, 15);
  textColor = a.getColorStateList(1);
  paint = new Paint(getPaint());
  paint.setTextSize(textSize);
  a.recycle();
}

On the onDraw get the line height and the vertical position of the baseline and calculate the correct starting point for the summary text. Use the correct text color for the state of the radio button.

@Override
protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  if (summary != null && summary.length() > 0) {
    int horizontalStartPosition = getCompoundPaddingLeft()
        + getCompoundDrawablePadding();
    int verticalStartPosition = getBaseline() + getLineHeight();

    paint.setColor(textColor.getColorForState(getDrawableState(), 0));
    canvas.drawText((String) summary, horizontalStartPosition,
        verticalStartPosition, paint);
  }
}

Upon setSummary add an additional new-line to the text. This is a bit hacky but I couldn't figure out a better way to make the super class to position the text correctly.

public void setSummary(CharSequence summary) {
  if (summary != null && summary.length() > 0) {
    setText(getText() + "\n");
  } else {
    setText(getText());
  }
  if (summary == null && this.summary != null || summary != null
      && !summary.equals(this.summary)) {
    this.summary = summary;
  }
}

Thus, we need to override the getText as well and remove the new-line when the summary is present.

@Override
@CapturedViewProperty
public CharSequence getText() {
  CharSequence text = super.getText();
  if (summary != null && summary.length() > 0) {
    text = text.subSequence(0, text.length() - 1);
  }
  return text;
}

You'll end up with a nice looking radio button with a summary text. There might be problems though, with multi-line texts and summaries. Ideas for improvement in that sense are welcome.

Upvotes: 3

Related Questions