【问题标题】:Align top of image to top of TextView将图像顶部与 TextView 顶部对齐
【发布时间】:2012-05-03 06:51:43
【问题描述】:

我想创建一个布局,将图像的顶部与 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" 属性似乎只影响文本,而不影响可绘制对象。

【问题讨论】:

  • 我认为你需要使用 relativeLayout...
  • 无论你需要在顶部还是左侧
  • 正如@amp 所说,使用相对布局最好..
  • @Claes 你找到答案了吗?我也面临类似的问题
  • @user3265443 使用一个自定义 Drawable 来包装你的 Drawable。有关示例代码,请参阅我的答案:stackoverflow.com/a/28906636/710990

标签: android android-layout textview drawable vertical-alignment


【解决方案1】:

您可以通过创建一个包裹您的 Drawable 的自定义 Drawable 来将复合 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();
    }
}

【讨论】:

  • 很好的解决方案。这必须是公认的答案。
  • 如何使用它来对齐文本和左侧可绘制到 textview 的左侧
  • 我必须将gravityDrawable的下界设置为0:gravityCompoundDrawable.setBounds(0, 0, originalCompoundDrawable.getIntrinsicWidth(), 0);
  • 我不明白这是怎么被接受的答案。除非您还覆盖 getOpacity()、setAlpha(...) 和 setColorFilter(...),否则它不会编译。这 3 种方法的功能是什么?
  • @Tharkius 答案中省略了这些方法,因为它们与对齐问题无关,但是您是对的,当您创建自定义 Drawable 时需要实现它们,就像我们一样在这里做。在这种特定情况下,您可能会为每个方法 getOpacity()、setAlpha() 和 setColorFilter() 调用 mDrawable 字段上的相应方法。所以在getOpacity()中你会返回mDrawable.getOpacity(),在setAlpha()中你会调用mDrawable.setAlpha(..)等等。这些方法的含义你可以在Drawable的文档中找到。
【解决方案2】:

尝试使用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>

【讨论】:

  • CompoundDrawable 的要点是尽量减少视图层次结构中的视图数量。这个解决方案没有回答这个问题,即使它在视觉上看起来是一样的。
【解决方案3】:

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

【讨论】:

    【解决方案4】:
    <?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>
    

    这样就可以了。

    【讨论】:

      【解决方案5】:

      使用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>
      

      【讨论】:

        【解决方案6】:

        这对我有用:

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

        【讨论】:

          猜你喜欢
          • 2017-12-03
          • 1970-01-01
          • 2013-12-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-04
          相关资源
          最近更新 更多