How to align drawableLeft to top instead center in android TextView?

Use SpannableString and ImageSpan to achieve this.

String msg=" "+"haii";
ImageSpan mImageSpan== new ImageSpan(mContext, R.drawable.icon);
SpannableString text = new SpannableString(msg);
text.setSpan(mImageSpan, 0, 1, 0);
mTextView.setText(text);

the extra space in the string variable is replaced by the icon.


I think it's even easier than all the answers above: You only need to do this:

public class TopGravityDrawable extends BitmapDrawable {

    public TopGravityDrawable(Resources res, Bitmap bitmap) {
        super(res, bitmap);
    }

    @Override
    public void draw(Canvas canvas) {
        int halfCanvas = canvas.getHeight() / 2;
        int halfDrawable = getIntrinsicHeight() / 2;
        canvas.save();
        canvas.translate(0, -halfCanvas + halfDrawable);
        super.draw(canvas);
        canvas.restore();
    }
}

And then

 final Bitmap bitmap = BitmapFactory.decodeResource(mTitle.getResources(), R.drawable.icon);
 icon = new TopGravityDrawable(mTitle.getResources(), bitmap);
 title.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);

Remember this only works properly with LEFT and RIGHT compound drawables


See my answer here.

You can align a compound-Drawable to the top (or bottom) by creating a custom Drawable that wraps your Drawable, and then manipulate the drawing of your custom Drawable by overriding the method onDraw(Canvas).

The sample below is the simplest possible example. This aligns the image to the top, but you can also make it align to the bottom, left or right of the TextView by implementing the required logic in the onDraw(Canvas)-method. You might also want to build in a margin in the onDraw(Canvas), to make your design implementation pixel perfect.

Sample usage:

GravityCompoundDrawable gravityDrawable = new GravityCompoundDrawable(innerDrawable);
// NOTE: next 2 lines are important!
innerDrawable.setBounds(0, 0, innerDrawable.getIntrinsicWidth(), innerDrawable.getIntrinsicHeight());
gravityDrawable.setBounds(0, 0, innerDrawable.getIntrinsicWidth(), innerDrawable.getIntrinsicHeight());
mTextView.setCompoundDrawables(gravityDrawable, null, null, null);

Sample code:

public class GravityCompoundDrawable extends Drawable {

    // inner Drawable
    private final Drawable mDrawable;

    public GravityCompoundDrawable(Drawable drawable) {
        mDrawable = drawable;
    }

    @Override
    public int getIntrinsicWidth() {
        return mDrawable.getIntrinsicWidth();
    }

    @Override
    public int getIntrinsicHeight() {
        return mDrawable.getIntrinsicHeight();
    }

    @Override
    public void draw(Canvas canvas) {
        int halfCanvas= canvas.getHeight() / 2;
        int halfDrawable = mDrawable.getIntrinsicHeight() / 2;

        // align to top
        canvas.save();
        canvas.translate(0, -halfCanvas + halfDrawable);
        mDrawable.draw(canvas);
        canvas.restore();
    }
}

If you want a purely XML solution then you can use an inset drawable to re-position your desired drawable.

<?xml version="1.0" encoding="utf-8"?>
<inset
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/actual_image_to_be_shown"
    android:insetTop="-32dp" />

You might have to play around with the inset value depending on your scenario. Then just use this XML drawable in your TextView drawableLeft/Start definition.