I am trying to have few Tabs and within each tab I would like to have a list view that will lead me to another Fragment (another listview)
It crashes whenever I press one of the elements on the ListView in Android.java file.
Android.java
package com.example.tabs;
import java.util.ArrayList;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class Android extends Fragment {
private ArrayList<String> listOfElements;
private ListView trackView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View android = inflater.inflate(R.layout.android_frag, container, false);
trackView = (ListView) android.findViewById(R.id.android_list);
listOfElements = new ArrayList<String>();
listOfElements.add("Scott");
listOfElements.add("james");
listOfElements.add("mike");
TrackAdapter trackAdapter = new TrackAdapter(getActivity(), listOfElements);
trackView.setAdapter(trackAdapter);
trackView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// _mClickListener.onViewSelected(position, listOfTracks);
try {
Fragment videoFragment = new NestedAndroidFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.addToBackStack(null);
transaction.replace(android.getId(), videoFragment);
transaction.commit();
} catch (Exception e) {
Log.d("TabsApp", e.toString());
}
}
});
return android;
}
}
Here is how I started:
android_frag.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<ListView
android:id="@+id/android_list"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</ListView>
NestedAndroidFragment.java
package com.example.tabs;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class NestedAndroidFragment extends Fragment {
private ListView trackView;
public NestedAndroidFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.nested_frag, container, false);
trackView = (ListView) root.findViewById(R.id.nested_android_list);
return root;
}
/* private void destroyFragment() {
getChildFragmentManager().beginTransaction().hide(this).commit();
}*/
}
nested_fragment.xml (I put pretty much the same as for the android fragment - coulnd't find a good example for that)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<ListView
android:id="@+id/nested_android_list"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</ListView>
</FrameLayout>
Has anyone done something similar before? I would appreciate your help.
Here is the stacktrace
11-11 21:35:51.808: E/AndroidRuntime(28384): FATAL EXCEPTION: main 11-11 21:35:51.808: E/AndroidRuntime(28384): android.content.res.Resources$NotFoundException: Unable to find resource ID #0xffffffff 11-11 21:35:51.808: E/AndroidRuntime(28384): at android.content.res.Resources.getResourceName(Resources.java:2639) 11-11 21:35:51.808: E/AndroidRuntime(28384): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:919) 11-11 21:35:51.808: E/AndroidRuntime(28384): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104) 11-11 21:35:51.808: E/AndroidRuntime(28384): at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682) 11-11 21:35:51.808: E/AndroidRuntime(28384): at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1460) 11-11 21:35:51.808: E/AndroidRuntime(28384): at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:440) 11-11 21:35:51.808: E/AndroidRuntime(28384): at android.os.Handler.handleCallback(Handler.java:730) 11-11 21:35:51.808: E/AndroidRuntime(28384): at android.os.Handler.dispatchMessage(Handler.java:92) 11-11 21:35:51.808: E/AndroidRuntime(28384): at android.os.Looper.loop(Looper.java:137) 11-11 21:35:51.808: E/AndroidRuntime(28384): at android.app.ActivityThread.main(ActivityThread.java:5419) 11-11 21:35:51.808: E/AndroidRuntime(28384): at java.lang.reflect.Method.invokeNative(Native Method) 11-11 21:35:51.808: E/AndroidRuntime(28384): at java.lang.reflect.Method.invoke(Method.java:525) 11-11 21:35:51.808: E/AndroidRuntime(28384): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1187) 11-11 21:35:51.808: E/AndroidRuntime(28384): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003) 11-11 21:35:51.808: E/AndroidRuntime(28384): at dalvik.system.NativeStart.main(Native Method)
I see what you've done - you are trying to replace the contents of the view in android_frag.xml with an instance of NestedAndroidFragment. There are two errors that you have here actually - the crash is the first one. I'll explain the second one shortly.
What you are trying to do in the following line is wrong.
In fragments, you should be replacing the contents of a root level container with a fragment. What you are trying to do is ask fragment B to reside inside fragment A but replace all of A. Do you see how this paradigm is broken? You cannot ask B to reside inside A while at the same time replacing A. And this is the reason for your crash. Fixing this is pretty simple. In android_frag.xml, add an id attribute for the FrameLayout as follows:
Now go back to your Android.java and replace line where you make the replace transaction with:
This will fix the issue of your crash but this is where you will notice another issue - the contents of the videoFragment will overlay the contents of your ListView. The reason for this is that while using fragments, Android expects you to fill the containers as and when you need them. But you have a ListView defined in the xml. Once a widget is defined in xml, you cannot keep replacing it or removing it as you would with fragments. Once it is in xml, it will always be in every view where that xml is. The best design in your case would be to have your Android class extend a ListFragment and then take things from there (but this is only from looking at what you have put up now. I am not sure how this would interact with your other code and hence only take my statement as a suggestion if it works for you).
As a workaround to deal with what you have right now, you need to hide your ListView before replacing the with the fragment. Hence add this following line to your onItemClick() method.