Reputation: 18143
I have an application with Two Activities (MainActivity and WelcomeActividy) both extends from android.support.v4.app.FragmentActivity
WelcomeActivity uses a ViewFlipper for display Fragments (Step1, Step2, ..., StepN) in one Step uses a fragment list (CategoryStarredFragment) the WelcomeActivity no have problems
MainActivity uses a tabhost for display fragment too all work fine but when try to include a the same CategoryStarredFragment (works fine in WelcomeActivity) i get a exception
04-11 15:32:28.197: E/AndroidRuntime(16124): Caused by: java.lang.ClassNotFoundException: android.view.fragment in loader dalvik.system.PathClassLoader[/data/app/com.package.apk]
I'm thinking that is the implementation of the tabhost which is generating the problem
here's MainActivity.java
public class MainActivity extends FragmentActivity implements OnTabChangeListener {
private TabHost mTabHost;
private SparseArray<Class<?>> mSparseFragments = new SparseArray<Class<?>>(){{
put(R.id.tab_home, HomeFragment.class);
// other tabs
put(R.id.tab_settings, SettingsFragment.class);
}};
private SparseArray<String> mSparseTags = new SparseArray<String>(){{
put(R.id.tab_home, "home");
// other tabs
put(R.id.tab_settings, "settings");
}};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initTabs();
}
private void initTabs() {
mTabHost = (TabHost)findViewById(android.R.id.tabhost);
mTabHost.setup();
mTabHost.setOnTabChangedListener(this);
mTabHost.addTab(buildTabSpec("home", R.string.title_tab_home, R.layout.regular_home_fragment));
// other tabs
mTabHost.addTab(buildTabSpec("settings", R.string.title_tab_settings, R.layout.regular_settings_fragment));
}
@Override
public void onTabChanged(String tabId) {
Log.i(TAG, "Tab changed to: " + tabId);
final FragmentManager fm = getSupportFragmentManager();
final FragmentTransaction ft = fm.beginTransaction();
Fragment fragment;
int current = 0;
for (int i = R.id.tab_home; i <= R.id.tab_settings; i++) {
if(mSparseTags.get(i).equals(tabId)) {
current = i;
} else if(null != (fragment = fm.findFragmentByTag(mSparseTags.get(i)))) {
ft.detach(fragment);
}
}
if(null == (fragment = fm.findFragmentByTag(tabId))) {
try {
ft.add(current, (Fragment) mSparseFragments.get(current).newInstance(), tabId);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} else {
ft.attach(fragment);
}
ft.commit();
}
private TabSpec buildTabSpec(String tag, int labelId, int viewId) {
final View indicator = LayoutInflater.from(getApplicationContext())
.inflate(R.layout.tab, (ViewGroup) findViewById(android.R.id.tabs), false);
((TextView)indicator.findViewById(R.id.text)).setText(labelId);
return mTabHost.newTabSpec(tag)
.setIndicator(indicator)
.setContent(new TabContent(getApplicationContext(), viewId));
}
public class TabContent implements TabContentFactory {
private Context mContext;
private int mViewId;
public TabContent(Context context, int viewId) {
mContext = context;
mViewId = viewId;
}
@Override
public View createTabContent(String tag) {
Log.i(TAG, "Inflation tab content " + tag);
View view = LayoutInflater.from(mContext).inflate(mViewId, null);
return view;
}
}
}
Here is MainActivity layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<TabHost
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@android:id/tabhost">
<LinearLayout
android:orientation="vertical"
android:layout_height="fill_parent"
android:layout_width="fill_parent">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/ab_stacked_solid_mainbar">
</TabWidget>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_height="fill_parent"
android:layout_width="fill_parent">
<FrameLayout
android:id="@+id/tab_home"
android:layout_height="fill_parent"
android:layout_width="fill_parent"/>
<!-- Other tabs -->
<FrameLayout
android:id="@+id/tab_settings"
android:layout_height="fill_parent"
android:layout_width="fill_parent"/>
</FrameLayout>
</LinearLayout>
</TabHost>
</RelativeLayout>
Here is layout first tab
<?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/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/title_tab_home"
android:textSize="64sp"/>
<fragment
android:id="@+id/category_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_marginTop="18dp"
class="com.package.CategoryStarredFragment" />
</LinearLayout>
Upvotes: 0
Views: 9081
Reputation: 109
I had the same problem in a project I have been cleaning (you know, sometimes you start adding ideas to an application, but just many of them won't survive to the end and it is much better to erase the grease to avoid functionality and security problems ... you would be able to see better without the forest in front of your eyes).
After some hours looking at the problem, I fixed it in another place and returned to my original situation. In fact, the solution is very simple (as usual and it is related with clean coding practices).
(1) be 100% sure you are importing the right FragmentActivity:
import android.support.v4.app.FragmentActivity;
(2) check that your Activity extends from FragmentActivity
(3) check that your Fragment also extends from the right android.support.v4.app... Fragment
(4) that's all ... the regular code must work
@Override
public View onCreateView(
LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState
) {
View vFragmentView = inflater.inflate(R.layout.my_fragment, container);
return vFragmentView;
}
// other stuff
Tested with a Samsung Galaxy Fit (2.3.4) and a Kindle Fire HD (4.0).
Upvotes: 1
Reputation: 1007659
You are attempting to load a layout containing a <fragment>
tag, on an API Level 10 or lower device, from an Activity
instead of a FragmentActivity
.
Actually, in this case, it is a bit more subtle. You are attempting to use LayoutInflater.from()
. This is fine, but you cannot use it on API Level 10 or lower devices to interpret layout resource files with <fragment>
tags in them, as LayoutInflater
from back then had no idea what a <fragment>
tag was. You need to use the LayoutInflater
instance returned by getLayoutInflater()
on your FragmentActivity
, in order to interpret <fragment>
tags.
Upvotes: 8