【问题标题】:How to align drawableLeft to top instead center in android TextView?如何将drawableLeft对齐到顶部而不是在android TextView中居中?
【发布时间】:2014-10-25 13:13:24
【问题描述】:

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

有可能实现吗?

【问题讨论】:

  • 不简单。没有drawableTopLeft。所以,要实现你想要的,要么使用单独的 ImageView,要么制作一个扩展 TextView 的新控件。
  • 使用 BitmapDrawable.setGravity 方法,同时确保你的可绘制边界高度等于 textview 高度
  • @FrankN.Stein 你可能是对的。您能否详细说明一下自定义控件。
  • @Sharif 你的文本视图高度是多少?高度不变?
  • 这是一个广泛的论点。以下是 Lars Vogel 的解释:vogella.com/tutorials/AndroidCustomViews/article.html,这是官方参考:developer.android.com/guide/topics/ui/custom-components.html

标签: android textview


【解决方案1】:

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

字符串变量中多余的空格被图标替换。

【讨论】:

  • 可爱的解决方案。但是图标和文本的重要性不同。你有什么建议吗?
  • 尝试删除 TextView 上的 fontPadding。
【解决方案2】:

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

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(icon, null, null, null);

请记住,这只适用于 LEFTRIGHT 复合可绘制对象

【讨论】:

  • 你应该改用title.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
【解决方案3】:

my answer here

您可以通过创建一个包裹您的 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();
    }
}

【讨论】:

  • 如何使用它来对齐文本和左drawable到textview的左边
【解决方案4】:

如果您想要一个纯粹的 XML 解决方案,那么您可以使用 inset 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。

【讨论】:

  • 如果你要给我反对票,至少告诉我你为什么不喜欢这个解决方案。
  • 硬编码值不适用于动态文本。负偏移量取决于有多少行文本 + fontSizeTextView 的其他属性。不过对于单行来说,这是一个巧妙的技巧。
  • 没有downvote,但可能是他们的原因:引用:“您可能不得不根据您的场景使用插入值”=>这意味着对于具有动态长度的文本视图,它不是一个解决方案或至少不是最好的
【解决方案5】:

你可以这样做:

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

【讨论】:

    【解决方案6】:

    您可以通过这种方式使用。希望对你有帮助。

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

    【讨论】:

    • 我不想这样,因为这样我们必须使用嵌套布局。
    • 外面的RelativeLayout完全没用。并且fill_parent 已被弃用,因为包含 API 级别 8。请改用match_parent
    • @androidcodehunter 它要么是嵌套布局,要么是自定义代码,我们需要采取一些措施 :( 如果它相当不错,我总是更喜欢仅 XML 的解决方案,这是正确实现的(你可以解决它带有一个简单的水平LinearLayout)。顺便说一句,如果你使用ConstraintLayoutRelativeLayout,你甚至不需要嵌套,但它仍然是2个视图。
    【解决方案7】:

    试试这样:

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

    【讨论】:

      猜你喜欢
      • 2015-04-02
      • 2014-09-01
      • 2018-04-11
      • 2013-12-21
      • 2010-12-17
      • 2012-06-30
      • 1970-01-01
      • 2014-02-23
      • 2012-04-22
      相关资源
      最近更新 更多