2012-07-22 10 views
5

He estado tratando de configurar un TextSwitcher con la carga de TextView desde un archivo xml. Tengo este ejemplo básico TextSwitcher que utiliza un TextView vacío trabajando bien:Cargando un TextView desde xml en un TextSwitcher

.java 

public class TextSwitcherTest extends Activity 
{ 
    private TextSwitcher textSwitcher; 

    private ViewFactory viewFactory = new ViewFactory() 
    { 
     public View makeView() 
     { 
      TextView textView = new TextView(TextSwitcherTest.this); 

      return textView; 
     } 
    }; 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 

     setContentView(R.layout.main); 

     textSwitcher = (TextSwitcher) findViewById(R.id.textSwitcher); 

     textSwitcher.setFactory(viewFactory); 

     Animation in = AnimationUtils.loadAnimation(this,android.R.anim.fade_in); 
     Animation out = AnimationUtils.loadAnimation(this,android.R.anim.fade_out); 

     textSwitcher.setInAnimation(in); 
     textSwitcher.setOutAnimation(out); 

     textSwitcher.setText("test ok"); 
    }  
} 

-

main.xml 

<?xml version="1.0" encoding="utf-8"?> 

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical" > 

    <TextSwitcher 
     android:id="@+id/textSwitcher" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" /> 

</LinearLayout> 

Pero cuando cambio el código para tratar de cargar un TextView desde un archivo XML, escupe una pila de errores. Aquí está el código modificado:

.java 

public class TextSwitcherTest extends Activity 
{ 
    private TextSwitcher textSwitcher; 

    private ViewFactory viewFactory = new ViewFactory() 
    { 
     public View makeView() 
     { 
      LayoutInflater inflater = LayoutInflater.from(TextSwitcherTest.this); 

      TextView textView = (TextView) inflater.inflate(R.id.textView,null); 

      return textView; 
     } 
    }; 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 

     setContentView(R.layout.main); 

     textSwitcher = (TextSwitcher) findViewById(R.id.textSwitcher); 

     textSwitcher.setFactory(viewFactory); 

     Animation in = AnimationUtils.loadAnimation(this,android.R.anim.fade_in); 
     Animation out = AnimationUtils.loadAnimation(this,android.R.anim.fade_out); 

     textSwitcher.setInAnimation(in); 
     textSwitcher.setOutAnimation(out); 

     textSwitcher.setText("test ok"); 
    }  
} 

-

textview.xml 

<?xml version="1.0" encoding="utf-8"?> 

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" > 

    <TextView 
     android:id="@+id/textView" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:text="@string/hello" /> 

</LinearLayout> 

¿Alguien puede ofrecer una sugerencia a dónde voy mal? El código compila bien, pero estoy seguro de que se trata de LayoutInflater mal utilizado de alguna manera?


mensajes de error (que no mostró la más '11 '):

07-22 03:51:24.096: W/dalvikvm(580): threadid=1: thread exiting with uncaught exception (group=0x409c01f8) 
07-22 03:51:24.137: E/AndroidRuntime(580): FATAL EXCEPTION: main 
07-22 03:51:24.137: E/AndroidRuntime(580): java.lang.RuntimeException: Unable to start activity ComponentInfo{test09.TextSwitcher01/test09.TextSwitcher01.TextSwitcherTest}: android.content.res.Resources$NotFoundException: Resource ID #0x7f050001 type #0x12 is not valid 
07-22 03:51:24.137: E/AndroidRuntime(580): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956) 
07-22 03:51:24.137: E/AndroidRuntime(580): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981) 
07-22 03:51:24.137: E/AndroidRuntime(580): at android.app.ActivityThread.access$600(ActivityThread.java:123) 
07-22 03:51:24.137: E/AndroidRuntime(580): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147) 
07-22 03:51:24.137: E/AndroidRuntime(580): at android.os.Handler.dispatchMessage(Handler.java:99) 
07-22 03:51:24.137: E/AndroidRuntime(580): at android.os.Looper.loop(Looper.java:137) 
07-22 03:51:24.137: E/AndroidRuntime(580): at android.app.ActivityThread.main(ActivityThread.java:4424) 
07-22 03:51:24.137: E/AndroidRuntime(580): at java.lang.reflect.Method.invokeNative(Native Method) 
07-22 03:51:24.137: E/AndroidRuntime(580): at java.lang.reflect.Method.invoke(Method.java:511) 
07-22 03:51:24.137: E/AndroidRuntime(580): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
07-22 03:51:24.137: E/AndroidRuntime(580): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
07-22 03:51:24.137: E/AndroidRuntime(580): at dalvik.system.NativeStart.main(Native Method) 
07-22 03:51:24.137: E/AndroidRuntime(580): Caused by: android.content.res.Resources$NotFoundException: Resource ID #0x7f050001 type #0x12 is not valid 
07-22 03:51:24.137: E/AndroidRuntime(580): at android.content.res.Resources.loadXmlResourceParser(Resources.java:2110) 
07-22 03:51:24.137: E/AndroidRuntime(580): at android.content.res.Resources.getLayout(Resources.java:857) 
07-22 03:51:24.137: E/AndroidRuntime(580): at android.view.LayoutInflater.inflate(LayoutInflater.java:394) 
07-22 03:51:24.137: E/AndroidRuntime(580): at android.view.LayoutInflater.inflate(LayoutInflater.java:352) 
07-22 03:51:24.137: E/AndroidRuntime(580): at test09.TextSwitcher01.TextSwitcherTest$1.makeView(TextSwitcherTest.java:23) 
07-22 03:51:24.137: E/AndroidRuntime(580): at android.widget.ViewSwitcher.obtainView(ViewSwitcher.java:80) 
07-22 03:51:24.137: E/AndroidRuntime(580): at android.widget.ViewSwitcher.setFactory(ViewSwitcher.java:99) 
07-22 03:51:24.137: E/AndroidRuntime(580): at test09.TextSwitcher01.TextSwitcherTest.onCreate(TextSwitcherTest.java:38) 
07-22 03:51:24.137: E/AndroidRuntime(580): at android.app.Activity.performCreate(Activity.java:4465) 
07-22 03:51:24.137: E/AndroidRuntime(580): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049) 
07-22 03:51:24.137: E/AndroidRuntime(580): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920) 
07-22 03:51:24.137: E/AndroidRuntime(580): ... 11 more 
+0

por favor agregue el "montón de errores" – Shine

+0

bien, ¡entonces lo siento, no los incluí antes! – Spoonface

Respuesta

14

Hay varias cosas mal con su código:

En primer lugar, el método LayoutInflater.inflate() espera que el ID de un archivo de diseño en forma de R.layout.layout_name y no en la forma de R.id.some_id:

TextView textView = (TextView) inflater.inflate(R.layout.textView, null); 

En segundo lugar, el código que use arrojará un ClassCastException porque la raíz del diseño inflado es LinearLayout y no TextView mientras intenta lanzarlo. Su código debe ser:

LinearLayout ll = (Linearlayout) inflater.inflate (R.layout.textView, null);

Pero incluso la línea anterior no funcionará porque, como su nombre sugiere, un TextSwitcher se llevará sólo a los niños de tipo TextView, nada puede interponerse entre el TextSwitcher y los dos TextView niños. El código correcto a utilizar estará en el final:

Disposición para textview.xml:

<?xml version="1.0" encoding="utf-8"?> 
<TextView 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/textView" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello" /> 

Y el campo viewFactory será:

private ViewFactory viewFactory = new ViewFactory() { 
     public View makeView() { 
      LayoutInflater inflater = LayoutInflater.from(TextSwitcherTest.this); 
      TextView textView = (TextView) inflater.inflate(R.layout.textView, null); 
      return textView; 
     } 
}; 
+0

hola, ahora lo entiendo. Gracias por su tiempo, ¡muy apreciado! – Spoonface

+0

si la vista de raíz fuera nula? –

+1

@DennisAnderson El usuario rootView debe ser nulo solo cuando no desee adjuntar la vista inflada a la vista raíz (básicamente cuando solo desea inflar un diseño sin asociarlo (en el momento del inflado) a otra vista). Eche un vistazo a la documentación del método inflate() que también toma un parámetro booleano 'https://developer.android.com/reference/android/view/LayoutInflater.html#inflate(org.xmlpull.v1.XmlPullParser, android .view.ViewGroup, boolean) ' – Luksprog

0

me ocurrió con esta solución , que para mí es lo más cercano a la definición de TextView directamente en el XML:

Primero, defina el TextSwitcher con dos TextView o bjects dentro de él, con su definición personalizada:

 <TextSwitcher 
      android:fontFamily="sans-serif-condensed" 
      android:id="@+id/detail_date_textswitch" 
      android:layout_height="wrap_content" 
      android:layout_width="match_parent"> 
      <TextView 
       android:id="@+id/detail_date_textview1" 
       android:textColor="@color/grey_700" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:textSize="20sp"/> 
      <TextView 
       android:id="@+id/detail_date_textview2" 
       android:textColor="@color/grey_700" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:textSize="20sp"/> 
     </TextSwitcher> 

Después de eso, en su código, definen los siguientes fábrica para su objeto TextSwitcher:

textSwitcher.setFactory(new ViewSwitcher.ViewFactory() { 
     boolean isFirst = true; 
     @Override 
     public View makeView() { 
      if (isFirst) { 
       isFirst = false; 
       TextView textView = (TextView) mDateView.findViewById(R.id.detail_date_textview1); 
       mDateView.removeViewAt(0); 
       return textView; 
      } else { 
       TextView textView = (TextView) mDateView.findViewById(R.id.detail_date_textview2); 
       mDateView.removeViewAt(0); 
       return textView; 
      } 
     } 
    }); 

no digo que no es un poco complicado, Pero funcionó para mí.

1

En realidad, no necesita establecer fábrica si coloca dos TextViews dentro de su TextSwitcher en formato XML. Esto funcionó para mí:

<TextSwitcher 
    android:id="@+id/id1" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:inAnimation="@android:anim/fade_in" 
    android:outAnimation="@android:anim/fade_out"> 

    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:lines="1"/> 
    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:lines="1"/> 
</TextSwitcher> 

(ninguna configuración adicional hecho en código, simplemente inflate y findViewById)

Sin embargo, usted tiene que duplicar los atributos de todo el TextViews. Esto puede evitarse moviendo el TextView al archivo por separado y luego incluyendo dos veces:

<TextSwitcher 
    android:id="@+id/id1" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:inAnimation="@android:anim/fade_in" 
    android:outAnimation="@android:anim/fade_out"> 

    <include layout="@layout/titlebar" /> 
    <include layout="@layout/titlebar" /> 
</TextSwitcher> 

Otra manera de evitar la duplicación sería la creación de un estilo personalizado y su aplicación a la vez TextViews.

+0

¡Bien hecho! Esta es la manera más limpia. – Josselin

Cuestiones relacionadas