【问题标题】:android: fit height of DrawableLeft in a textViewandroid:在textView中适合DrawableLeft的高度
【发布时间】:2014-03-06 08:02:06
【问题描述】:

我试图在文本块旁边显示一条蓝线,就像这样:

这是我的代码:

<TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:drawableLeft="@drawable/blue_line" />

blue_line 是一个 jpg 文件。一个蓝色矩形。无论文本视图中的文本如何,它都会以原始大小显示。如何根据文本的高度动态调整其高度?比如文字少的时候变短,文字多的时候变长……

【问题讨论】:

  • 使用 QuoteSpan 或LeadingMarginSpan 之一
  • 我试过quotespan 看起来很棒,但是有什么办法可以增加线条的宽度吗?以及如何使用leadingmarginspan?
  • 我认为这可能是一个准确的解决方法:stackoverflow.com/a/59934868/6094503

标签: android drawable


【解决方案1】:

您可以尝试在代码中通过设置图像边界来实现

textView1.getViewTreeObserver()
        .addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            Drawable img = ActivityName.this.getContext().getResources().getDrawable(
                R.drawable.blue_line);
            img.setBounds(0, 0, img.getIntrinsicWidth() * textView1.getMeasuredHeight() / img.getIntrinsicHeight(), textView1.getMeasuredHeight());
            textView1.setCompoundDrawables(img, null, null, null);
            textView1.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
    });

【讨论】:

  • 在我的例子中,这个视图的父容器在创建时是 View.GONE。这会导致 getMeasuredHeight() == 0 并且图像的大小也为零。我已经通过使用 textView1.getLineHeight() 而不是 textView1 解决了这个问题。 getMeasuredHeight() 在这两种情况下。
  • 为什么一定要在“onGlobalLayout”中完成?而不仅仅是在第一次将图像设置为 compundDrawable 时在“onCreate”中?
  • @EladBenda 这需要在 OnGlobalLayoutListener 中完成,因为在绘制视图时会调用它,只有在绘制视图时才能获得正确的视图高度和宽度。在 onCreate 方法中,视图尚未绘制,因此您将得到高度和宽度为 0。
【解决方案2】:

最好的方法是将你的drawable包装在一个xml drawable文件中,并在你的文本视图中将它设置为一个drawable,如下所示:

可绘制的 XML 文件:

<?xml version="1.0" encoding="utf-8"?>
<bitmap 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:scaleType="fitXY"
    android:src="@drawable/total_calories"/>

XML 中的文本视图:

<TextView 
    android:id="@+id/title_total_cal"
    style="@style/title_stats_textview"
    android:drawableLeft="@drawable/total_calories_drawable"/>

【讨论】:

  • 你测试过这个吗?对我不起作用(虽然应用在按钮上)。图片仍被裁剪。
  • 用你的 xml 发布一个新问题
  • 也许你需要看看你的主题是否限制了这一点。大约 4 年前回答了这个问题,所以发生了很多变化。此外,按钮可能需要不同的 XML 覆盖来处理不同的按下状态。
  • @Shan Xeeshi 你尝试了什么?
  • 请记住,您不要使用另一个 XML 可绘制对象作为位图 XML 中的源可绘制对象。要使用此解决方案,您应该使用 PNG 或 JPG 绘图。
【解决方案3】:

尝试如下...

<RelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" >

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:src="@drawable/btndr" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/imageView" />

</RelativeLayout>

【讨论】:

    【解决方案4】:

    简单地说,将您的图像保持为 9patch 可绘制。

    您可以将android:drawableLeft="@drawable/checkmark" 添加到您的文本视图中。您还可以设置drawablePadding 以保持文本视图井井有条。

    android:drawableLeft="@drawable/button_icon"
    android:drawablePadding="2dip"
    

    这里是创建9patch的链接drawable

    <TextView android:text="@string/txtUserName" 
    android:id="@+id/txtUserName"
    android:layout_width="160dip"
    android:layout_height="60dip"
    android:layout_gravity="center"
    android:drawableLeft="@drawable/button_icon"
    android:drawablePadding="2dip"
    />  
    

    【讨论】:

    • 尝试设置普通的drawable,如果它被拉伸或挤压去9patch。 @Tekno Freek。
    【解决方案5】:

    不幸的是,setBounds 对我不起作用,所以我不得不做一个解决方法。

    // Turn wanted drawable to bitmap
    Drawable dr = getResources().getDrawable(R.drawable.somedrawable);
    Bitmap bitmap = ((BitmapDrawable) dr).getBitmap();
    
    // I had a square image with same height and width so I needed only TextView height (getLineHeight)
    int size = textView1.getLineHeight();
    Drawable d = new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(bitmap, size, size, true));
    textView1.setCompoundDrawables(d, null, null, null);
    
    // Now we can set some spacing between text and image
    textView1.setCompoundDrawablePadding(10);
    

    这不是关于性能的最佳解决方案,因为创建了新的位图,但仍然有效。

    【讨论】:

      【解决方案6】:

      您可以在可绘制画布上绘制一条具有所需高度的线,并将其设置为 TextView 的左侧可绘制对象。看看这个:

      public class FullHeightLineDrawable extends Drawable {
          private Paint mPaint;
          private int mHeight;
      
          public FullHeightLineDrawable(int height) {
              mPaint = new Paint();
              mPaint.setColor(CompatUtils.getColor(R.color.colorAccent));
              mPaint.setAntiAlias(true);
              mPaint.setStrokeWidth(15);
      
              mHeight = height;
          }
      
          @Override
          public void draw(Canvas canvas) {
              canvas.drawLine(0, -mHeight, 0, mHeight, mPaint);
          }
      
          @Override
          public void setAlpha(int alpha) {
          }
      
          @Override
          public void setColorFilter(ColorFilter colorFilter) {
          }
      
          @Override
          public int getOpacity() {
              return 0;
          }
      }
      

      用法:

      final Drawable drawable = new FullHeightLineDrawable(getHeight());
      mTextView.setTextColor(watchingColor);
      mTextView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
      

      【讨论】:

        【解决方案7】:

        我抽象出这个方法。当drawable位于TextView的左侧时,它可以工作,动态缩放。如果drawable在右边,这个方法不起作用,需要弄清楚原因,但是你可以直接使用textView.setcompounddrawableswithintrinsicbounds()和大小合适的Drawable资源

        @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
        public static void ajustCompoundDrawableSizeWithText(final TextView textView, final Drawable leftDrawable, final Drawable topDrawable, final Drawable rightDrawable, final Drawable bottomDrawable) {
            textView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
                @Override
                public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                   if(leftDrawable != null){
                       leftDrawable.setBounds(0, 0, (int)textView.getTextSize(), (int)textView.getTextSize());
                   }
                    if(topDrawable != null){
                        topDrawable.setBounds(0, 0, (int)textView.getTextSize(), (int)textView.getTextSize());
                    }
                    if(rightDrawable != null){
                        rightDrawable.setBounds(0, 0, (int)textView.getTextSize(), (int)textView.getTextSize());
                    }
                    if(bottomDrawable != null){
                        bottomDrawable.setBounds(0, 0, (int)textView.getTextSize(), (int)textView.getTextSize());
                    }
                    textView.setCompoundDrawables(leftDrawable, topDrawable, rightDrawable, bottomDrawable);
                        textView.removeOnLayoutChangeListener(this);
                }
            });
        }
        

        【讨论】:

          【解决方案8】:

          我创建了一个扩展 TextView 的类,并在 onPreDrawListener 中调整可绘制对象的大小。

          public class MyTextView extends AppCompatTextView {
          
              public MyTextView(Context context, AttributeSet attrs, int style) {
                  super(context, attrs, style);
                  fitCompoundDrawableToLineHeight();
              }
          
              private void fitCompoundDrawableToLineHeight() {
                  OnPreDraw.run(this, () -> {
                      final Drawable[] cd = getCompoundDrawables();
                      Arrays.stream(cd)
                          .filter(drawable -> drawable != null)
                          .forEach(d -> d.setBounds(0, 0, getLineHeight(), getLineHeight()));
                      setCompoundDrawables(cd[0], cd[1], cd[2], cd[3]);
                  });
              }
          }
          
          // Convenience class that abstracts onPreDraw logic
          public class OnPreDraw {
              public static void run(View view, Runnable task) {
                  view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                      @Override
                      public boolean onPreDraw() {
                          if (!view.getViewTreeObserver().isAlive()) {
                              return true;
                          }
                          view.getViewTreeObserver().removeOnPreDrawListener(this);
                          task.run();
                          return true;
                      }
                  });
              }
          }
          

          【讨论】:

            【解决方案9】:

            您需要制作一个水平的 XML 布局,左边有蓝线,右边有一个 textview。 比像项目一样使用该布局并制作这些项目的 ListView 。类似here,但更简单

            【讨论】:

              猜你喜欢
              • 2023-03-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-02-10
              • 1970-01-01
              • 2012-06-30
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多