Add 2 of the Same Fragments to the Same Container - java

I'm trying to, as you can see in the title, add 2 of the same fragments to the same container. I'm using a fragmentransaction to add my fragment. It works the first time, but when I try to add a second fragment, the fragment is replaced.
Here's my addition code:
public void addNewCategoryFragment(Category c) {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
CategoryFragment categoryFragment = new CategoryFragment(c.name);
fragmentTransaction.add(R.id.fragment_root, categoryFragment, String.valueOf(c.getID()));
fragmentTransaction.commit();
}
Here's the xml that I'm trying to add the fragment to:
<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:background="#drawable/school"
android:orientation="vertical"
tools:context=".MainActivity" >
<LinearLayout
android:id="#+id/fragment_root"
android:layout_width="match_parent"
android:layout_height="413dp"
android:orientation="vertical" >
</LinearLayout>
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<Button
android:id="#+id/submit_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:text="Submit" />
<Button
android:id="#+id/new_category_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|left"
android:onClick="createNewCategory"
android:text="New Category" />
</FrameLayout>

at a glance the java looks fine, it could be the layout. without knowing the layout of your fragment it's hard to say but my guess is it is just being covered up. Try putting a ScrollView around them or setting isScrollContainer to true like this:
<LinearLayout
android:id="#+id/fragment_root"
android:layout_width="match_parent"
android:layout_height="413dp"
android:orientation="vertical"
android:isScrollContainer="true">
</LinearLayout>
i'd also replace the "fill_parent" values with "match_parent" in the rest of the layout because fill_parent is deprecated

Related

Fragment replaces entire screen

I have the following structures and fragment replace/add does not only replace its host view but whole screen. What can cause this?
Main Activity layout without data
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".activity.MainActivity">
<FrameLayout
android:id="#+id/nav_host_fragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="12"
app:defaultNavHost="true" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_nav"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="bottom"
android:layout_weight="1"
app:labelVisibilityMode="unlabeled"
android:background="#drawable/transparent_button"
app:onNavigationItemSelected="#{viewModel::onNavigationItemSelected}"
app:layout_behavior="#string/hide_bottom_view_on_scroll_behavior"
app:menu="#menu/bottom_navigation_menu" />
</LinearLayout>
Fragment layout
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?android:attr/actionBarSize"
tools:context=".fragment.HomeFragment">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="20dp"
android:background="#drawable/transparent_button"
android:onClick="#{viewModel::onFloatingButtonClicked}"
android:src="#drawable/ic_baseline_add_24" />
</FrameLayout>
Main activity onCreate
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
mainViewModel = ViewModelProviders.of(this, new ViewModelFactory(getApplication())).get(MainViewModel.class);
activityMainBinding.setViewModel(mainViewModel);
activityMainBinding.executePendingBindings();
fragmentList.put(FragmentsEnum.HOME.getValue(), new HomeFragment());
fragmentList.put(FragmentsEnum.PROFILE.getValue(), new ProfileFragment());
Fragments.addFragment(getSupportFragmentManager(), R.id.nav_host_fragment, fragmentList.get(FragmentsEnum.HOME.getValue()), FragmentsEnum.HOME.getValue()); // DEFAULT FRAGMENT
}
Fragments util
public static void addFragment(FragmentManager manager, int containerId, Fragment fragment, String tag) {
if (!manager.isStateSaved()) {
manager.beginTransaction().add(containerId, fragment, tag).commit();
}
}
On onview of main activity I am setting Home Fragment active when the activity starts. But it hides my bottom nav bar and replaces entire screen.
I think that this is a problem with the usage of LinearLayout as the root element for the fragment and bottomnav. Try replacing it with either ConstraintLayout or CoordinatorLayout. If none of those work try removing the top padding from the Fragment.
Your FrameLayout will just overlap the BottomNavigationView. Furthermore you should use the FragmentContainerView for your nav host. You'd want to have your FragmentContainerView explicitly above your BottomNavigationView. I changed your LinearLayout to a ConstraintLayout with proper constraints:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nav_host_fragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="#+id/bottom_nav"
app:defaultNavHost="true" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_nav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:labelVisibilityMode="unlabeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:background="#drawable/transparent_button"
app:onNavigationItemSelected="#{viewModel::onNavigationItemSelected}"
app:layout_behavior="#string/hide_bottom_view_on_scroll_behavior"
app:menu="#menu/bottom_navigation_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>

I cannot get OnClickListeners to work with my Android Activity containing two different Fragments

I am very new to Android Development and have been trying to get this to work for a while now. The basic structure of my Activity is two fragments between which you can switch by swiping. Both fragments have different layouts and contain different buttons and I am in the process of getting the buttons to work.
When I try to set the OnClickListener for any button in onCreate(), the App no longer starts. Here is my onCreate() Code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
imgButton = (ImageButton)findViewById(R.id.imageButton);
OnClickListener btnListener = new OnClickListener() {
#Override
public void onClick(android.view.View view) {
//Do Something
}
};
imgButton.setOnClickListener(btnListener);
}
The App Crashes with a null object reference, saying that imgButton's value is null. I certainly am doing this wrong, but I wasn't able to find the correct way of setting up button listeners for two fragments. Can anybody point me in the right direction?
EDIT: activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.dansoft.daily_surprise.MainActivity">
<android.support.v4.view.ViewPager
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
fragment_main.xml:
<RelativeLayout 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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:background="#drawable/background"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="com.dansoft.daily_surprise.MainActivity$PlaceholderFragment">
<ImageButton
android:id="#+id/imageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:layout_marginBottom="10dp"
android:layout_marginStart="10dp"
android:src="#drawable/box_1"
android:background="#android:color/transparent"
/>
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="#drawable/img_1"
/>
</RelativeLayout>
fragment_sec.xml:
<RelativeLayout 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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:background="#drawable/background"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="com.dansoft.daily_surprise.MainActivity$PlaceholderFragment">
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="#drawable/img_2"
/>
<Button
android:id="#+id/button"
android:layout_width="290dp"
android:layout_height="220dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="100dp"
android:background="#android:color/transparent"
/>
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="151dp"
android:text="22"
android:textColor="#android:color/black"
android:textSize="200sp" />
</RelativeLayout>
Your should track button clicks on your fragments, not on your activities.
Your fragments are not laid-out after onCreate. So your findViewById returns null.
Move your listener code to your fragments.

Add fragment below another overlapping

I'm was trying to display fragment below another fragment, but i'm facing Issue with view, when i invoke the 2nd fragment that should come below first fragment it's overlap.
My First fragment container RelativeLayout with Id mainLayout and 2nd fragment with Id carLayout.
I assume the issue with XML code.
My XML
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/topLayout">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="#+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
android:layout_weight="1" />
</LinearLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/mainLayout">
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/carLayout">
</RelativeLayout>
</LinearLayout>
i need to set fragment 2 below fragment 1
but it'as overlapping.
as I understand you need to set two fragment in same view
// add your first fragment
FragmentTransaction transaction = getFragmentManager().beginTransaction().add(frame_container1 , YOUR_FIRST_FRAGMENT).commit;
// add your second fragment
FragmentTransaction transaction = getFragmentManager().beginTransaction().add(frame_container2 , YOUR_SECOND_FRAGMENT).commit;
<linearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="2">
<FrameLayout
android:id="#+id/frame_container1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
<FrameLayout
android:id="#+id/frame_container2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
</linearLayout>
or simply
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="YOUR FRAGMENT CLASS"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</fragment>
carLayout is a RelativeLayout so new fragment will be over the last one, change it to a LinearLayout with orientation vertical.
You need another view below your carLayout.
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/anotherLayout"
android:layout_below="#id/carLayout">
</RelativeLayout>
The 'add' method adds a fragment to a view, so you can modify your method to use a different container every time:
public void replaceFragment(Fragment someFragment, int containerId) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.add(containerId , someFragment);
transaction.addToBackStack(null);
transaction.commit();
}
case R.id.home_menu:
fragment = new mainFrog();
replaceFragment(fragment,R.id.carLayout);
public void Haraj_cars(View view) {
fragment = new carFrog();
replaceFragment(fragment,R.id.anotherLayout);
}

Overlapping layouts using fragment transaction android

So I am trying load my login fragment from my main activity. I think I have a problem not replacing the whole layout in when I use the fragment transcation replace() method.
Here is my activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
}
#Override
protected void onStart() {
super.onStart();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
LoginFragment lf = new LoginFragment();
ft.replace(R.id.mapView, lf);
ft.addToBackStack("map to login");
ft.commit();
}
activity_maps.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:showIn="#layout/activity_maps">
<fragment
android:id="#+id/mapView"
android:name="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="#layout/activity_maps" />
<Button
android:id="#+id/btn
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
login_fragment.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:facebook="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".LoginActivity"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/white"
android:inputType="textPersonName"
android:text="#string/Username"
android:ems="10"
android:id="#+id/username"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:layout_marginBottom="10dp" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/white"
android:inputType="textPersonName"
android:text="#string/Password"
android:ems="10"
android:id="#+id/password"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:layout_marginBottom="10dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="#string/ForgotPassword"
android:id="#+id/forgotPassword"
android:layout_gravity="center_horizontal"
android:textColor="#197cff" />
<Button
android:id="#+id/GoogleButton"
android:layout_width="215dp"
android:layout_height="wrap_content" />
</LinearLayout>
Any recommendations on how I should restructure my xml files?
Thanks for your time!
Any recommendations on how I should restructure my xml files?
Your problems have nothing to do with the xml layouts. First of all embedding that MapFragment in the activity layout and then replacing it with another fragment as the activity starts(onStart()) doesn't make any sense at all. Secondly, embedded fragments(meaning fragments declared in the xml with the fragment tag) can't be used in fragment transactions, they are meant to be static. So remove the MapFragment from the xml layout and do a simple transaction to add the LoginFragment in a empty ViewGroup from the activity layout.

Height MapFragment Layout not work

I'm build an app that contain two tabhost (top and botton) and in one tab, I want to put a Google Map through the Google API. All works well but the map does not display correctly. You can see better in this picture:
My code is:
fragment_mapa.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/map_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<fragment
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.SupportMapFragment"/>
</RelativeLayout>
MapaFragment.java
public class MapaFragment extends Fragment {
public MapaFragment(){}
public GoogleMap mapa;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_mapa, container, false);
if (container != null) {
container.removeAllViews();
}
GoogleMap map = ((SupportMapFragment) getActivity().getSupportFragmentManager()
.findFragmentById(R.id.map)).getMap();
((MainActivity) getActivity()).setBar();
//Asigno el nombre de la vista e integro tabhost-sliding
((MainActivity) getActivity()).setTitle("Mapa");
((MainActivity) getActivity()).integrationMenu();
return rootView;
}
public void onDestroyView() {
super.onDestroyView();
Log.d("DESTROY", "onDestroyView");
Fragment f = getActivity()
.getSupportFragmentManager().findFragmentById(R.id.map);
if (f != null) {
getActivity().getSupportFragmentManager()
.beginTransaction().remove(f).commit();
}
}
}
And my activity_main.xml that contain the two tabhost and a framelayout that call the fragments:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Estructura de los dos tabhost -->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/LinearLayout1"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- TABHOST SUPERIOR -->
<RelativeLayout
android:id="#+id/l1"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:gravity="right"
android:layout_above="#+id/l2"
android:layout_alignParentTop="true">
<android.support.v4.app.FragmentTabHost
android:id="#+id/tabhost_sup"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TabWidget
android:id="#android:id/tabs"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="50dip"
android:layout_weight="0"/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff">
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0"/>
</ScrollView>
</LinearLayout>
</android.support.v4.app.FragmentTabHost>
</RelativeLayout>
<!-- TABHOST INFERIOR -->
<RelativeLayout
android:id="#+id/l2"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="50dip"
android:layout_weight="1"
android:gravity="right"
android:layout_alignParentBottom="true"
android:background="#android:color/background_light" >
<android.support.v4.app.FragmentTabHost
android:id="#android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:id="#+id/RelativeLayout1"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="0"/>
<TabWidget
android:id="#android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:layout_marginBottom="0dp"/>
</LinearLayout>
</android.support.v4.app.FragmentTabHost>
</RelativeLayout>
</RelativeLayout>
<!-- Listview to display slider menu -->
<ListView
android:id="#+id/list_slidermenu"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#color/list_divider"
android:dividerHeight="1dp"
android:listSelector="#drawable/list_selector"
android:background="#color/list_background"/>
<ListView
android:id="#+id/right_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="end"
android:choiceMode="singleChoice"
android:divider="#color/list_divider"
android:dividerHeight="1dp"
android:listSelector="#drawable/list_selector"
android:background="#color/list_background"/>
</android.support.v4.widget.DrawerLayout>
Removing scrollview is not convinient solution.Instead of it try android:FillViewPort="True" for Scrollview in your layout solve your problem for all screen where you may require scroll for your activity content.Hope this helps you!!
SOLUTION (by Hardik):
Remove the scrollview in my activity_main.xml and it works well.
Use hierarchiviewer of android tools to check layout values.
For the future:
If you have a ScrollView then elements must specify their height (width for horizontal scroll view) otherwise what height should they have, infinite?
I also had an issue where the exact thing happened when placing the map fragment inside a Relative Layout that had height = Wrap_Content, with minimum height.
Setting a constant height resolved the issue, same idea.
came across this same issue but my map fragment is inside a scrollview and it needs to have a scrollview since there are also other views aside from the map. if it only contains the map, then yes scrollview is not needed.

Categories

Resources