2011-11-18 11 views
5

Estoy tratando de crear una barra de pestañas en Android usando un RelativeLayout y un RadioGroup que tiene un indicador que se deslizará para indicar el RadioButton activo dentro del RadioGroup.RelativeLayout: alinea la vista al hijo del grupo de vista hermano

Estos son botones de radio personalizados que son efectivamente rectángulos con un ícono sobre texto, todos los contenidos centrados, que usa un selector de estado personalizado para el fondo.

Aquí es mi jerarquía actual:

<RelativeLayout>  // Main view of the tab bar 
    <RadioGroup>   // The buttons 
    <RadioButton /> 
    <RadioButton /> 
    <RadioButton /> 
    </RadioGroup> 
    <ImageView />  // The indicator 
</RelativeLayout> 

La idea que tenía era cuando se hace clic en un botón de opción, me gustaría alinear el indicador a la & parte inferior parte superior del botón de opción seleccionado (y lo anime). Sin embargo, parece que layout_align<Edge> solo funciona con elementos hermanos, no con miembros de otro grupo de vista, es decir, puedo alinearme con el RadioGroup mismo, pero no con un RadioButton dentro de él.

Pensé en poner el indicador como miembro del RadioGroup, pero como RadioGroup es una extensión de LinearLayout, no parece haber una manera de colocarlo en el borde de un RadioButton dado.

¿Alguien puede pensar en cómo podría resolver este problema? ¿O tal vez hay una solución mejor que mi técnica de alineación animada al botón?

ACTUALIZACIÓN Con la ayuda de @superjos, logré resolver esto bastante bien.

Tuve que dar a cada botón una altura conocida en lugar de usar wrap_content (no es ideal, pero para este proyecto probablemente debería funcionar bien). Haga que la altura del indicador coincida con la de los botones. Asegúrese de que RadioGroup esté configurado para ajustar el contenido y centrado verticalmente en la vista principal. Establezca el indicador en alignTop y toRightOf RadioGroup. A continuación, haga clic en el botón para el oyente:

int prevY, newY; 
int prevButtonIndex, newButtonIndex; 

public void moveIndicator(button, indicator, index) { 
    prevY = newY; 
    newY = prevY + (index - prevButtonIndex) * button.getHeight(); 
    TranslateAnimation animation = new TranslateAnimation(0, 0, prevY, newY); 
    animation.setDuration(500); 
    animation.setFillAfter(true); // stay at final animation position 
    indicator.setAnimation(); 
    animation.start(); 
} 
+0

genial! ¡y la implementación también se ve bien! – superjos

Respuesta

1

Aquí está mi idea al respecto. Los siguientes son algunos pasos más detallados.

La idea es que ImageView tenga un hermano RadioGroup, como está en su muestra. El ImageView se encuentra inicialmente a la derecha del RadioGroup, y su línea media horizontal está alineada con la del primer RadioButton (o el que se elija).

Luego, con un clic de RadioButton, se crea/configura una TranslateAnimation en tiempo de ejecución para permitir que el ImageView cambie verticalmente hasta que su línea media se alinee con la del botón en el que se hizo clic. La animación se establece con fillAfter para mantenerse firme después de que se complete.

Pasos:

  • Cree sus recursos para que ImageView y RadioButtons tienen la misma altura, o bien trabajar con los acolchados verticales por lo que son el resultado de la misma altura.

  • Para alinear inicialmente el ImageView al primer RadioButton, algunos son suficientes XML podía: en ImageView adjuntar layout_toRightOf y layout_alignTop a la RadioGroup. Para tener en cuenta el relleno superior de RadioGroup, puede agregarlo al atributo XML de relleno superior de ImageView. O mejor como margen superior.

  • Cuando se hace clic en un RadioButton, cree una TranslateAnimation que se aplicará a ImageVew, cambiando solo la coordenada Y comenzando desde 0 hasta su destino hasta el valor Y (mientras que el atributo desde/hastaX será 0). Que es dada por una fórmula como:

    toY = (ClickedRadioButton.Index - LastClickedRadioButton.Index) * RadioButton.Heigth 
    

    Aquí Índice de es la posición ordinal de la RadioButton dentro del grupo (por ejemplo, de 0 a 2) (Advertencia: es decir pseudo-código, no necesariamente una existente Campo Java llamado , índice).

  • Aplica la animación al ImageView y enciéndelo.

+0

En su mayor parte, parece que podría ser la solución a usar. El algoritmo funciona en su mayor parte (aunque necesita establecer 'setFillAfter (true)' para hacer que se pegue), pero el uso de la coordenada de inicio 0 hace que la animación siempre comience desde el punto de partida original, no desde el punto de inicio actual. He intentado usar 'getTop()', 'getBaseline()', 'getLocation() [1]'. Pero esos no funcionan y hacen que el punto de partida sea la primera o la posición más baja. ¿Alguna idea de cómo adaptarse a esto? –

+0

Parece que el problema radica en que solo cambia la posición del dibujo. Para solucionar esto, aplico un cambio real layout_marginTop al indicador que es un desplazamiento basado en el botón marcado cuando finaliza la animación. Esto funciona bien, pero el único problema es que parpadea cuando termina de animar. ¿Hay alguna forma de animar simplemente un cambio en los parámetros de diseño? –

+0

Está el marco _new_ [animación de propiedad] (http://developer.android.com/guide/topics/graphics/prop-animation.html), que le permite animar muchas (¿todas?) Propiedades de vista, tipo de WPF/Enlace de propiedades de Silverlight a animaciones. Ha estado allí desde API 11, pero nunca lo he usado. – superjos

0

Se puede personalizar el estilo RadioButton para incluir una versión 9patched de la imagen indicador como fondo para el (podría ser comprobado para las radios ..) estado seleccionado. O bien, como dibujable

Sin embargo, depende de cómo quiera que se vea la animación.

Por ejemplo.

<style name="TabRadioButton" parent="@android:style/Widget.CompoundButton.RadioButton"> 
    <item name="android:background">@drawable/tab_bg</item> 
    <item name="android:drawableLeft">@drawable/tab_indicator</item> 
</style> 
+0

El indicador es básicamente un triángulo que apunta al centro del botón desde uno de los bordes, y se deslizará de un centro de borde de botón a otro en línea recta cuando se hace clic en el botón. No estoy seguro de que ponerlo como un drawable en el botón en sí me dé ese efecto. –

Cuestiones relacionadas