Loading a TextView from xml into a TextSwitcher

Viewed 5762

I've been trying to setup a TextSwitcher with the TextView loading in from an xml file. I have this basic TextSwitcher example that uses an empty TextView working ok:

.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>

But when I change the code to try and load a TextView from an xml file, it spits out a pile of errors. Here's the amended code:

.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>

Can anyone offer a suggestion where I'm going wrong? The code compiles ok but I'm sure it's with the LayoutInflater being misused in some way?


error messages (it didn't display the '11 more'):

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
4 Answers

Pretty simple using mostly XML.

In your XML add a TextSwitcher root view and two TextViews within it:

<TextSwitcher
    android:id="@+id/textswitcher_id"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentEnd="true"
    android:inAnimation="@android:anim/fade_in"
    android:outAnimation="@android:anim/fade_out">

    <TextView
        android:id="@+id/tv_onboarding_next"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Text1" />

    <TextView
        android:id="@+id/tv_onboarding_letsgo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Text2" />

</TextSwitcher>

Then in code, wherever you want the animation action to occur:

Using Kotlin:

textswitcher_id.setText(getString("Text2"))

// and somewhere else, switch it back:

textswitcher_id.setText(getString("Text1"))

Or in Java:

findViewById(R.id.textswitcher_id).setText(getString("Text2"));

// and somewhere else, switch it back:

findViewById(R.id.textswitcher_id).setText(getString("Text1"));

Note:

  • Within the XML you can also use two includes rather TextView twice, see: https://stackoverflow.com/a/42724239/1852191

  • The reason we have the default text in the XML even though we set it programmatically later is because on the first view it will be blank, until it's set

Related