44

我想创建一个布局,将图像的顶部与 TextView 的顶部对齐,如下所示:

---------  Text text text text text text text
| Image |  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.

我尝试通过设置android:drawableLeft我的图像来做到这一点,但这会使图像垂直居中:

           Text text text text text text text
---------  text text text text text text text
| Image |  text text text text text text text
---------  text text text text text text text
           text text text text text.

这是否可能仅使用 TextView 或者我是否需要创建包含 TextView 和 ImageView 的 RelativeLayout?

这是我的 TextView 的 XML 布局,它给出了不正确的布局:

<TextView
    android:gravity="top"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:drawableLeft="@drawable/image"
    android:drawablePadding="8dp"
    android:text="@string/text" />

android:gravity="top"属性似乎只影响文本,而不影响可绘制对象。

4

6 回答 6

32

您可以通过创建一个包装您的 Drawable 的自定义 Drawable 来将一个复合 Drawable 与顶部(或底部)对齐,然后通过覆盖方法来操作您的自定义 Drawable 的绘图onDraw(Canvas)

下面的示例是最简单的示例。这会将图像与顶部对齐,但您也可以通过在 - 方法中实现所需的逻辑来使其与 TextView 的底部、左侧或右侧对齐onDraw(Canvas)。您可能还想在 中建立一个边距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();
    }
}
于 2015-03-06T19:57:29.487 回答
1

我认为,有一种比 3 个视图更简单、更快捷的方法。您需要为图标准备适当的 9patch,然后使用 FrameLayout。甚至可能只有一个 EditText/TextView使用与背景相同的可绘制对象。此答案中描述了更多详细信息。

于 2013-07-26T11:36:02.947 回答
1

尝试使用RelativeLayout......

<?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" >

    <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="fill_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/imageView1"
        android:text="@string/text" />

</RelativeLayout>
于 2012-04-23T04:26:01.977 回答
0
<?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" >

    <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="@string/text" />

</RelativeLayout>

这样就可以了。

于 2012-11-30T05:33:09.710 回答
0

使用layout_alignTop. 有了它,您可以将视图的顶部与另一个视图的顶部对齐

<?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" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/text" />

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@id/textView1"
        android:layout_toLeftOf="@id/textView1"
        android:src="@drawable/ic_launcher" />    

</RelativeLayout>
于 2014-02-20T08:05:24.837 回答
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()
                    }
                }
            }
        }
    }
}
于 2020-09-07T13:28:10.460 回答