如何将drawableLeft与top对齐而不是在android TextView中居?

时间:2014-09-01 10:18:42

标签: android textview

TextView我设置drawableLeft drawable从中心显示的位置。我需要将drawableLeftTextView内的顶部对齐,就像这张图片一样。

enter image description here

有可能实现这个目标吗?

7 个答案:

答案 0 :(得分:6)

请参阅my answer here

您可以通过创建包装Drawable的自定义Drawable将Compound-Drawable对齐到顶部(或底部),然后通过覆盖方法onDraw(Canvas)来操纵自定义Drawable的绘图。

以下示例是最简单的示例。这会将图像与顶部对齐,但您也可以通过在onDraw(Canvas) - 方法中实现所需的逻辑使其与TextView的底部,左侧或右侧对齐。您可能还希望在onDraw(Canvas)中建立边距,以使您的设计实现像素完美。

样本用法:

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);

示例代码:

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();
    }
}

答案 1 :(得分:4)

使用SpannableString和ImageSpan来实现这一目标。

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);

字符串变量中的额外空格将替换为图标。

答案 2 :(得分:4)

我认为它比上面的所有答案都更容易:你只需要这样做:

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();
    }
}

然后

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

请记住,这仅适用于 LEFT RIGHT 复合drawables

答案 3 :(得分:3)

如果您想要一个纯粹的XML解决方案,那么您可以使用插入drawable来重新定位您想要的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" />

您可能需要根据您的方案使用插入值。然后在TextView drawableLeft / Start定义中使用这个XML drawable。

答案 4 :(得分:0)

你可以这样做:

public class DrawableTopLeftTextView extends TextView {

    public DrawableTopLeftTextView(Context context) {
        super(context);
    }

    public DrawableTopLeftTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public DrawableTopLeftTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        if (!TextUtils.isEmpty(getText())) {

            Drawable[] drawables = getCompoundDrawables();

            if (drawables != null) {

                Drawable drawableLeft = drawables[0];

                if (drawableLeft != null) {

                    Paint.FontMetricsInt fontMetricsInt = getPaint().getFontMetricsInt();
                    Rect bounds = new Rect();
                    getPaint().getTextBounds((String) getText(), 0, length(), bounds);
                    int textVerticalSpace = Math.round(bounds.top - fontMetricsInt.top);
                    int offset = (getHeight() - drawableLeft.getIntrinsicHeight()) / 2 - textVerticalSpace - getPaddingTop() / 2;
                    drawableLeft.setBounds(0, -offset, drawableLeft.getIntrinsicWidth(), drawableLeft.getIntrinsicHeight() - offset);
                }
            }
        }
        super.onDraw(canvas);
    }
}

答案 5 :(得分:0)

尝试这样:

class MyTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null
) : AppCompatTextView(context, style) {
    private val leftDrawable = ContextCompat.getDrawable(context, R.drawable.checkmark)

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        setBulletPoint(compoundDrawables[0], canvas)
    }

    private fun setBulletPoint(drawableLeft: Drawable?, canvas: Canvas?) {
        if (!TextUtils.isEmpty(text)) {
            leftDrawable?.let { drlft ->
                if (lineCount == 1) {
                    setCompoundDrawablesWithIntrinsicBounds(drlft, null, null, null)
                } else {
                    val buttonWidth = drlft.intrinsicWidth
                    val buttonHeight = drlft.intrinsicHeight
                    val topSpace = abs(buttonHeight - lineHeight) / 2
           
                    drlft.setBounds(0, topSpace, buttonWidth, topSpace + buttonHeight)
                    canvas?.apply {
                        save()
                        drlft.draw(canvas)
                        restore()
                    }
                }
            }
        }
    }
}

答案 6 :(得分:-1)

你可以这样使用。愿它对你有帮助。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >

<RelativeLayout
    android:layout_width="fill_parent"
    android:layout_height="100dp"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true" >

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/imageView1"
        android:text=" Text Text Text Text Text Text Text Text Text Text Text Text 
        Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text   Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text" />
</RelativeLayout>