Alinear 2 textos, 1 normal, 1 opuesto

Yo hago un Android aplicación con un botón donde hay un total de 4 textos y quiero alinear los primeros 2. Uno en el lado izquierdo más de la parte inferior del texto y el otro y el lado derecho del texto inferior.

Así que de esto:

antes de

setText(item.title + " " + item.roomId + "\n" + item.teacher + " " + item.classes);

A esto:

Después (esto es lo que quiero)

setText(declare here a spannable);

Creo que debo trabajar con Spannable , he probado algunas cosas con Alignment.ALIGN_NORMAL y Alignment.ALIGN_OPPOSITE pero creo que es primero debe calcular la longitud del texto inferior y luego hacer la alineación. (He encontrado un buen ejemplo aquí, pero no está funcionando en mi configuración).

Espero que alguien me pueda apuntar a una buena dirección.

Editar:

La razón por la que no puedo (creo) usar RelativeLayout o LinearLayout es que estoy extendiendo el botón en una clase diferente ( ScheduleItemView.java ):

 /** * Custom view that represents a {@link ScheduleItem} instance, including its * title and time span that it occupies. Usually organized automatically by * {@link ScheduleItemsLayout} to match up against a {@link TimeRulerView} * instance. */ public class ScheduleItemView extends Button { private ScheduleItem mItem; public ScheduleItemView(Context context, ScheduleItem item) { super(context); mItem = item; setSingleLine(false); setText(item.title + " " + item.roomId + "\n" + item.teacher + " " + item.classes); // TODO: turn into color state list with layers? int textColor = Color.WHITE; int accentColor = item.accentColor; LayerDrawable buttonDrawable = (LayerDrawable) context.getResources() .getDrawable(R.drawable.btn_block); buttonDrawable.getDrawable(0).setColorFilter(accentColor, PorterDuff.Mode.SRC_ATOP); buttonDrawable.getDrawable(1).setAlpha(item.containsStarred ? 255 : 0); setTextColor(textColor); setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources() .getDimensionPixelSize(R.dimen.text_size_small)); setGravity(Gravity.CENTER | Gravity.BOTTOM); setBackgroundDrawable(buttonDrawable); } public ScheduleItem getScheduleItem() { return mItem; } @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec( getMeasuredHeight(), MeasureSpec.EXACTLY)); // layout(getLeft(), getTop(), getRight(), getBottom()); setGravity(Gravity.CENTER); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getRight() - getLeft(), getBottom() - getTop()); } } 

He intentado hacer esto en protected void onLayout ( ScheduleItemsLayout.java ):

 child.setLayoutParams(new LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); 

Pero eso no funciona. No estoy seguro si debo utilizar new RelativeLayout(this) .

¿Es mejor utilizar Spannable en este caso?

El origen del proyecto se puede descargar aquí (que puede importar en Eclipse)

Bueno, si no puedes pasar de Button a ViewGroup , esto es lo que puedes hacer en tu clase extendida de Button:

Retirar:

 setText(item.title + " " + item.roomId + "\n" + item.teacher + " " + item.classes); 

Agregue lo siguiente al constructor ScheduleItemView's :

 float[] fl1 = new float[item.title.length()]; getPaint().getTextWidths(item.title, fl1); float[] fl2 = new float[item.roomId.length()]; getPaint().getTextWidths(item.roomId, fl2); float[] fl3 = new float[item.teacher.length() + item.classes.length() + 1]; getPaint().getTextWidths(item.teacher + " " + item.classes, fl3); float differenceInWidth = sumUpTheArray(fl3) - sumUpTheArray(fl1) - sumUpTheArray(fl2); float fSpaceArray[] = new float[1]; getPaint().getTextWidths(" ", fSpaceArray); int numOfSpaces = (int) (differenceInWidth / fSpaceArray[0]); char[] spaceCharArr = new char[numOfSpaces]; Arrays.fill(spaceCharArr, ' '); setText(item.title + String.valueOf(spaceCharArr) + item.roomId + "\n" + item.teacher + " " + item.classes); 

Agregue este método auxiliar que resume un array de float :

 public float sumUpTheArray(float[] arr) { float sum = 0f; for (int i = 0; i < arr.length; i++) { sum += arr[i]; } return sum; } 

No está seguro de por qué está sobreescribiendo los onDraw(Canvas) y onMeasure(int, int) .

Huelga decir que este es un fragmento de código complicado. Lo que pasa es que estamos midiendo cuánto espacio debemos poner entre title y roomId para obtener la alineación deseada. El código es sencillo (aunque cringe-digno), por lo que no se han incluido comentarios.

Por otro lado, puede extender RelativeLayout:

 public class ScheduleItemAlternateView extends RelativeLayout { private ScheduleItem mItem; public ScheduleItemAlternateView(Context context, ScheduleItem item) { super(context); mItem = item; int textColor = Color.WHITE; int accentColor = item.accentColor; LayerDrawable buttonDrawable = (LayerDrawable) context.getResources() .getDrawable(R.drawable.btn_block); buttonDrawable.getDrawable(0).setColorFilter(accentColor, PorterDuff.Mode.SRC_ATOP); buttonDrawable.getDrawable(1).setAlpha(item.containsStarred ? 255 : 0); // Three TextViews to hold the `title`, `roomId` // and `teacher&room` independently TextView tvTitle = new TextView(context); TextView tvRoomId = new TextView(context); TextView tvTeacherAndClasses = new TextView(context); // Example ids tvTitle.setId(100); tvRoomId.setId(101); tvTeacherAndClasses.setId(102); tvTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources() .getDimensionPixelSize(R.dimen.text_size_small)); tvRoomId.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources() .getDimensionPixelSize(R.dimen.text_size_small)); tvTeacherAndClasses.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources() .getDimensionPixelSize(R.dimen.text_size_small)); tvTitle.setPadding(30, 20, 30, 0); tvRoomId.setPadding(30, 20, 30, 0); tvTeacherAndClasses.setPadding(30, 5, 30, 20); tvTitle.setTextColor(textColor); tvRoomId.setTextColor(textColor); tvTeacherAndClasses.setTextColor(textColor); // Set text tvTitle.setText(item.title); tvRoomId.setText(item.roomId); tvTeacherAndClasses.setText(item.teacher + " " + item.classes); // LayoutParms RelativeLayout.LayoutParams paramsTitle = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); paramsTitle.addRule(RelativeLayout.ALIGN_LEFT, tvTeacherAndClasses.getId()); RelativeLayout.LayoutParams paramsRoomId = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); paramsRoomId.addRule(RelativeLayout.ALIGN_RIGHT, tvTeacherAndClasses.getId()); RelativeLayout.LayoutParams paramsTeacherAndClasses = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); paramsTeacherAndClasses.addRule(RelativeLayout.CENTER_HORIZONTAL); paramsTeacherAndClasses.addRule(RelativeLayout.BELOW, tvTitle.getId()); // Add Views to this RelativeLayout addView(tvTitle, paramsTitle); addView(tvRoomId, paramsRoomId); addView(tvTeacherAndClasses, paramsTeacherAndClasses); // Set the background as LayerDrawable setBackgroundDrawable(buttonDrawable); } } 

Aquí, creamos tres TextViews, y establecer su LayoutParams para obtener la alineación adecuada.

El resultado es el mismo para ambos, aunque yo recomendaría el segundo enfoque:

Introduzca aquí la descripción de la imagen

Una de las maneras más fáciles que he encontrado para lograr este tipo de comportamiento es tomar ventaja de la propiedad android layout_weight como así:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="30dp" android:background="@color/Orange" android:orientation="vertical" android:padding="20dp" > <LinearLayout android:layout_width="fill_parent" android:layout_height="match_parent" android:orientation="horizontal" > <TextView android:id="@+id/top_left_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="SCHK" /> <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" > </LinearLayout> <TextView android:id="@+id/top_right_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="G102" /> </LinearLayout> <TextView android:id="@+id/bottom_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="VIM M4O3WI, M404WI, M402SJ" /> </LinearLayout> 

De esta manera el LinearLayout con un peso de 1 ocupará el espacio necesario para separar correctamente las dos cadenas en la línea superior como se desee.

¿Por qué estás "extendiendo el botón en una clase diferente"? Si está haciendo esto simplemente para obtener la esquina redondeada / fondo naranja que se muestra en su pregunta, puede obtener este mismo efecto estableciendo el fondo de la disposición lineal de nivel superior a la del estilo del botón.

Utilice 3 TextViews dentro de RelativeLayout.

Para el title

  android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" 

Para roomId

  android:id="@+id/roomId" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" 

Para el teacher

  android:id="@+id/teacher" android:layout_below="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerHorizontal="true" android:layout_centerVertical="true" 
  • La mejor manera de obtener una SpannableString de un SpannableStringBuilder
  • Cómo agregar el radio de la esquina y el relleno al texto spannable de la multi-línea
  • El método draw () de ReplacementSpan no se llama
  • Establecer arrastrar audiencia en SpannableString
  • Cómo configurar la fuente personalizada para palabra en un texto TextView
  • ¿Hay alguna manera de insertar un ImageSpan en un TextView sin interrumpir el texto?
  • Android TextView formato de palabras múltiples
  • StringIndexOutOfBoundsException de SpannableStringInternal
  • Establecer una fuente y un color diferentes a parte de un TextView
  • Espaciado de párrafos con SpannableStringBuilder en TextView
  • Creación de softkey con emoji personalizado
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.