I'm trying to follow the Udacity Developing Android Apps course. I got to Lesson 3.03. Here, we are instructed to launch a new Activity (DetailActivity) from ForecastFragment when clicking an item in a list.
However, I keep getting an error when attempting to launch the DetailActivity. Binary XML file line #1: Error inflating class fragment, where it's caused by DetailActivity.java in it's onCreate() method.
I've already searched around, but none of the fixes suggested for this issue helped me at all.
The specific error is:
Caused by: android.app.Fragment$InstantiationException: Trying to instantiate a class
com.myapp.sunshine.app.DetailActivityFragment that is not a Fragment
DetailActivity.java
public class DetailActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail); //failing here
}
}
DetailActivityFragment.java
public class DetailActivityFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_detail, container, false);
}
}
activity_detail.xml
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:id="#+id/fragment"
android:name="com.myapp.sunshine.app.DetailActivityFragment"
tools:layout="#layout/fragment_detail" android:layout_width="match_parent"
android:layout_height="match_parent" />
I should mention that I'm not using support libraries--as I'm targeting SDK 21+, Lollipop only.
This isn't the only fragment we've created in the course either. The other fragment we created looks identical to this one.
activity_main.xml
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:id="#+id/fragment"
android:name="com.myapp.sunshine.app.ForecastFragment"
tools:layout="#layout/fragment_main" android:layout_width="match_parent"
android:layout_height="match_parent" />
And for good measure, I'm including the ForecastFragment class. I've omitted unnecessary parts of code.
ForecastFragment.java
public class ForecastFragment extends Fragment {
private ArrayAdapter<String> mForecaseAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String[] forecastArray = {
"Today - Sunny - 88/63",
"Tomorrow - Foggy - 74/58",
"Sunday - Rainy - 65/59",
"Monday - Cloudy - 72/67"
};
final List<String> weekForecast = new ArrayList<>(Arrays.asList(forecastArray));
mForecaseAdapter = new ArrayAdapter<>(
getActivity(),
R.layout.list_item_forecast,
R.id.list_item_forecast_textview,
weekForecast);
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
final ListView listView = (ListView) rootView.findViewById(R.id.listview_forecast);
listView.setAdapter(mForecaseAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String forecast = mForecaseAdapter.getItem(position);
Intent detailActivityIntent = new Intent(getActivity(), DetailActivity.class)
.putExtra(Intent.EXTRA_TEXT, forecast);
startActivity(detailActivityIntent);
}
});
return rootView;
}
}
fragment_detail.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".DetailActivityFragment">
<TextView android:text="#string/hello_world" android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
which is nearly identical to
fragment_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivityFragment">
<ListView
android:id="#+id/listview_forecast"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center" />
</FrameLayout>
You should be using FragmentActivity instead of Activity
public class DetailActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail); //failing here
}
}
Related
I am new to android and have been following udacity's video lectures.
The list view is not getting populated by the array adapter and when
i ran the app on mobile the app showed only the main activity layout.
the list view is not appearing on the mobile screen ,can anyone tell me whats the error here,is it something related to frame layout or is there an
error in
array adapter.
Thanks in advance
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public static class PlaceHolderFragment extends Fragment {
private ArrayAdapter<String> mForecastAdapter;
public PlaceHolderFragment(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootview= inflater.inflate(R.layout.fragment_main, container, false);
String[] forecastArray={
"Today","Tommorow","wed","Thursday","Friday","Saturday","Sunday"
};//creating some fake data to show in list view
List<String> fore=new ArrayList<String>(Arrays.asList(forecastArray));
mForecastAdapter=new ArrayAdapter<String>(getActivity(),R.layout.list_item_forecast,R.id.list_item_forecast_textview,fore);
ListView listview= (ListView)rootview.findViewById(R.id.listview_forecast);
listview.setAdapter(mForecastAdapter);
return rootview;
}
}
}
activity_main_xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/container"
tools:context="com.saxenarc.jeetesh.layouts.MainActivity">
</FrameLayout>
list_item_forecast.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:id="#+id/list_item_forecast_textview"
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
>
</TextView>
fragment_main.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">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/listview_forecast"></ListView>
</FrameLayout>
Checked everything thrice before posting it.
Your code and list is working well but you haven't told the list where to be displayed. You can fix this in 2 ways.
First
Add the fragment inside the main activity since its not visible.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentManager.beginTransaction().replace(R.id.container, new PlaceHolderFragment).commit();
}
Second
Stop using the fragment and use the listview inside the Main activity
activity_main.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">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/listview_forecast"></ListView>
</FrameLayout>
MainActivity.java
List<String> fore = new ArrayList<String>(Arrays.asList(forecastArray));
mForecastAdapter = new ArrayAdapter<String>(this,R.layout.list_item_forecast,R.id.list_item_forecast_textview,fore);
ListView listview= (ListView) findViewById(R.id.listview_forecast);
listview.setAdapter(mForecastAdapter);
I'm really confused on what I've done with my code.
It's just a simple app using Fragments but I get below error :
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.sgrumo.sunshineonyourmind/com.example.sgrumo.sunshineonyourmind.MainActivity}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
This is my MainActivity class :
public class MainActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState==null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new MainActivityFragment()).commit();
}
}
Activity-main XML :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:ignore="MergeRootFrame"
tools:context="com.example.sgrumo.sunshineonyourmind.MainActivity">
I just wanted a Fragment inside my activity main, what's wrong with my code?
This is the Fragment class i use :
public class MainActivityFragment extends Fragment {
public MainActivityFragment() {}
String[] forecastArray = {
"Today - Sunny - 31/20",
"Tomorrow - Sunny - 42,30",
"Wednesday - Rainy - 20,15",
"Thursday - FINIMONDO - 35,20"
};
ArrayList<String> list = new ArrayList<>(Arrays.asList(forecastArray));
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),R.layout.list_item_forecast,R.id.list_item_forecast_textview,list);
ListView lw = (ListView)rootView.findViewById(R.id.listview_forecast);
lw.setAdapter(adapter);
return rootView;
}
And its XML :
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.sgrumo.sunshineonyourmind.MainActivityFragment"
tools:showIn="#layout/activity_main">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/listview_forecast"
android:layout_gravity="center" />
Please change the code as following in your onCreateView method
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
You missed to add false. Thanks.
Use getSupportFragmentManager().beginTransaction()
.replace(R.id.container, new MainActivityFragment()).commit() instead of getSupportFragmentManager().beginTransaction()
.add(R.id.container, new MainActivityFragment()).commit()
I get the following exception:
java.lang.IllegalArgumentException:
No view found for id 0x7f04001a (com.whatever:layout/fragment_main)
Looking at similar questions on SO:
One answer suggests using getChildFragmentManager() instead of getSupportFragmentManager().
This is not an option since MainActivity is not a Fragment.
Another answer suggests that fragment_main is not a child of activity_main, but I think I have that setup in activity_main.xml with tools:layout="#layout/fragment_main
Another suggests that setContent() has not been called, but I have that in onCreate()
What am I missing?
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void onStart() {
super.onStart();
// create fragment immediately
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.layout.fragment_main, new MainActivityFragment());
fragmentTransaction.commit();
boolean wereThereWereAnyPendingTransactions = fragmentManager.executePendingTransactions();
}
}
MainActivityFragment.java
public class MainActivityFragment extends Fragment implements Observer<String> {
public MainActivityFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
activity_main.xml
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragment"
android:name="com.whatever.MainActivityFragment"
tools:layout="#layout/fragment_main"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
fragment_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragment_main_table"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".MainActivityFragment">
<TextView
android:text="#string/fragment_main_xml"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
The answer with respect to code:
actvity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_frame_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:context=".MainActivity" >
</FrameLayout>
MainActivity.java:
...
fragmentTransaction.add(R.id.activity_frame_layout, new MainActivityFragment());
...
If you embed a Fragment inside of an Activity XML layout, you do not create it dynamically. The system does it for you. So there is no need to create the transaction and commit it, the Fragment will be created and added when you called setContentView().
Note that the tools:layout= line does not do anything at runtime. It is strictly for the tools to better link layouts and components together.
I found similar topics in stackoverflow but it didn't help for me.
I am showing google map using fragment and it crashes after get another fragment and come back.
In other words, google map shows only once and crashes.
Here are the codes.
public class MapTabMainFragment extends BaseFragment {
private AdView adView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = null;
try {
view = inflater.inflate(R.layout.fragment_map_main, container,
false);
} catch (Exception e) {
e.printStackTrace();
}
initComponents(view);
initValues();
initListeners();
return view;
}
public void initComponents(View view) {
adView = (AdView) view.findViewById(R.id.adView1);
}
public void initValues() {
AdRequest re = new AdRequest();
adView.loadAd(re);
}
public void initListeners() {
}
}
public class BaseFragment extends Fragment {
public BottomTabActivity mActivity;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivity = (BottomTabActivity) this.getActivity();
}
public boolean onBackPressed() {
return false;
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
}
}
when I try to catch the exception, it is
android.view.InflateException: Binary XML file line #20: Error inflating class fragment.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/lib/com.google.ads"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/WhiteColor"
android:orientation="vertical" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/header" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="#dimen/data_listview_margin_top" >
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="#dimen/data_listview_margin_bottom"
class="com.google.android.gms.maps.SupportMapFragment" />
<!--class="com.cyrilmottier.polaris2.maps.SupportMapFragment" -->
<com.google.ads.AdView
android:id="#+id/adView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
app:adSize="SMART_BANNER"
app:adUnitId="ca-app-pub-9766031373541061/3761995838"
app:loadAdOnCreate="true"
app:testDevices="TEST_EMULATOR, TEST_DEVICE_ID" >
</com.google.ads.AdView>
</RelativeLayout>
</LinearLayout>
You cannot have nested fragments in XML. You should do it in code.
The best way is to create a FrameLayout, and replace it with your fragment at run-time.
Suppose the XML is as follows:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/inquiryLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".InquiryFragment" >
<FrameLayout
android:id="#+id/contentFrame"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true" >
</FrameLayout>
</RelativeLayout>
Now the code is simple:
public class InquiryFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.inquiry_fragment, container, false);
Plan1Fragment frag = new Plan1Fragment();
getChildFragmentManager().beginTransaction()
.replace(R.id.contentFrame, frag).commit();
return v;
}
}
And that's it.
I've solved it myself after research on stackoverflow.
It's something related with nested fragment issues.
I removed map fragment in xml and placed frame for it and then add fragment programmatically.
it works like a charm.
Thanks for your all efforts.
// try this way
public class MapTabMainFragment extends FragmentActivity {
private AdView adView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_map_main);
adView = (AdView) findViewById(R.id.adView1);
AdRequest re = new AdRequest();
adView.loadAd(re);
}
}
You are trying to access the Activity before it's actually created in your BaseFragment class...
mActivity = (BottomTabActivity) this.getActivity();
Instead, override the "onActivityCreated" method and do it there...
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
mActivity = (BottomTabActivity) this.getActivity();
}
Edit your application's AndroidManifest.xml file, and add the following declaration within the element. This embeds the version of Google Play services that the app was compiled with.
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
->this solves mine.
Instead of putting xmlns:android="http://schemas.android.com/apk/res/android" in the Linear Layout tag, put it in <com.google.android.gms.ads.AdView tag. as shown below:
<com.google.android.gms.ads.AdView
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="#+id/adView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
app:adSize="SMART_BANNER"
app:adUnitId="ca-app-pub-9766031373541061/3761995838"
app:loadAdOnCreate="true"
app:testDevices="TEST_EMULATOR, TEST_DEVICE_ID" />
For further assistance visit this Link
I m trying to make a simple fragment example where one fragment will show an Article List and the other will show detailed article.
This is my main activity class-
public class ArticleFragment extends Activity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}// end class
This is the main layout file-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment android:name="com.example.ArticleList"
android:id="#+id/list"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<fragment android:name="com.example.ArticleDetails"
android:id="#+id/viewer"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
This is my two fragment class for ArticleList and ArticleDetails
public class ArticleList extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.articlelist, container, false);
}
public class ArticleDetails extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.articledetails, container, false);
}
}
I have also TWO XML layout files(containing a textview) for both articleList, ArticleDetails fragment. But the app has stopped working. What have I missed here? Pls help thanx.
Check your Package name inside the code
<fragment android:name="com.abc.def............./>
.Thanks to you I know that we can do it.