I am trying open a Fragment From onOptionsItemSelected Method - java

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

Toolbar disappears while replacing fragment when Data Binding in Android

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();
}

How to close a parent fragment from child fragment in navigation component

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?

TabHost inside Fragment

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)

Fragment does not show up when app starts (onCreate) but does when it resumes (onResume)

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.

Create Switch and add it to Layout

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:

Categories