Android - SupportMapFragment with GoogleMaps API 2.0 giving IllegalArgumentException - android

I am trying to use the latest Map API 2.0 provided for Android. I am using the Support Library as I want to support Android 2.2. Following is my code:
Main Activity class
public class MainActivity extends FragmentActivity {
public FragmentManager fManager ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fManager = getSupportFragmentManager();
Button showMapButton = (Button) findViewById(R.id.showMapButton);
showMapButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
loadMapFragment();
}
});
}
private void loadMapFragment() {
MapPageFragment plotterFragment = new MapPageFragment();
FragmentTransaction ft = fManager.beginTransaction();
ft.replace(R.id.allFragmentsFrameLayout, plotterFragment);
ft.addToBackStack(null);
ft.commit();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
Main Activity layout file
<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"
tools:context=".MainActivity" >
<Button
android:id="#+id/showMapButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Show Map"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_marginTop="30dp"
android:layout_alignParentTop="true" />
<FrameLayout
android:id="#+id/allFragmentsFrameLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentTop="true">
<!-- Put fragments dynamically -->
</FrameLayout>
</RelativeLayout>
Map Fragment Class
public class MapPageFragment extends SupportMapFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
return inflater.inflate(R.layout.map_fragment_layout, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
}
Map Fragment Layout
<?xml version="1.0" encoding="utf-8"?>
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="#+id/map"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
class="com.google.android.gms.maps.SupportMapFragment"
map:uiCompass="true"
map:mapType= "normal"
map:uiRotateGestures="true"
map:uiScrollGestures="true"
map:uiTiltGestures="true"
map:uiZoomControls="true"
map:uiZoomGestures="true" />
Android Manifest File
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mapfragmentexample"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />
<permission
android:name="com.plotter.permission.MAPS_RECEIVE"
android:protectionLevel="signature"/>
<uses-permission android:name="com.plotter.permission.MAPS_RECEIVE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="AIzaSyA5FtIeLQ1gGUihZIZPQVi3Yz_0l4NG9PY"/>
</application>
</manifest>
Everything is working fine for the first time. i.e. When I click on the Show Map button the map fragment gets loaded and displays the map. When I press back button, the map fragment is unloaded and I can see the Show Map button again.
I face an issue when I press the Show Map button again. I get the following error:
FATAL EXCEPTION: main
android.view.InflateException: Binary XML file line #2: Error inflating class fragment
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:699)
at android.view.LayoutInflater.inflate(LayoutInflater.java:468)
at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
at com.mapfragmentexample.MapPageFragment.onCreateView(MapPageFragment.java:17)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1460)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:911)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1444)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:429)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4503)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:809)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:576)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalArgumentException: Binary XML file line #2:
Duplicate id 0x7f040006, tag null, or parent id 0x0 with another fragment
for com.google.android.gms.maps.SupportMapFragment
at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:285)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:671)
... 18 more
I am not getting where I am getting wrong or missing anything.

You can fix this, if you delete all nested fragments in onDestroyView(). Don't know if it is a proper solution.
public void onDestroyView() {
super.onDestroyView();
Fragment fragment = (getFragmentManager().findFragmentById(R.id.map));
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.remove(fragment);
ft.commit();
}
And inflating them as usual in onCreateView()
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.map, container, false);
}

You need to use getChildFragmentManager() to add SupportMapFragment not not through xml.
For "why", see official documentation: http://developer.android.com/about/versions/android-4.2.html#NestedFragments
Take a look at my answer here: https://stackoverflow.com/a/15512285/2183804

You cannot inflate a layout into a fragment when that layout includes a fragment. Nested fragments are only supported when added to a fragment dynamically. More detail here!

Used this solution (similar to others):
public void onDestroyView() {
FragmentManager fm = getActivity().getSupportFragmentManager();
Fragment fragment = (fm.findFragmentById(R.id.map));
if (fragment.isResumed()) {
FragmentTransaction ft = fm.beginTransaction();
ft.remove(fragment);
ft.commit();
}
super.onDestroyView();
}
I had problems before using the if (fragment.isResumed).

I was facing the same issue in JakeWhartonViewPagerIndicatore along with SherlockFragments. Here is sample TestFragment with solved issue, thanks to Natalia for providing above solution. Your fragment may be a little different from mine.
Reference: Making ActionBarSherlock and ViewPagerIndicator play nice
Good Luck..!!
package com.example.vpiabstest;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.actionbarsherlock.app.SherlockFragment;
public class TestFragment extends SherlockFragment {
private String mContent = "???";
private String text;
private static final String KEY_TAB_NUM = "key.tab.num";
public static TestFragment newInstance(String text) {
TestFragment fragment = new TestFragment();
// Supply num input as an argument.
Bundle args = new Bundle();
args.putString(KEY_TAB_NUM, text);
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
text = getString(R.string.tab_page_num) + mContent;
View view = null;
if(text.contains("2")) {
view = inflater.inflate(R.layout.pinpoints_list, null);
} else if(text.contains("1")) {
view = inflater.inflate(R.layout.main_fragment_activity, null);
} else {
view = inflater.inflate(R.layout.activity_main, null);
((TextView)view.findViewById(R.id.text)).setText(text);
}
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContent = getArguments() != null ? getArguments().getString(KEY_TAB_NUM) : "???";
}
public void onDestroyView() {
super.onDestroyView();
// Your Programing skills goes here
if(text == null || !text.contains("1")) {
return;
}
// Do Not Miss this
try {
Fragment fragment = (getFragmentManager().findFragmentById(R.id.map_fragment));
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.remove(fragment);
ft.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
}

Use dialog.SetContentView() method in your activity's onCreate() cause when we tring to load.
Dialog again it loads only dialog not the whole activity life cycle and leads it to exception of Duplicate id.
Try it.

Try this
Maps fragment layout
<?xml version="1.0" encoding="utf-8"?>
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/map"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
map:uiCompass="true"
map:mapType= "normal"
map:uiRotateGestures="true"
map:uiScrollGestures="true"
map:uiTiltGestures="true"
map:uiZoomControls="true"
map:uiZoomGestures="true"
tools:context="the.package.name.of.mappagefragment.MapPageFragment" />
Map fragment class
public class MapPageFragment extends SupportMapFragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View rootView = super.onCreateView(inflater, container, savedInstanceState);
if (rootView == null)
{
rootView = inflater.inflate(R.layout.map_fragment_layout, container, false);
}
return rootView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
}
}

I used Natalia response but at times broke the application.
Use this one and it worked perfectly without breaking.
#Override
public void onDestroyView() {
try{
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.remove(nestedFragment);
transaction.commit();
}catch(Exception e){
}
super.onDestroyView();
}
https://stackoverflow.com/a/7953801/3364157

Fragment fragment = (getChildFragmentManager().findFragmentById(R.id.mapview));
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.remove(fragment);
ft.commit();
Use this saves the day.

Use intent flags:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
when calling main activity.

I had the same problem. Try adding ...
android:name="com.mapfragmentexample.MapPageFragment"
... to fragment in the layout file!

Related

Fragments won't change on Android application

Respected programmers of stack overflow,
I am very new to the world of programming and am actually trying to build an app to help my fellow medical students.
In my app I can't seem to be able to change fragments after pressing buttons on the navigation bar. Only a single fragment loads at first (home fragment) and the rest do not change at all.
Since I am new to the programming world it may just be a small mistake on my part, but I do hope you all can guide me.
Here is my MainActivity java file
public class MainActivity extends AppCompatActivity {
BottomNavigationView bnView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bnView=findViewById(R.id.bnView);
bnView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
int id=item.getItemId();
if (id==R.id.home) {
loadfrag(new Homefragment(), true);
}else if(id==R.id.subject_based) {
loadfrag(new subjectfragment(), false);
}else if(id==R.id.about) {
loadfrag(new aboutfragment(), false);
}else if(id==R.id.exam) {
loadfrag(new examfragment(), false);
}else {
loadfrag(new paperfragment(), false);
}
return true;
}
});
bnView.setSelectedItemId(R.id.home);
}
public void loadfrag(Fragment fragment, boolean flag){
FragmentManager fm=getSupportFragmentManager();
FragmentTransaction ft= fm.beginTransaction();
if (flag)
ft.add(R.id.container,fragment);
else
ft.replace(R.id.container,fragment);
ft.commit();
}
}
My main activity xml file is as follows;
<?xml version="1.0" encoding="utf-8"?>
<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"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#color/goojasto"
tools:context="com.cringyprithak.mcqrunch_3.MainActivity">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="?attr/actionBarSize"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bnView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#EFD115"
app:menu="#menu/nav_items" />
</RelativeLayout>
My menu is as follows
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/subject_based"
android:icon="#drawable/ic_sub"
android:title="Subject-wise"/>
<item
android:id="#+id/paper"
android:icon="#drawable/ic_paper"
android:title="Paper-wise"/>
<item
android:id="#+id/home"
android:icon="#drawable/ic_home"
android:title="Home"/>
<item
android:id="#+id/exam"
android:icon="#drawable/ic_exam"
android:title="Exam Practice"/>
<item
android:id="#+id/about"
android:icon="#drawable/ic_action_name"
android:title="About Me"/>
</menu>
and an example of the coding in my fragments would be
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class aboutfragment extends Fragment {
View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view= inflater.inflate(R.layout.fragment_homefragment, container, false);
return view;
}
}
I have been trying all day to make a bottom navigation bar and have fragments switch according to the buttons in the navigation bar but I haven't been able to.
I've watched countless videos and tried anything I could find. Please help me.
Your code is fine in general. It is the proper way to switch between Fragment by using BottomNavigationBar.
Just a small change for following function. You can directly use replace() when switching between Fragment:
// Removed the boolean flag and use replace() directly
public void loadfrag(Fragment fragment) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
// Can remove the add() function and just use replace()
ft.replace(R.id.container, fragment);
ft.commit();
}
So I guess the problem you encounter is when you try to load the view to your Fragment.
For your aboutfragment, you are trying to load R.layout.fragment_homefragment. And from the naming seems that it is a HomeFragment layout rather than your aboutfragment layout. You should have a your aboutfragment layout there:
public class aboutfragment extends Fragment {
View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Should replace R.layout.fragment_homefragment with your aboutfragment layout
view = inflater.inflate(R.layout.fragment_homefragment, container, false);
return view;
}
}
And for better practice, please follow Java Naming Convention when you are creating functions or classes.
For example:
Homefragment should be in HomeFragment
aboutfragment should be in AboutFragment

Running Fragment Transaction Stops the application as soon as it opens

If I remove the .commit() in the transaction the app compiles but shows an empty screen. If I add .commit() the app opens and closes instantly. I am new to fragments can anyone help resolve this. I have simply added an ImageView layout. Infalted it in Fragment class and hardcoded an image in it. Further I just created an instance of that Fragment in MainActivity.
My Android Studio version is: 3.1.3
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
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"
tools:context=".MainActivity">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="180dp"
android:id="#+id/head_container"
/>
</android.support.constraint.ConstraintLayout>
body_part_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/body_part_frag"
>
</ImageView>
BodyPartFragment.java
package com.example.musa.my_frag_app;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
public class BodyPartFragment extends Fragment {
public BodyPartFragment(){
//Do Nothing
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View rootView = inflater.inflate(R.layout.body_part_fragment, container);
ImageView body_image = rootView.findViewById(R.id.body_part_frag);
body_image.setImageResource(R.drawable.ic_launcher_background);
return rootView;
}
}
MainActivity.java
package com.example.musa.my_frag_app;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BodyPartFragment headfrag = new BodyPartFragment();
FragmentManager frag_m = getSupportFragmentManager();
frag_m.beginTransaction().add(R.id.head_container,headfrag).commit();
//frag_m.executePendingTransactions();
}
}
inflater.inflate(R.layout.body_part_fragment, container); will definitely throw an exception. The default for LayoutInflator.inflate() is attachToRoot=true. It should be false when called from onCreateView in a Fragment as this handles that for you. Change to inflater.inflate(R.layout.body_part_fragment, container, false);
add param for attachToRoot false
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View rootView = inflater.inflate(R.layout.body_part_fragment, container, false);
TextView body_text = rootView.findViewById(R.id.body_part_frag);
body_text.setText("Hello World");
return rootView;
}
Try This for fragment body part:
<android.support.constraint.ConstraintLayout
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">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/body_part_frag"/>
</android.support.constraint.ConstraintLayout>
Try like this:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
BodyPartFragment headfrag = new BodyPartFragment();
fragmentTransaction.replace(R.id.head_container, headfrag);
fragmentTransaction.commit();
change
View rootView = inflater.inflate(R.layout.body_part_fragment, container);
to
View rootView = inflater.inflate(R.layout.body_part_fragment, null);

Android: how do I access views (using findViewById) of an Activity from a Fragment onCreateView()?

I have a pretty simple project with an Activity that contains a Fragment. Only thing you may be unfamiliar with is that I am using a VideoEnabledWebView which isn't that complicated and is something I've used before. It's just a custom webview.
Here is my code:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- Don't forget the internet permission if you will be using the WebView to load remote content -->
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:hardwareAccelerated="true" > <!-- Only works in API level 11+, and allows the HTML5 videos to play in-line -->
<activity
android:name="name.cpr.ExampleActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
ExampleActivity.java
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import cpr.name.videoenabledwebview.R;
public class ExampleActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
Log.i("rai", "activity onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example);
}
}
activity_example.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"
tools:context=".ExampleActivity">
<!-- View that will be hidden when video goes fullscreen -->
<RelativeLayout
android:id="#+id/nonVideoLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment android:name="name.cpr.WebViewFragment"
android:id="#+id/webViewFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
<!-- View where the video will be shown when video goes fullscreen -->
<RelativeLayout
android:id="#+id/videoLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</RelativeLayout>
WebViewFragment.java
package name.cpr;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import cpr.name.videoenabledwebview.R;
public class WebViewFragment extends Fragment {
private VideoEnabledWebView webView;
private VideoEnabledWebChromeClient webChromeClient;
View rootView;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.root, container, false);
webView = (VideoEnabledWebView) rootView.findViewById(R.id.webView);
Log.i("rai", "nonVideoLayout = " + R.id.nonVideoLayout);
Log.i("rai", "videoLayout = " + R.id.videoLayout);
View nonVideoLayout = rootView.findViewById(R.id.nonVideoLayout);
if(nonVideoLayout == null){
Log.i("rai", "why is nonVideoLayout null?");
}
ViewGroup videoLayout = (ViewGroup) rootView.findViewById(R.id.videoLayout);
if(videoLayout == null){
Log.i("rai", "why is videoLayout null?");
}
webChromeClient = new VideoEnabledWebChromeClient(nonVideoLayout, videoLayout);
webView.setWebChromeClient(webChromeClient);
webView.loadUrl("http://m.youtube.com");
return rootView;
}
}
root.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="100dp"
android:layout_height="100dp"
android:text="the fragment"/>
<name.cpr.VideoEnabledWebView
android:id="#+id/webView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
I just can't get access to those two relative layouts in my Activity, I keep getting null.
Things I have tried that DON'T work:
rootView.findViewById //rootView is the return from the inflate
getActivity().findViewById
getView().findViewById
container.findViewById
I've also tried this in my fragments onCreate:
context = getActivity().getApplicationContext();
webViewFragmentId = context.getResources().getIdentifier(
"root", "layout", context.getPackageName());
webViewId = context.getResources().getIdentifier("webView", "id",
context.getPackageName());
nonVideoLayoutId = context.getResources().getIdentifier("nonVideoLayout", "id", context.getPackageName());
videoLayoutId = context.getResources().getIdentifier("videoLayout","id", context.getPackageName());
rootView = inflater.inflate(webViewFragmentId, null);
webView = (VideoEnabledWebView) rootView.findViewById(webViewId);
View nonVideoLayout = getActivity().findViewById(nonVideoLayoutId);
ViewGroup videoLayout = (ViewGroup) getActivity().findViewById(videoLayoutId);
webChromeClient = new VideoEnabledWebChromeClient(nonVideoLayout, videoLayout);
webView.setWebChromeClient(webChromeClient);
webView.loadUrl("http://m.youtube.com");
return rootView;
Update 2020-10-27
Now that onActivityCreated has been deprecated the documentation states you should instead register a LifecycleObserver to know when the Activity.onCreate() method has completed.
See this answer for an example.
Original Answer
You should override onActivityCreated and access the views you need from the activity in that method because when onCreateView is run in the fragment the activity has not yet had its layout set so you cannot access its views.
#Override
public void onActivityCreated (Bundle savedInstanceState) {
View nonVideoLayout = getActivity().findViewById(R.id.nonVideoLayout);
ViewGroup videoLayout = (ViewGroup) getActivity().findViewById(R.id.videoLayout);
...
}
You need to override onActivityCreated() as activity view is not created until this method is called .
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
View nonVideoLayout = ((MainActivity)getActivity()).findViewById(R.id.nonVideoLayout);
if(nonVideoLayout == null){
Log.e("rai", "why is nonVideoLayout null?");
}
else{
Log.e("rai", "view not null hurray");
}
View videoLayout = getActivity().findViewById(R.id.videoLayout);
if(videoLayout == null){
Log.e("rai", "why is videoLayout null?");
}else{
Log.e("rai", "view not null hurray");
}
You need to override onViewCreated. The views aren't created at the onCreate but are once the view is actually created. This post gives a little more information Difference between onCreateView and onViewCreated in Fragment
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
...
}

Can anyone solve my Android Fragment issue? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I need to pass Data From Activity to fragment.here below i have attached my code.please help me
This is My XML file
<?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="horizontal" >
<GridView
android:id="#+id/grdView_products_order"
android:layout_width="258dp"
android:layout_height="match_parent"
android:numColumns="3" >
</GridView>
<fragment
android:id="#+id/fragment1"
android:name="com.example.orderfree.order_screen.OrdersListFragment"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</LinearLayout>
I have extend Fragment at com.example.orderfree.order_screen.OrdersListFragment this class.like
public class OrdersListFragment extends Fragment {
.......
.......
}
And also i am extend Activity on MainActivity class.Like
public class MainActivity extends Activity{
private GridView productList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Fragment fr=new OrdersListFragment();
FragmentManager fm = getFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.fragment1, fr);
fragmentTransaction.commit();
productList = (GridView) findViewById(R.id.grdView_products_order);
productList.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// From Here i need to pass value to That Fragment
// Can you tell How to send Value to fragments Dynamically
}
});
}
Try this
package com.example.myfragments;
import android.os.Bundle;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.res.Configuration;
import android.view.WindowManager;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Configuration config = getResources().getConfiguration();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
/**
* Check the device orientation and act accordingly
*/
if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
/**
* Landscape mode of the device
*/
LM_Fragment ls_fragment = new LM_Fragment();
fragmentTransaction.replace(android.R.id.content, ls_fragment);
}else{
/**
* Portrait mode of the device
*/
PM_Fragment pm_fragment = new PM_Fragment();
fragmentTransaction.replace(android.R.id.content, pm_fragment);
}
fragmentTransaction.commit();
}
}
Create two fragment files LM_Fragement.java and PM_Fragment.java under com.example.mycontentprovider package.
Following is the content of LM_Fragement.java file:
package com.example.myfragments;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class LM_Fragment extends Fragment{
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
/**
* Inflate the layout for this fragment
*/
return inflater.inflate(
R.layout.lm_fragment, container, false);
}
}
Following is the content of PM_Fragement.java file:
package com.example.myfragments;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class PM_Fragment extends Fragment{
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
/**
* Inflate the layout for this fragment
*/
return inflater.inflate(
R.layout.pm_fragment, container, false);
}
}
Create two layout files lm_fragement.xml and pm_fragment.xml under res/layout directory.
Following is the content of lm_fragement.xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#7bae16">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/landscape_message"
android:textColor="#000000"
android:textSize="20px" />
<!-- More GUI components go here -->
</LinearLayout>
Following is the content of pm_fragment.xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#666666">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/portrait_message"
android:textColor="#000000"
android:textSize="20px" />
<!-- More GUI components go here -->
</LinearLayout>
Following will be the content of res/layout/activity_main.xml file which includes your fragments:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="horizontal">
<fragment
android:name="com.example.fragments"
android:id="#+id/lm_fragment"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<fragment
android:name="com.example.fragments"
android:id="#+id/pm_fragment"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
Make sure you have following content of res/values/strings.xml file:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">MyFragments</string>
<string name="action_settings">Settings</string>
<string name="hello_world">Hello world!</string>
<string name="landscape_message">This is Landscape mode fragment
</string>
<string name="portrait_message">This is Portrait mode fragment
</string>
</resources>
use getActivity() you can access protected and public methods.
Your Activity
public class MyActivity extends Activity {
private int data;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
data=125;
}
public int getMyIntVariable() {
return data;
}
}
Your Fragment
public class MyFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
MyActivity activity = (MyActivity)getActivity();
int i = activity.getMyIntVariable();
return view;
}
}
Suppose you want to send a string called clickstring.Then in the activity:
Bundle bundle=new Bundle();
bundle.putString("name1",clickstring );
fragment = new FragButton1();
fragment.setArguments(bundle);
where FragButton1 is your fragment.
Then in FragButton1:
String strtext=getArguments().getString("name1");
tv=(TextView)rootView.findViewById(R.id.tv_times1);
tv.setText(strtext);
I am recieving the data in a string strtext and displaying it in a textview.

Android ActionBarSherlock tabbed action bar with a mapview

I have 4 views, two of which contain mapviews. What I really want in the end is a tabbed navigation between these 4 views.
After some research, it seams like the best idea would be to use ActionBarSherlock and make each one of these views a "Fragment" inside a master "Main" Activity. This seams like a very easy to do thing but is causing me massive amounts of trouble (indeed, seams to be a pain for everyone from what I can find online).
First, my code.
ActivityMain.java
public class ActivityMain extends SherlockFragmentActivity
{
static String CLASS_NAME = "ActivityMain";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
Log.v(CLASS_NAME, "here");
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.createMenu();
}
public void createMenu()
{
this.getSupportActionBar().setDisplayShowHomeEnabled(false);
this.getSupportActionBar().setDisplayShowTitleEnabled(false);
this.getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
Tab tab1 = getSupportActionBar()
.newTab()
.setText("First tab")
.setTabListener(new MyTabListener<FragmentOne>(this, FragmentOne.class));
getSupportActionBar().addTab(tab1);
Tab tab2 = getSupportActionBar()
.newTab()
.setText("Second tab")
.setTabListener(new MyTabListener<FragmentTwo>(this, FragmentTwo.class));
getSupportActionBar().addTab(tab2);
}
public class MyTabListener<T extends Fragment> implements TabListener
{
private ActivityMain mActivity;
private Fragment mFragment;
private Class<T> mClass;
public MyTabListener(ActivityMain activity, Class<T> fragmentClass)
{
mActivity = activity;
mClass = fragmentClass;
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft)
{
if (mFragment == null)
{
mFragment = Fragment.instantiate(mActivity, mClass.getName());
ft.add(android.R.id.content, mFragment, null);
}
else
{
//ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.animationtest);
ft.attach(mFragment);
}
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft)
{
if (mFragment != null)
{
ft.detach(mFragment);
}
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft)
{
}
}
}
FragmentOne loads just fine, no problems on that one. FragmentTwo is where the trouble begins. Here is the files:
FragmentTwo.java
package com.test;
import com.actionbarsherlock.app.SherlockFragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class FragmentTwo extends SherlockFragment
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Log.v("Test", "Two!");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.two, container, false);
return view;
}
}
and the corresponding layout looks like this:
<?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" >
<com.google.android.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mapMapView"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="0.40"
android:clickable="true"
android:apiKey="MY_KEY"
/>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
style="#android:style/ButtonBar"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<Button
android:id="#+id/refreshButton"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:onClick="refreshSightings"
android:text="#string/A_MAP_REFRESH_BUTTON" />
</LinearLayout>
</LinearLayout>
Now of course this is giving me the error Binary XML file line #7: Error inflating class com.google.android.maps.MapView
I have tried importing the https://github.com/petedoyle/android-support-v4-googlemaps package and replacing the already existing android-support-v4 package but when I try to run my app, it dies with the error that it can't find the ActivityMain class.
First question, am I even going about this in the right way? Should I be using this 1 main activity and loading all the other things in Fragments?
Next, if I am doing this in a correct way, is there a good tutorial for how to get this to work in a decent way? I can't find anything online except for other people asking the same questions and a few tutorials that haven't worked for me.
Basically, how can I have tabbed navigation with 2 maps in 2 different tabs?

Categories

Resources