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
There are several things wrong with your code:
First, the LayoutInflater.inflate()
method expects the id of a layout file in the form of R.layout.layout_name
and not in the form of R.id.some_id
:
TextView textView = (TextView) inflater.inflate(R.layout.textView, null);
Second, the code you use will throw a ClassCastException
because the root of the inflated layout is a LinearLayout
and not a TextView
as you try to cast it. Your code should be:
LinearLayout ll = (Linearlayout) inflater.inflate(R.layout.textView, null);
But even the line above will not work because, as its name suggest, a TextSwitcher
will take only children of type TextView
, nothing can come between the TextSwitcher
and the two TextView
children. The correct code to use will be in the end:
Layout for 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" />
And the viewFactory
field will be:
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;
}
};
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With