I am learning Android and I cannot find the solution to a fragment instantiation error when they are in different flavors.
Setup:
I have a main fragment that is loaded into the main activity.
I have two favors: paid and free.
The main (common) part of the app doesn't have the fragment (layout + java files), I put them into the favors.
I get the following error when I try to run my program:
01-24 19:38:06.211 27417-27417/com.udacity.gradle.builditbigger.paid E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.udacity.gradle.builditbigger.paid, PID: 27417
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.udacity.gradle.builditbigger.paid/com.udacity.gradle.builditbigger.MainActivity}: android.view.InflateException: Binary XML file line #1: Binary XML file line #1: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: android.view.InflateException: Binary XML file line #1: Binary XML file line #1: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #1: Error inflating class fragment
Caused by: java.lang.NullPointerException
at java.lang.VMClassLoader.findLoadedClass(Native Method)
at java.lang.ClassLoader.findLoadedClass(ClassLoader.java:738)
at java.lang.ClassLoader.loadClass(ClassLoader.java:363)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at android.support.v4.app.Fragment.isSupportFragmentClass(Fragment.java:499)
at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:3637)
at android.support.v4.app.FragmentController.onCreateView(FragmentController.java:111)
at android.support.v4.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:338)
at android.support.v4.app.BaseFragmentActivityApi14.onCreateView(BaseFragmentActivityApi14.java:39)
at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:67)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:780)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:287)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:139)
at com.udacity.gradle.builditbigger.MainActivity.onCreate(MainActivity.java:14)
at android.app.Activity.performCreate(Activity.java:6975)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
I have tried many different versions of the fragment name because the error message tells me that the problem is with that, unfortunately none of them worked. Could you please help me to find the route cause of the issue (I mean not just the solution but why doesn't this work)? The code can be found on GitHub, but the relevant files are here:
src/java/com/udacity/gradle/builditbigger/MainActivity.java
package com.udacity.gradle.builditbigger;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void tellJoke(View view) {
new EndpointsAsyncTask().execute(this);
}
}
src/res/layout/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:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="#layout/fragment_main" />
src/free/java/com/udacity/gradle/builditbigger/free/MainActivityFragment.java
package com.udacity.gradle.builditbigger.free;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.udacity.gradle.builditbigger.R;
/**
* A placeholder fragment containing a simple view.
*/
public class MainActivityFragment extends Fragment {
public MainActivityFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_main, container, false);
AdView mAdView = (AdView) root.findViewById(R.id.adView);
// Create an ad request. Check logcat output for the hashed device ID to
// get test ads on a physical device. e.g.
// "Use AdRequest.Builder.addTestDevice("ABCDEF012345") to get test ads on this device."
AdRequest adRequest = new AdRequest.Builder()
.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
.build();
mAdView.loadAd(adRequest);
return root;
}
}
src/free/res/layout/fragment_main.xml
<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: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.udacity.gradle.builditbigger.MainActivity">
<TextView
android:id="#+id/instructions_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/instructions" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/instructions_text_view"
android:onClick="tellJoke"
android:text="#string/button_text" />
<com.google.android.gms.ads.AdView
android:id="#+id/adView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
ads:adSize="BANNER"
ads:adUnitId="#string/banner_ad_unit_id" />
</RelativeLayout>
src/paid/java/com/udacity/gradle/builditbigger/paid/MainActivityFragment.java
package com.udacity.gradle.builditbigger.paid;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.udacity.gradle.builditbigger.R;
/**
* A placeholder fragment containing a simple view.
*/
public class MainActivityFragment extends Fragment {
public MainActivityFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_main, container, false);
return root;
}
}
src/paid/res/layout/fragment_main.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: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.udacity.gradle.builditbigger.MainActivity">
<TextView
android:id="#+id/instructions_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/instructions" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/instructions_text_view"
android:onClick="tellJoke"
android:text="#string/button_text" />
</RelativeLayout>
Meanwhile, I found the solution. In src/res/layout/activity_main.xml you need to give the android:name attribute to the fragment in order to make it work. The name is the same in both flavors (MainActivityFragment), but the namespaces are different (free and paid). The only way to resolve this issue is that you need to move this layout file to the flavor parts of the application, and delete the original from the main part. Long story short, you have to delete the src/res/layout/activity_main.xml file, and add these two files to the project:
src/free/res/layout/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.udacity.gradle.builditbigger.free.MainActivityFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="#layout/fragment_main" />
src/paid/res/layout/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.udacity.gradle.builditbigger.paid.MainActivityFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="#layout/fragment_main" />
I am sorry for the original question, but I hope that it will be useful for someone.
Related
Hey guys I am a beginner in Android Develpoment. I am currently learning Navigation Components, but stuck in this app. I am setting listener to the button present in the activity_main.xml inside the FirstFragment.java and SecondFragment.java but my app crashes. I don't know what I am doing wrong.
Main Activity.java
package com.ahstore.inventory;
import android.os.Bundle;
import com.google.android.material.snackbar.Snackbar;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.fragment.NavHostFragment;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.ahstore.inventory.databinding.ActivityMainBinding;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private AppBarConfiguration appBarConfiguration;
private ActivityMainBinding binding;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
binding.fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
return NavigationUI.navigateUp(navController, appBarConfiguration)
|| super.onSupportNavigateUp();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:theme="#style/Theme.Inventory.AppBarOverlay"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:popupTheme="#style/Theme.Inventory.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<HorizontalScrollView
android:id="#+id/horizontalScrollView"
android:layout_width="409dp"
android:layout_height="50dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:scrollIndicators="none"
android:scrollbarAlwaysDrawHorizontalTrack="false"
android:scrollbarAlwaysDrawVerticalTrack="false"
android:scrollbars="none"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/appBarLayout">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:layout_weight="1"
android:text="Button" />
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:layout_weight="1"
android:text="Button" />
</LinearLayout>
</HorizontalScrollView>
<fragment
android:id="#+id/nav_host_fragment_content_main"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/horizontalScrollView"
app:navGraph="#navigation/nav_graph" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="#android:drawable/ic_input_add"
tools:ignore="SpeakableTextPresentCheck,SpeakableTextPresentCheck" />
</androidx.constraintlayout.widget.ConstraintLayout>
FirstFragment.java
package com.ahstore.inventory;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment;
import com.ahstore.inventory.databinding.FragmentFirstBinding;
public class FirstFragment extends Fragment {
private FragmentFirstBinding binding;
#Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
View view=inflater.inflate(R.layout.fragment_first,container,false);
return view;
}
public void onViewCreated(#NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Button button1=view.findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
NavHostFragment.findNavController(FirstFragment.this)
.navigate(R.id.action_FirstFragment_to_SecondFragment);
}
});
}
#Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
fragment_first.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".FirstFragment">
<ScrollView
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="First" />
</LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
SecondFragment.java
package com.ahstore.inventory;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment;
import com.ahstore.inventory.databinding.FragmentSecondBinding;
public class SecondFragment extends Fragment {
private FragmentSecondBinding binding;
#Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
View view=inflater.inflate(R.layout.fragment_second,container,false);
return view;
}
public void onViewCreated(#NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Button button=view.findViewById(R.id.button2);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
NavHostFragment.findNavController(SecondFragment.this)
.navigate(R.id.action_SecondFragment_to_FirstFragment);
}
});
}
#Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
fragment_second.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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/cl"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SecondFragment">
<TextView
android:id="#+id/textview_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="am second"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Error
2022-03-04 16:54:11.473 2392-2392/com.ahstore.inventory E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.ahstore.inventory, PID: 2392
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ahstore.inventory/com.ahstore.inventory.MainActivity}: android.view.InflateException: Binary XML file line #79 in com.ahstore.inventory:layout/activity_main: Binary XML file line #79 in com.ahstore.inventory:layout/activity_main: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3800)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3976)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2315)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:246)
at android.app.ActivityThread.main(ActivityThread.java:8550)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
Caused by: android.view.InflateException: Binary XML file line #79 in com.ahstore.inventory:layout/activity_main: Binary XML file line #79 in com.ahstore.inventory:layout/activity_main: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #79 in com.ahstore.inventory:layout/activity_main: Error inflating class fragment
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at com.ahstore.inventory.FirstFragment.onViewCreated(FirstFragment.java:35)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2987)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:546)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:112)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1647)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3128)
at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:3065)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2988)
at androidx.fragment.app.FragmentStateManager.ensureInflatedView(FragmentStateManager.java:392)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:281)
at androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(FragmentLayoutInflaterFactory.java:140)
at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:135)
at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:319)
at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:298)
at android.view.LayoutInflater.tryCreateView(LayoutInflater.java:1067)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:995)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:959)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1121)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
at android.view.LayoutInflater.inflate(LayoutInflater.java:680)
at android.view.LayoutInflater.inflate(LayoutInflater.java:532)
at com.ahstore.inventory.databinding.ActivityMainBinding.inflate(ActivityMainBinding.java:75)
at com.ahstore.inventory.databinding.ActivityMainBinding.inflate(ActivityMainBinding.java:69)
at com.ahstore.inventory.MainActivity.onCreate(MainActivity.java:32)
at android.app.Activity.performCreate(Activity.java:8198)
2022-03-04 16:54:11.474 2392-2392/com.ahstore.inventory E/AndroidRuntime: at android.app.Activity.performCreate(Activity.java:8182)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3773)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3976)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2315)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:246)
at android.app.ActivityThread.main(ActivityThread.java:8550)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
Here are a few points that will help you understand your issue better
Your activity and fragments have their own respective layout files (xmls)
View are bound within their layout files. Simply put, if an element with id, say A, is present in activity_main.xml, then it can only be accessed when the layout being inflated is activity_main.xml. If the contentView of your Activity is activity_main.xml, it will be able to access all Views inside the layout file.
In fragments, the layout is inflated in the onCreateView method, which returns the resulting View for the Fragment. The findViewById(id) method is called against that View object. The method will look for the View with the given id inside that View only. If it is able to find the View it will return it, else it will return null. Same goes for finding a View inside an Activity (you do not need to specify the View for an Activity as it will automatically reference the layout that is specified in setContentView).
Now that we have the above points cleared, we can see the issue that you are facing. Firstly, the buttons with ids button1 and button2 are in your activity_main.xml layout file. However you are trying to access these from your Fragment1 and Fragment2 classes. But your Fragment1 and Fragment2 classes have their own layout files which do not have the two buttons. So, when you try to retrieve the buttons (using findViewById), it returns null because the buttons are not present in the layout. You then try to set a click listener. Since, the button object is null, calling any method on it will result in a Null Pointer Exception being throw.
We now understand what you are doing wrong. Now, how do we fix this. First you need to understand what it is you want to achieve. In this case I would suggest that you move both buttons to the respective Fragment layouts i.e. the View with id button1 will go to Fragment1 and the View with id button2 will go to Fragment2. This should help resolve the NPE that you are facing.
Still there are some cases where a Fragment might want to access a View that is present in its parent Activity. One of the ways to do this would be to
Create a public method in your Activity class which returns a View with the given id.
public View getViewById(int id) {
return findViewById(id);
}
Use this method in your Fragment by doing so
((MainActivity) getActivity()).getViewById(R.id.button1)
Other approaches involve using Interfaces which I am sure you will learn about as you continue learning more.
Just to wrap things up, you have two ways to go about fixing your issue. Either move the buttons to the fragment layout files or create a public method to retrieve those views.
I am a beginner in android development and I have encountered some difficulty in running my app in the simulator. I am following chapter 12 of the head first textbook to design an app with tab navigation. It has four fragments and I am using the fragment pager adapter and tab layout to navigate through the app. When I run the app in the simulator it is crashed with the error message "app has stopped". My code for the main activity is as follows:
package com.hfad.bitsandpizzas;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import androidx.appcompat.widget.ShareActionProvider;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.MenuItemCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
public class MainActivity extends AppCompatActivity {
private ShareActionProvider shareActionProvider;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
SectionsPagerAdapter pagerAdapter =
new SectionsPagerAdapter(getSupportFragmentManager());
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(pagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(pager);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
MenuItem menuItem = menu.findItem(R.id.action_share);
shareActionProvider =
(ShareActionProvider) MenuItemCompat.getActionProvider(menuItem);
setShareActionIntent("Want to join me for pizza?");
return super.onCreateOptionsMenu(menu);
}
private void setShareActionIntent(String text) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, text);
shareActionProvider.setShareIntent(intent);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_create_order:
Intent intent = new Intent(this, OrderActivity.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 4;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new TopFragment();
case 1:
return new PizzaFragment();
case 2:
return new PastaFragment();
case 3:
return new StoresFragment();
}
return null;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return getResources().getText(R.string.home_tab);
case 1:
return getResources().getText(R.string.pizza_tab);
case 2:
return getResources().getText(R.string.pasta_tab);
case 3:
return getResources().getText(R.string.store_tab);
}
return null;
}
}
}
this is the xml file for main activity:
<?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="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.hfad.bitsandpizzas.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" >
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
this is the logcat (edited)
2020-06-05 10:16:13.812 17323-17323/com.hfad.bitsandpizzas E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.hfad.bitsandpizzas, PID: 17323
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.hfad.bitsandpizzas/com.hfad.bitsandpizzas.MainActivity}: android.view.InflateException: Binary XML file line #10: Binary XML file line #10: Error inflating class android.support.design.widget.AppBarLayout
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Caused by: android.view.InflateException: Binary XML file line #10: Binary XML file line #10: Error inflating class android.support.design.widget.AppBarLayout
Caused by: android.view.InflateException: Binary XML file line #10: Error inflating class android.support.design.widget.AppBarLayout
Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.design.widget.AppBarLayout" on path: DexPathList[[zip file "/data/app/com.hfad.bitsandpizzas-2/base.apk"],nativeLibraryDirectories=[/data/app/com.hfad.bitsandpizzas-2/lib/x86, /system/lib, /vendor/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at android.view.LayoutInflater.createView(LayoutInflater.java:609)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:787)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:727)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:858)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821)
at android.view.LayoutInflater.inflate(LayoutInflater.java:518)
at android.view.LayoutInflater.inflate(LayoutInflater.java:426)
at android.view.LayoutInflater.inflate(LayoutInflater.java:377)
at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:555)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:161)
at com.hfad.bitsandpizzas.MainActivity.onCreate(MainActivity.java:27)
at android.app.Activity.performCreate(Activity.java:6679)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.hfad.bitsandpizzas/com.hfad.bitsandpizzas.MainActivity}:
android.view.InflateException: Binary XML file line #10: Binary XML
file line #10: Error inflating class
android.support.design.widget.AppBarLayout
You are using AppBarLayout & TabLayout from support libraries while using androidx project,
so you need to replace android.support.design.widget.AppBarLayout with com.google.android.material.appbar.AppBarLayout
And replace android.support.design.widget.TabLayout with com.google.android.material.tabs.TabLayout
So, change your layout to be:
<?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="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.hfad.bitsandpizzas.MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
I'm new to android development, and I have been trying to use fragments, however, the app is crashing when I try to switch to landscape mode. I have been trying to use android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" android:windowSoftInputMode="adjustPan" in my application manifest, but it seems that the application just ignores it and keeps staying in portrait mode despite being in landscape until the app restarts.
Here is my code
main XML
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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"
tools:context=".MainActivity">
<fragment
android:id="#+id/fragment"
android:name="com.example.TopFrag"
android:layout_width="421dp"
android:layout_height="163dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.49"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<fragment
android:id="#+id/fragment2"
android:name="com.example.BottomFrag"
android:layout_width="413dp"
android:layout_height="568dp"
android:layout_marginTop="1dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.708"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/fragment" />
</androidx.constraintlayout.widget.ConstraintLayout>
//Main activity `
package com.example;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.FragmentManager;
import android.os.Bundle;
MainActivity
public class MainActivity extends AppCompatActivity implements TopFrag.TopHalfFragmentListener{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment myFragment = new TopFrag();
ft.replace(R.id.fragment,myFragment);
ft.commit();
}
#Override
public void handleClicks(int holder) {
}
}
Fragment 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:background="#color/topFrag"
tools:context=".TopFrag" >
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/btnUp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="88dp"
android:layout_marginEnd="71dp"
android:text="#string/minus"
app:layout_constraintEnd_toStartOf="#+id/btnDown"
app:layout_constraintHorizontal_bias="0.855"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/btnDown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="88dp"
android:layout_marginEnd="88dp"
android:text="#string/plus"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
Fragment.java
package com.example;
import android.os.Bundle;
import android.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
/**
* A simple {#link Fragment} subclass.
*/
public class TopFrag extends Fragment implements View.OnClickListener{
public TopFrag() {
// Required empty public constructor
}
Button up;
Button down;
int count =0;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View mv = inflater.inflate(R.layout.fragment_top, container, false);
up = mv.findViewById(R.id.btnDown);
down = mv.findViewById(R.id.btnUp);
up.setOnClickListener(this);
down.setOnClickListener(this);
return mv;
}
#Override
public void onClick(View v) {
if (up.isPressed()){
count= count+1;
}else if(count>0){
count= count -1;
}
TopHalfFragmentListener clickListner = (TopHalfFragmentListener) getActivity();
clickListner.handleClicks(count);
}
public interface TopHalfFragmentListener{
void handleClicks(int count);
}
}
Fragment 2 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:background="#color/bottomFragColor"
tools:context=".BottomFrag" >
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/txtOutput"
android:layout_width="31dp"
android:layout_height="13dp"
android:layout_marginTop="200dp"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
Fragment 2.JAVA
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {#link Fragment} subclass.
*/
public class BottomFrag extends Fragment {
public BottomFrag() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View mv = inflater.inflate(R.layout.fragment_bottom, container, false);
return mv;
}
}
The error i received..
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example, PID: 1096
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.example/com.example.MainActivity}: android.view.InflateException: Binary XML file
line #9: Binary XML file line #9: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4754)
at android.app.ActivityThread.-wrap18(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1599)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: android.view.InflateException: Binary XML file line #9: Binary XML file line #9: Error
inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #9: Error inflating class fragment
Caused by: java.lang.IllegalStateException: Fragment com.example.TopFrag did not create a view.
at android.app.FragmentManagerImpl.onCreateView(FragmentManager.java:3643)
at android.app.FragmentController.onCreateView(FragmentController.java:98)
at android.app.Activity.onCreateView(Activity.java:6187)
at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:389)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:780)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:469)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
at com.example.MainActivity.onCreate(MainActivity.java:22)
at android.app.Activity.performCreate(Activity.java:6975)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4754)
at android.app.ActivityThread.-wrap18(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1599)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Any help is much appreciated.
I am trying to get a LinearLayout to be added to the main Activity view when a button is pressed.
NOTE before trying this with merge I used LinearLayout with the same results. I read this post which made me thing merge would help.
The XML for the View I want to add looks like this.
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/grocery_list_row">
<EditText
android:hint="Price"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:hint="Item"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</merge>
The java for this View looks like so
package com.example.developer.grocerylist.impl;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import com.example.developer.grocerylist.R;
/**
* Created by developer on 8/16/2015.
*/
public class GroceryListTableRowImpl extends LinearLayout {
int mRows;
public GroceryListTableRowImpl(Context context) {
this(context, null);
}
public GroceryListTableRowImpl(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
public GroceryListTableRowImpl(Context context, AttributeSet attributeSet, int defStyles) {
super(context, attributeSet, defStyles);
}
public void addRow(){
mRows++;
removeAllViews();
for(int i = 0; i < mRows; i++){
addView(createRow());
}
}
private View createRow() {
View v;
LayoutInflater inflater = LayoutInflater.from(getContext());
v = inflater.inflate(R.layout.grocery_list_row,this,true);
return v;
}
}
The main Activity's XML looks like this
<TableLayout 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: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=".GroceryList"
android:id="#+id/list_table">
<com.example.developer.grocerylist.impl.GroceryListTableRowImpl
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/grocery_list">
</com.example.developer.grocerylist.impl.GroceryListTableRowImpl>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<DigitalClock
android:textSize="20pt"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
</TableRow>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="250px"
android:textSize="20pt"
android:paddingBottom="5px"
android:text=""
android:background="#777777"
android:textColor="#ff0000" />
<Button
android:id="#+id/add"
android:text="add" />
</TableRow>
</TableLayout>
Finally the main Activity's java
package com.example.developer.grocerylist.activities;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TableLayout;
import android.widget.TextView;
import com.example.developer.grocerylist.R;
import com.example.developer.grocerylist.api.GroceryListTableRow;
import com.example.developer.grocerylist.impl.GroceryListTableRowImpl;
public class GroceryList extends AppCompatActivity implements OnClickListener {
TextView textView = null;
GroceryListTableRowImpl groceryListTableRow = null;
Button add = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_grocery_list);
textView = (TextView)findViewById(R.id.textview);
groceryListTableRow = (GroceryListTableRowImpl)findViewById(R.id.grocery_list);
add = (Button)findViewById(R.id.add);
add.setOnClickListener(this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_grocery_list, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onClick(View v) {
groceryListTableRow.addRow();
}
}
When I boot up the App and click the button I get this
Process: com.example.developer.grocerylist, PID: 2353
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:3936)
at android.view.ViewGroup.addView(ViewGroup.java:3786)
at android.view.ViewGroup.addView(ViewGroup.java:3727)
at android.view.ViewGroup.addView(ViewGroup.java:3700)
at com.example.developer.grocerylist.impl.GroceryListTableRowImpl.addRow(GroceryListTableRowImpl.java:34)
at com.example.developer.grocerylist.activities.GroceryList.onClick(GroceryList.java:61)
at android.view.View.performClick(View.java:4780)
at android.view.View$PerformClick.run(View.java:19866)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
I know this is a lot to take in. I have been scratching my head on this one. I have never made a compound view before. That might be evident. Any help would be greatly appreciated. Thanks in advance!
UPDATE When debugging when I get to the addView(createRow()) line things fail. It does not seem to be making it into the createRow() method.
As per my observation inside your createRow() method change and try this thing
ViewGroup parent = (ViewGroup)v.Parent;
return parent
since you have used merge there is parent viewgroup, so either return parent view or remove the parent using
parent.RemoveView(v);
return v;
Thanks to #njkz2
What fixed this for me was changing my onCreate() method to this.
private View createRow() {
View v;
LayoutInflater inflater = LayoutInflater.from(getContext());
v = inflater.inflate(R.layout.grocery_list_row,this,false);
return v;
}
Also I changed the class to extend TableLayout instead of LinearLayout to get the desired effect. This is because I was added the compound view (which is a LinearLayout) to my GroceryListTableRowImpl. So GroceryListTableRowImpl needed to be a TableLayout.
I am trying to implement fragment tag, in my code so that I can use it with GoogleMap API. However just at the outset i am getting stuck because of an error "Binary XML File Line".
I tried searching it in the forum but I was not able to solve it.
Kindly help me understand this problem.
I am attaching all the files here my activity_main.xml
<LinearLayout 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="com.example.mapdemo.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
</LinearLayout>
My activity_map.xml file goes as
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:text="Loc:"
android:textSize="20sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
/>
<EditText
android:id="#+id/edt_locationName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|center_vertical"
android:ems="10"/>
<Button
android:id="#+id/btn_GetLocation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Go"
android:layout_gravity="right|center_vertical"
android:onClick="geoLocate"/>
</LinearLayout>
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</fragment>
</LinearLayout>
My main java file goes as
package com.example.mapdemo;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Log cat is as below :-
05-19 14:45:15.763: E/AndroidRuntime(28629): FATAL EXCEPTION: main
05-19 14:45:15.763: E/AndroidRuntime(28629): Process: com.example.mapdemo, PID: 28629
05-19 14:45:15.763: E/AndroidRuntime(28629): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.mapdemo/com.example.mapdemo.MainActivity}: android.view.InflateException: Binary XML file line #36: Error inflating class fragment
05-19 14:45:15.763: E/AndroidRuntime(28629): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2436)
05-19 14:45:15.763: E/AndroidRuntime(28629): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2498)
05-19 14:45:15.763: E/AndroidRuntime(28629): at android.app.ActivityThread.access$900(ActivityThread.java:179)
05-19 14:45:15.763: E/AndroidRuntime(28629): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1324)
In your MainActivity, add the following import statement
import android.support.v4.app.Fragment;
Edit: I'm not sure if this will work, but try changing your fragment tag to this
<fragment
android:id="#+id/map"
class="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</fragment>
try to put the fragment inside the linearLayout tag