1

I would like to set a background drawable (or resource) on a TextView, not taking into account its compound drawable width (and paddings).

Getting the width of the compound (left one to be more precise), and its paddings should not be a problem, but the setting of the background on the width of the textview minus the width of the compound drawable (described above).

Should you have any advice on doing that, please let me know.

Here's the needed result: separator

PS. I thought about having a horizontal LinearLayout with an ImageView and TextView as its children, and having the background set on the textview only, but I am interested in having the same result with less Views (in this case, exactly one), if it is possible.

DoruAdryan
  • 1,314
  • 3
  • 20
  • 35

1 Answers1

2

You could use a LayerDrawable which supports insets, for example:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:left="dimension" android:right="dimension">
        <shape android:shape="rectangle">
            <solid android:color="color" />
        </shape>
    </item>
</layer-list>

If you want to change your Drawable dynamically you're better off writing your own Drawable class. The following DividerDrawable for instance draws a line to a given padding onto a white background:

public class DividerDrawable extends Drawable {

    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private float mDensity;
    private int mPaddingLeft = 0;

    public DividerDrawable(Context context) {
        mPaint.setColor(Color.BLACK);
        mDensity = context.getResources().getDisplayMetrics().density;
    }

    @Override
    public void draw(Canvas canvas) {
        int width = canvas.getWidth();
        int height = canvas.getHeight();
        canvas.drawColor(Color.WHITE);
        canvas.drawRect(mPaddingLeft, height - mDensity, width, height, mPaint);
    }

    @Override
    public void setAlpha(int alpha) {

    }

    @Override
    public void setColorFilter(ColorFilter colorFilter) {

    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }

    public void setPaddingLeft(int paddingLeft) {
        if (mPaddingLeft != paddingLeft) {
            mPaddingLeft = paddingLeft;
            invalidateSelf();
        }
    }
}

To set the left padding based on your left CompoundDrawable you could do something like this:

private void setBackground(TextView textView, DividerDrawable background) {
    Drawable drawableLeft = textView.getCompoundDrawables()[0];
    int paddingLeft = drawableLeft != null ?
            textView.getPaddingLeft() + drawableLeft.getIntrinsicWidth() + textView.getCompoundDrawablePadding() :
            textView.getPaddingLeft();
    background.setPaddingLeft(paddingLeft);
    textView.setBackground(background);
}

To make good use of all this call it like so:

    DividerDrawable dividerDrawable = new DividerDrawable(this);
    TextView textView = (TextView) findViewById(R.id.text);
    setBackground(textView, dividerDrawable);
Markus Rubey
  • 5,153
  • 2
  • 21
  • 17
  • Thanks. I managed to do it with your help. I would ask you one more thing: Is there a method that's being called every time I'm setting (or changing its position) a drawable on the TextView (including from xml). ie: setCompoundDrawables / setCompoundDrawablesRelative, or do I need to override every single one and compute the new width and paddings ? – DoruAdryan Dec 22 '15 at 08:42
  • Sorry, but I don't quite follow you. If you call setCompoundDrawables() requestLayout() will be called to take care of changes (measuring, laying out, and drawing). What are you trying to achieve? – Markus Rubey Dec 22 '15 at 09:07
  • I mean where is the best place to add the left inset to the layerdrawable, so it would automatically change itself whenever the left drawable is visible / gone or placed somewhere else? As I tried to explain in my question, I need that grey line to not be displayed over the icon, but only over the text. – DoruAdryan Dec 22 '15 at 13:14
  • You could create a drawable for each state and switch between those, or maybe even write your own Drawable class. – Markus Rubey Dec 22 '15 at 13:44
  • I managed to do it by setting a background of an layer-list drawable with left-padding. I am interested in setting that left-padding of the layer-list drawable dynamically (whenever I set a left drawable or left padding on the TextView, the background (divider on top of the View) should shrink its width accordingly. Can you help me with that? – DoruAdryan Dec 24 '15 at 18:24