I am trying to call a fragment from an activity. But unable. This is what I tried.
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
if (item.getItemId()==R.id.action_search){
SearchFragment searchFragment=new SearchFragment();
getSupportFragmentManager().beginTransaction().add(R.id.container,searchFragment,null).commit();
}
return true;
}
And My main_activity.xml
<androidx.appcompat.widget.LinearLayoutCompat 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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/container"
tools:context=".Controllers.MainActivity">
After trying the app does crash but its also not opening the fragment which I want.
The fragment xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/searchFragment"
tools:context=".SearchFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerViewSearchFrag"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.recyclerview.widget.RecyclerView>
And Fragment java is
public class SearchFragment extends Fragment {
private RecyclerView mRecyclerViewSearch;
private RecyclerViewAdpater mAdpater;
public SearchFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.fragment_search, container, false);
mRecyclerViewSearch=view.findViewById(R.id.recyclerViewSearchFrag);
mRecyclerViewSearch.setLayoutManager(new LinearLayoutManager(getContext()));
mAdpater=new RecyclerViewAdpater(DataSevices.mChineseColors,getActivity());
return view;
}
}
Please correct me if I am doing anything wrong
You can use Framlayout instead of Linear-layout
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
if you want some other components in your MainActivity , create a fragment for that.
and replace it.
in activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" />
in your fragment xml:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SearchFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerViewSearchFrag"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
create new fragment fragment_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
...
</LinearLayout>
and MainFragment.java
public class MainFragment extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup
container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
//...
return view;
}
}
Related
I'm replacing my main activity's layout with fragments in order to keep the same navigation menu. However I've done data binding to fragment_home.xml and now the toolbar no longer shows up, even though I still switch to the intended fragment. After some debugging, I believe it has something to do with the setContentView in HomeFragment.java.
Any ideas?
Here's my activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
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/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity"
tools:openDrawer="start">
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#000"
android:elevation="4dp"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
<FrameLayout
android:id="#+id/frag_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/nav_header"
app:menu="#menu/side_navbar"
app:itemTextColor="#color/black"
app:itemIconTint="#color/black"/>
</androidx.drawerlayout.widget.DrawerLayout>
Replacing frame layout with the fragment
getSupportFragmentManager().beginTransaction().replace(R.id.frag_container, new HomeFragment()).commit(); ```
And the fragment_home.xml
<?xml version="1.0" encoding="utf-8"?>
<layout 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"
tools:context=".HomeFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/viewCities"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:padding="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</layout>
And finally the HomeFragment.java
public class HomeFragment extends Fragment {
private CityViewModel cityViewModel;
private RetrofitAdapter retrofitAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = inflater.inflate(R.layout.fragment_home, container, false);
FragmentHomeBinding activityMainBinding =
DataBindingUtil.setContentView(getActivity(), R.layout.fragment_home);
RecyclerView recyclerView = activityMainBinding.viewCities;
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setHasFixedSize(true);
cityViewModel = new ViewModelProvider(requireActivity()).get(CityViewModel.class);
retrofitAdapter = new RetrofitAdapter();
recyclerView.setAdapter(retrofitAdapter);
return view;
}
}
You do not have to set the content view again from the fragment. From the HomeFragnent for using the data-binding just do something as follows.
FragmentHomeBinding binding; // declare the binding variable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil
.inflate(inflater, R.layout.fragment_home, container, false);
/* FragmentHomeBinding activityMainBinding =
DataBindingUtil.setContentView(getActivity(), R.layout.fragment_home); */
RecyclerView recyclerView = binding.viewCities; // use the binding here
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setHasFixedSize(true);
cityViewModel = new ViewModelProvider(requireActivity()).get(CityViewModel.class);
retrofitAdapter = new RetrofitAdapter();
recyclerView.setAdapter(retrofitAdapter);
return binding.getRoot();
}
I'm creating an app that need to nested navigation graphs and a want to close a parent fragment from child fragment.
I can close a fragment by calling
getActivity().getSupportFragmentManager().popBackStack();
with this i can only close the current top fragment in back stack.
in this picture i want to close Fragment2 from Framgent3.
EDIT:
I'm opening Fragment2 with:
Navigation.findNavController(getView()).navigate(R.id.action_fragment1_to_fragment2);
Fragment1:
public class Fragment1 extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment1, container, false);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getView().findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Navigation.findNavController(v).navigate(R.id.action_fragment1_to_fragment2);
}
});
}
}
Fragment1 layout:
<?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"
android:background="#color/colorPrimaryDark">
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Framgent2:
public class Fragment2 extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment2, container, false);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
public void close () {
getActivity().getSupportFragmentManager().popBackStack();
}
}
in Fragment2 i have another graph, Fragment2 layout:
<?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:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<fragment
android:id="#+id/child_graph_base"
android:name="androidx.navigation.fragment.NavHostFragment"
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"
app:defaultNavHost="true"
app:navGraph="#navigation/child_graph" />
</android.support.constraint.ConstraintLayout>
Fragment3:
public class Fragment3 extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment3, container, false);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getView().findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
NavHostFragment navHostFragment = (NavHostFragment) getParentFragment();
Fragment2 fragment2 = (Fragment2) navHostFragment.getParentFragment();
fragment2.close();
}
});
}
}
Fragment3 layout:
<?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"
android:background="#color/colorPrimaryDark">
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Main Graph (MainActivity):
<?xml version="1.0" encoding="utf-8"?>
<navigation 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/main_graph"
app:startDestination="#id/fragment1">
<fragment
android:id="#+id/fragment1"
android:name="alistar.navigation.fragments.Fragment1"
android:label="fragment1"
tools:layout="#layout/fragment1" >
<action
android:id="#+id/action_fragment1_to_fragment2"
app:destination="#id/fragment2" />
</fragment>
<fragment
android:id="#+id/fragment2"
android:name="alistar.navigation.fragments.Fragment2"
android:label="fragment2"
tools:layout="#layout/fragment2" />
</navigation>
Child Graph (in Framgent2)
<?xml version="1.0" encoding="utf-8"?>
<navigation 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/child_graph"
app:startDestination="#id/fragment3">
<fragment
android:id="#+id/fragment3"
android:name="alistar.navigation.fragments.Fragment3"
android:label="fragment3"
tools:layout="#layout/fragment3" />
</navigation>
i solved the problem by calling close() method in the parent fragment (Fragment2) from Fragment3. i changed close method to this:
public void close () {
Navigation.findNavController(getView()).popBackStack();
}
also i removed:
app:defaultNavHost="true"
from my child graph and worked OK!
include the graph of (frag2,frag3) in frag1's graph using include
<include app:graph="#navigation/frag1_graph"/>
and then:
add an action to your fragment3 with appropriate Destination and popUpTo arguments
<fragment
android:id="#+id/Fragment3"
android:name="whatever"
android:label="whatever"
tools:layout="#layout/whatever" >
<action
android:id="#+id/action_Fragment3_to_Fragmen1"
app:destination="#id/Fragment1"
app:launchSingleTop="true"
app:popUpTo="#+id/Fragment1"
app:popUpToInclusive="true" /> </fragment>
and then
findNavController(fragment).navigate(R.id.action_Fragment3_to_fragment1)
and then display fragment3 again. i think that's what you want right?
I'm trying to create a tabHost inside a Fragment, so I can create a tabs inside that fragment I've tried changing the extends to android.support.v4.app.Fragment but then the complete app won't build. This issue I have is the following:
wrong 2nd argument type. found'android.app.fragment' required 'android.support.v4.app.fragment'
This is the code I wrote:
public class TimeTableFragment extends Fragment {
FragmentNameFactory nameFactory = new FragmentNameFactory();
String body;
String major;
String status;
private FragmentTabHost mTabHost;
public TimeTableFragment(){
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceStatus){
((MainActivity) getActivity()).setFragmentName(nameFactory.getNameNL(7));
View view = inflater.inflate(R.layout.ftimetable, container, false);
mTabHost = (FragmentTabHost) view.findViewById(android.R.id.tabhost);
mTabHost.setup(getActivity(), getChildFragmentManager(), R.id.realtabcontent);
mTabHost.setup();
mTabHost.addTab(mTabHost.newTabSpec("fragmentb").setIndicator("Fragment B"));
mTabHost.addTab(mTabHost.newTabSpec("fragmentc").setIndicator("Fragment C"));
mTabHost.addTab(mTabHost.newTabSpec("fragmentd").setIndicator("Fragment D"));
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstance){
super.onViewCreated(view, savedInstance);
}
#Override
public void onActivityCreated(Bundle savedInstance){
super.onActivityCreated(savedInstance);
}}
The .xml (ftimetables):
<?xml version="1.0" encoding="utf-8"?>
<TabHost
android:id="#android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:id="#+id/linearLayout1"
android:layout_height="match_parent"
android:orientation="vertical">
<TabWidget
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#android:id/tabs">
</TabWidget>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#android:id/tabcontent">
</FrameLayout>
</LinearLayout>
</TabHost>
I hope someone can help me fix this issue!
change your TimeTableFragment import code
import android.app.fragment(x)
import android.support.v4.app.fragment(o)
I'm having an issue where a fragment in my main activity does not show up when the app is being started initially (during the main apps onCreate method) but does show up when I pause the app and then resume it (during the onResume method)
Here's the important parts of my main activity
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<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:id="#+id/activity_main"
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" />
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
MainActivity:
public class MainActivity extends Activity {
protected FrameLayout fragment_container;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (findViewById(R.id.fragment_container) != null) {
if (savedInstanceState != null) {
TextViewFragment fragment = new TextViewFragment();
fragment.setArguments(getIntent().getExtras());
getFragmentManager().beginTransaction().add(R.id.fragment_container, fragment).commit();
}
}}
TextViewFragment:
public class TextViewFragment extends Fragment {
#Override
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.textview_fragment, container, false);
}
}
textview_fragment:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:text="This is not showing up"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:typeface="sans"
android:textSize="35sp"/>
</LinearLayout>
Any help is appreciated!
When it starts first then if (savedInstanceState != null) { condition gives null.
You may remove the condition then it will load the fragment always.
I have a Fragment
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
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="match_parent"
android:padding="10dp"
android:id="#+id/switchLayout">
</LinearLayout>
</FrameLayout>
and want to add switches to the LinearLayout as soon as the Fragment is loaded
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootview = inflater.inflate(R.layout.fragment, container, false);
LinearLayout switchLayout = (LinearLayout) rootview.findViewById(R.id.switchLayout);
Switch new_switch = new Switch(getActivity());
new_switch.setText("test");
new_switch.setChecked(true);
switchLayout.addView(new_switch);
return rootview;
}
but when the Fragment gets loaded nothing happens, the LinearLayout is displayed but the switch doesn't appear and I don't get any error messages.
I already tried adding
new_switch.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT)
);
but it makes no difference
note: this is my first question here, hopefully it's not too stupid ^^
I've tried to perform the same what you are doing and it works.
Main activity layout:
<?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"
<FrameLayout
android:id="#+id/containerFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Then in MainActivity.java:
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().replace(R.id.containerFragment,
new MyFragment()).commit();
MyFragment and fragment layout is the same as you described.
Result: