Android: trying to add a fragment to the backstack ("Blank activity" project) - android

I have just created a new "Blank activity" project. And now I would like to add a fragment to the backstack when pressing the button that the "Blank activity" shows. The problem: the applicaction closes unexpectedly when pressing the button.
Steps I have followed to create a fragment from an activity
Steps I have followed to add a fragment to the backstack
These are the only codes I added to the Blank Activity project:
//MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
context = this;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ExampleFragment ef = new ExampleFragment();
/////// This line closes the application /////////
getFragmentManager().beginTransaction()
.add(65, ef) //65 is random number
// Add this transaction to the back stack
.addToBackStack(null)
.commit();
setContentView(R.layout.news_articles);
}
});
}
This is the layout of the fragment:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<fragment android:name="com.example.tirengarfio.myapplication.ExampleFragment"
android:id="#+id/headlines_fragment"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
ExampleFragment.java
package com.example.tirengarfio.myapplication;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class ExampleFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.example_fragment, container, false);
}
}

First understand difference between
1. Adding a fragment statically vs
2. Adding a fragment dynamically.
This tutorial will help you http://www.vogella.com/tutorials/AndroidFragments/article.html
( check section 5.1 and section 5.2 in the tutorial )
Also you are doing
getFragmentManager().beginTransaction()
.add(65, ef) //65 is random number
// Add this transaction to the back stack
.addToBackStack(null)
.commit();
verify the .add(65, ef) part. You cannot add a random int 65 it has to be resource id for the container view where you want do dynamically add a fragment.

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

Default fragment in activity

I've seen many posts on this matter, but I can't figure it out for my code. I have created a tabbed activity and set three buttons at the bottom. The buttons switch between different fragments. A button in a MainActivity opens this tabbed activity, but the problem is that the fragment layout is empty (see image below).
The buttons work perfectly and send me to the right fragments, but when it opens, no fragments are loaded.
The code, which I build following an YouTube tutorial looks like this:
TabbedActivity.class
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
public class TabbedActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tabbed_activity);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction transaction = fragmentManager.beginTransaction();
int intentFragment = getIntent().getExtras().getInt("frgToLoad");
switch (item.getItemId()) {
case R.id.navigation_home:
transaction.replace(R.id.content,new Fragment_B1()).commit();
/* mTextMessage.setText(R.string.title_home);*/
return true;
case R.id.navigation_dashboard:
transaction.replace(R.id.content,new Fragment_B2()).commit();
/*mTextMessage.setText(R.string.title_dashboard);*/
return true;
case R.id.navigation_notifications:
transaction.replace(R.id.content,new Fragment_B3()).commit();
/*mTextMessage.setText(R.string.title_notifications);*/
return true;
}
return false;
}
};
}
The fragments have the same code pattern inside, which is basic and it makes no point to add it here. The xml of the TabbedActivity looks like this:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="TabbedActivity">
<FrameLayout
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toBottomOf="#+id/appbar">
</FrameLayout>
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="0dp"
android:layout_marginStart="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/navigation" />
</android.support.constraint.ConstraintLayout>
Can anyone help me to figure out how to open Fragment_B1 by default? I have tried adding the code from the best answer from here, but still doesn't work.
You can just added the original fragment direct on the onCreate, like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tabbed_activity);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
if(savedInstanceState == null) {
getSupportFragmentManager().
beginTransaction().replace(R.id.content,new Fragment_B1()).commit();
}
}
In the last add, navigation.setSelectedItemId(navigation_home);

Open Fragment From Activity

Im working on a small google maps app that lets users find places close to them, I want to add functionality that lets the user add a place to a list of favourites, So far ive created classes that may do the functionality.
My main activity is my home page which opens other activities, code below:
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageButton;
public class MainActivity extends AppCompatActivity {
ImageButton btnNearBy;
ImageButton btnFavourites;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnNearBy = (ImageButton) findViewById(R.id.btnNearby);
btnNearBy.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent mapIntent = new Intent(getBaseContext(), MapsActivity.class);
startActivity(mapIntent);
}
});
btnFavourites = (ImageButton) findViewById(R.id.btnFavourites);
btnFavourites.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager fragmentManager = MainActivity.this.getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
FavouriteListFragment fragment = new FavouriteListFragment();
fragmentTransaction.add(R.id.fragment_container, fragment); //ERROR ON THIS LINE
fragmentTransaction.commit();
}
});
}
}
Ive created a button that should open up the fragment that holds the list of favourites ,My fragment is declared like this:
public class FavouriteListFragment extends Fragment { ... }
Im a little unsure how to open the fragment from the MainActivity when clicking a button.
Any ideas?
Thanks!
There are two ways of displaying fragments:
1- First you need to define a fragment container in your code like the following:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="do something"
android:onClick="openFragment" />
<FrameLayout
android:id="#+id/fragment_container"
android:layout_height="wrap_content"
android:layout_width="match_content" />
</LinearLayout>
and then you need to create a function called openFragment in your activity and use the following code in openFragment:
getSupportFragmentManager().beginTransaction().add(R.id_fragment_container,new FavouriteListFragment()).commit();
2- You can define the fragment in your activity xml file like:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/my_fragment"
android:name="com.example.android.something.FavouriteListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.android.something.FavouriteListFragment"
tools:layout="#android:layout/fragment_layout" />
The first one is called dynamic fragment creation and the second one is called static. You have more freedom with the first one but if your fragment doesn't change throughout the activity it is simpler to use the second one
Since you are using android.support.v4.app.Fragment and there has been a lot of confusion in importing correct version. Try like this:
android.support.v4.app.FragmentManager fragmentManager = MainActivity.this.getSupportFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
FavouriteListFragment fragment = new FavouriteListFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
Where fragment_container is FrameLayout inside activity_main.
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
Reference

TextView doesn't show inside Fragment

I have a Fragment class, called from by FragmentTabHost, which does not display nothing.
This is my ArticulosFragment class:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class ArticulosFragment extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("App", "asdasdasd");
return inflater.inflate(R.layout.fragment_articulos, container, false);
}
}
I have a simple TextView in the 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="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Articulos"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
When I run the app, the log added shows correctly, but the text Articulos doesn't.
Edit: This is my TabHost class which displays (or should displays) the ArticulosFragment class:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
tabHost.setup(this, getSupportFragmentManager(),
android.R.id.tabcontent);
inicializarTabs();
}
public void inicializarTabs() {
TabHost.TabSpec spec = tabHost.newTabSpec("Articulos");
spec.setContent(new TabContentFactory() {
#Override
public View createTabContent(String tag) {
// TODO Auto-generated method stub
return findViewById(R.id.realtabcontent);
}
});
spec.setIndicator("Articulos");
tabHost.addTab(spec, ArticulosFragment.class, null);
}
Two Things That Might Cause That:
Check If The Container coming is null for view
Check you Code For Fragment that show Fragment
Try Removing onCreate method from Fragment
TabContentFactory
Makes the content of a tab when it is selected. Use this if your tab
content needs to be created on demand, i.e. you are not showing an
existing view or starting an activity.
Please notice this line:
you are not showing an existing view or starting an activity.
public abstract View createTabContent (String tag)
Callback to make the tab contents
Parameters
tag Which tab was selected.
Returns
The view to display the contents of the selected tab.
So because you have a fragment and it is already have a view you do not need createTabContent and the interesting part is:
https://github.com/android/platform_frameworks_support/blob/master/v13/java/android/support/v13/app/FragmentTabHost.java#L219
as you see fragmentTabHost overwrites your TabContentFactory.
anyway your problem is:
tabHost.setup(this, getSupportFragmentManager(),android.R.id.tabcontent);
change it to:
tabHost.setup(this, getSupportFragmentManager(),R.id.realtabcontent);

Android Fragments make duplicate TextView on orientation change

I am trying to make a very simple App, but there's an error I can't get rid of it. Maybe someone can help me.
I'm making an Activity with an ActionBar and 3 Tabs. Beneath the Tabs is a FrameLayout, where I put Fragments with a TextView in it. So when clicking on a tab the content of the TextView shoud change.
This works fine until I change the orientation. After the change there is a duplicate TextView and I have no idea where it cames from. Here's a picture for better understanding:
Overlapping TextViews
Here's my Activity:
package com.test;
import android.app.ActionBar;
import android.app.Activity;
import android.app.FragmentTransaction;
import android.app.ActionBar.Tab;
import android.os.Bundle;
import android.widget.Toast;
public class ProblemActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ActionBar bar = getActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
String tab1 = "First Tab";
bar.addTab(bar
.newTab()
.setText(tab1)
.setTabListener(
new TabListener(new First())));
String tab2 = "Second Tab";
bar.addTab(bar
.newTab()
.setText(tab2)
.setTabListener(
new TabListener(new Second())));
String tab3 = "Third Tab";
bar.addTab(bar
.newTab()
.setText(tab3)
.setTabListener(
new TabListener(new Third())));
}
private class TabListener implements ActionBar.TabListener {
private MyFragment mFragment;
public TabListener(MyFragment fragment) {
this.mFragment = fragment;
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.add(R.id.fragment_content, mFragment, null);
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(mFragment);
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
Toast.makeText(ProblemActivity.this, "Reselected!", Toast.LENGTH_SHORT)
.show();
}
}
}
The Fragment's:
public class First extends MyFragment {
public First() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View fragView = inflater.inflate(R.layout.tab1, container, false);
TextView tv = (TextView) fragView.findViewById(R.id.textView1);
tv.setText("First Tab");
return fragView;
}
}
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/fragment_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
and the content of the Fragment's.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="TextView"
android:textSize="35dp" />
</LinearLayout>
It would be amazing if some could show me what I'm making wrong.
Thank's in advance!
Edit: I tried already this proposed solution but I would like to work with class Objects, so that I can use their Methods.
Edit2: Solved the problem now. It was sufficient to add android:configChanges="keyboardHidden|orientation|screenSize" to my Activity.
Since the OP already solved his problem, but hasn't been active on SO for almost a year, here is an answer containing the solution:
Adding the following to the Activity solved the problem:
android:configChanges="keyboardHidden|orientation|screenSize"
You can get overlapping views if there is something wrong with one of your layouts. This seems to happen in particular if you have a fragment. For example, a View in the Fragment can overlap a View in the containing layout.
Sometimes this can be fixed by Cleaning your project (if you are using Eclipse).

Categories

Resources