android - studio - textview drawable size
Android: ajuste la altura de DrawableLeft en un textView (9)
Estoy tratando de mostrar una línea azul al lado de un bloque de texto, más o menos así:
Aquí está mi código:
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/blue_line" />
blue_line es un archivo jpg. un rectángulo azul. se muestra en su tamaño original independientemente del texto en la vista de texto. ¿Cómo puedo ajustar su altura dinámicamente de acuerdo con la altura del texto? como hacerlo más corto cuando hay poca cantidad de texto y más largo cuando hay más texto ...
Creé una clase que amplía TextView
, y TextView
tamaño de los elementos onPreDrawListener
en 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;
}
});
}
}
Desafortunadamente, setBounds no me funcionaba, así que tuve que hacer una solución.
// 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);
No es la mejor solución con respecto al rendimiento porque se crea un nuevo mapa de bits, pero aún funciona.
Intenta lo siguiente ...
<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>
La mejor manera de hacerlo es envolver su dibujo en un archivo de dibujo XML y configurarlo como un dibujo en su vista de texto de la siguiente manera:
Archivo XML que se puede dibujar:
<?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"/>
TextView en XML:
<TextView
android:id="@+id/title_total_cal"
style="@style/title_stats_textview"
android:drawableLeft="@drawable/total_calories_drawable"/>
Necesita hacer un diseño XML horizontal que tenga la línea azul a la izquierda y una vista de texto a la derecha. Utilice ese diseño como un elemento y realice una vista de lista de esos elementos. Algo así, pero un poco más simple.
Puede dibujar una línea con la altura deseada en el lienzo dibujable y establecer como dibujable a la izquierda de su TextView. mira esto:
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;
}
}
Uso:
final Drawable drawable = new FullHeightLineDrawable(getHeight());
mTextView.setTextColor(watchingColor);
mTextView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
Puedes intentar hacerlo en código estableciendo límites para la imagen
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);
}
});
Simplemente, mantenga su imagen como 9patch drawable.
Puede agregar android:drawableLeft="@drawable/checkmark"
a su vista de texto. También puede configurar drawablePadding
para mantener la vista de texto organizada.
android:drawableLeft="@drawable/button_icon"
android:drawablePadding="2dip"
Aquí está el enlace para crear 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"
/>
Yo abstraigo este método. Funciona cuando el dibujable está a la izquierda de TextView, y se escala de forma dinámica. Si drawable está en el lado derecho, este método no funciona, ya que necesita averiguar por qué, pero puede usar directamente textView.setcompounddrawableswithintrinsicbounds()
con el recurso Drawable del tamaño correcto
@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);
}
});
}