I have a drawerlayout, viewpager, and tablayout in my activity_main.xml I have two fragments HomeFragment and BookingFragment, I'm trying to launch the BookingFragment from another activity's on itemclick. I have tried multiple solutions like creating a framelayout with the id container and put the pager inside it and then user it in the fragment transaction and also I tried making an empty framelayout with the same id and put it above the pager, but it didn't work.
Here's the code for my method that I'm trying to start the fragment from
public void startTransaction(){
Fragment newFragment = new BookingFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.pager, newFragment);
transaction.addToBackStack(null);
transaction.commit();
}
Here's my activity_main.xml
<android.support.v4.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_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="net.app.cairobus.cairobus.MainActivity">
<LinearLayout 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:orientation="vertical"
tools:context=".MainActivity">
<android.support.v7.widget.Toolbar
android:id="#+id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="?attr/colorPrimary"
android:elevation="6dp"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/app_bar"
android:background="?attr/colorPrimary"
android:elevation="6dp"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_below="#id/tab_layout"
android:background="#fff" />
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="#+id/main_drawer"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#f2f2f2"
app:headerLayout="#layout/drawer_header"
app:itemIconTint="#color/accent"
app:itemTextColor="#color/secondary_text"
app:menu="#menu/menu_drawer" />
</android.support.v4.widget.DrawerLayout>
and here's the fragment I'm trying to start
public class BookingFragment extends Fragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
public static BookingFragment newInstance(String param1, String param2) {
BookingFragment fragment = new BookingFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
public BookingFragment() {}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_booking, container, false);
}
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(Uri uri);
}
}
You can't programmatically add a Fragment to a ViewPager. That's the job of the FragmentPagerAdapter.
So your main activity has a HomeFragment tab and a BookingFragment tab. You want to navigate from the HomeFragment to a TripActivity, and then navigate from the TripActivity to the BookingFragment.
To navigate from the HomeFragment to the TripActivity, use Activity.startActivityForResult().
To navigate from the TripActivity back to the BookingFragment, call Activity.setResult() then Activity.finish(). In setResult(), you can set a result code that means "open the BookingFragment" and set any other parameters you need in the data intent.
In your MainActivity, override onActivityResult(). When you receive a result code for the BookingFragment, call setCurrentItem(page) on the ViewPager to display the BookingFragment.
If you need to set up fields in the BookingFragment, you'll need to keep a reference to the BookingFragment returned from adapter.getItem() so you can call setters, etc.
Related
I have a navhost where fragments are swapped in and out and inside the navhost is a tabLayout with 3 fragments in the 3 tabs. once I go from the contact fragment to the addContact fragment and press the back button, the contact fragment is blank, the other 2 fragments are also blank but after a short delay, the view will load for them but not the contact fragment. this video will show what I'm saying a bit better https://drive.google.com/file/d/1fQlzTWV04Su-Gdi98buTbq4PIYKhSj7u/view?usp=sharing.
I've seen other people have this problem but they are using fragment transaction whereas I'm using a nav graph for navigation
my Fragment with the tablayout (activity_message.xml)
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Fragments.MainMenuFragment">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:minHeight="?actionBarSize"
android:padding="#dimen/appbar_padding"
android:text="#string/app_name"
android:textAppearance="#style/TextAppearance.Widget.AppCompat.Toolbar.Title" />
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" /></androidx.coordinatorlayout.widget.CoordinatorLayout>
my contact fragment (contact_fragment.xml)
<androidx.constraintlayout.widget.ConstraintLayout 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="match_parent"
android:layout_height="match_parent"
tools:context=".Fragments.contactFragment">
<!-- TODO: Update blank fragment layout -->
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.recyclerview.widget.RecyclerView>
<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"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_margin="#dimen/fab_margin"
app:srcCompat="#android:drawable/ic_dialog_email" /></androidx.constraintlayout.widget.ConstraintLayout>
my add contact fragment
public class AddContactFragment extends Fragment {
private Contact contact;
public AddContactFragment() {
}
public static AddContactFragment newInstance(){
AddContactFragment fragment = new AddContactFragment();
Bundle args = new Bundle();
//args.putString(ARG_PARAM1, param1);
//args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OnBackPressedCallback callback = new OnBackPressedCallback(true) {
#Override
public void handleOnBackPressed() {
Navigation.findNavController(getView()).navigate(R.id.action_addContactFragment_to_mainMenuFragment);
}
};
requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.add_contact_fragment,container,false);
TextView nameHeading = view.findViewById(R.id.contactNameHeading);
TextView numberHeading = view.findViewById(R.id.contactNoHeading);
TextView idHeading = view.findViewById(R.id.contactIdHeading);
nameHeading.setText("Name");
numberHeading.setText("Phone Number");
numberHeading.setText("Account ID");
return view;
}
}
my contact fragment (one in the tab layout)
public class contactFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private ArrayList<Contact> contacts;
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
public contactFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment contactFragment.
*/
// TODO: Rename and change types and number of parameters
public static contactFragment newInstance(String param1, String param2) {
contactFragment fragment = new contactFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
final View view = inflater.inflate(R.layout.fragment_contact, container, false);
RecyclerView rvContacts = (RecyclerView) view.findViewById(R.id.list);
contacts = Contact.createContactsList(50);
ContactsAdapter adapter = new ContactsAdapter(contacts);
rvContacts.setAdapter(adapter);
rvContacts.setLayoutManager(new LinearLayoutManager(getContext()));
FloatingActionButton fab = view.findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Navigation.findNavController(view).navigate(R.id.action_mainMenuFragment_to_addContactFragment);
}
});
return view;
}
}
my main menu fragment
public class MainMenuFragment extends Fragment {
public MainMenuFragment() {
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public static MainMenuFragment newInstance(String param1, String param2) {
MainMenuFragment fragment = new MainMenuFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_message,container,false);
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this.getContext(), getFragmentManager());
ViewPager viewPager = view.findViewById(R.id.view_pager);
viewPager.setAdapter(sectionsPagerAdapter);
TabLayout tabs = view.findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
return view;
}
}
my navhost (acvtivity_message_nav.xml)
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MessageActivity"
>
<fragment
android:id="#+id/fragment2"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph_message" /></androidx.constraintlayout.widget.ConstraintLayout>
my message activity
public class MessageActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message_nav);
}
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() == 1) {
finish();
} else {
super.onBackPressed();
}
}
}
my navgraph
<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/nav_graph_message"
app:startDestination="#id/mainMenuFragment">
<fragment
android:id="#+id/addContactFragment"
android:name="com.example.encryptedsmsapp.Fragments.AddContactFragment"
android:label="AddContactFragment" >
<action
android:id="#+id/action_addContactFragment_to_mainMenuFragment"
app:destination="#id/mainMenuFragment" />
</fragment>
<fragment
android:id="#+id/contactFragment"
android:name="com.example.encryptedsmsapp.Fragments.contactFragment"
android:label="fragment_contact"
tools:layout="#layout/fragment_contact" >
<action
android:id="#+id/action_contactFragment_to_addContactFragment"
app:destination="#id/addContactFragment" />
</fragment>
<fragment
android:id="#+id/mainMenuFragment"
android:name="com.example.encryptedsmsapp.Fragments.MainMenuFragment"
android:label="activity_message"
tools:layout="#layout/activity_message" >
<action
android:id="#+id/action_mainMenuFragment_to_addContactFragment"
app:destination="#id/addContactFragment" />
</fragment>
I have a bottom navigation activity ,In bottom navigation activity I have 3 icons Home,Reminders,settings.
For this I have 3 fragments, Home fragment, Reminder fragment and settings fragment. I don't have anything in fragments all are empty fragments except Home fragment. In Home Fragment I have a Tab layout but I didn't added anything with tab layout.
After running the project the Home fragment is not get displayed (default when app get launched). It shows only the bottom navigation view.
If I clicked on reminders Icon app get crashed with the following error.
Error:
java.lang.IllegalArgumentException: No view found for id 0x7f080076 (com.aviz.www.reminder:id/reminders_Fragment) for fragment Reminders{2eca87b #0 id=0x7f080076}
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1413)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1740)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1809)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:799)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2580)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2367)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2322)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2229)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:700)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
MainActivity.xml
<?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/Conslayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<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>
MainActivity
public class MainActivity extends AppCompatActivity
implements Home.OnFragmentInteractionListener,
Reminders.OnFragmentInteractionListener,
Settings.OnFragmentInteractionListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
switchToHomeFragment();
break;
case R.id.navigation_dashboard:
switchToRemindersFragment();
break;
case R.id.navigation_notifications:
switchToSettingsFragment();
break;
}
return false;
}
};
public void switchToHomeFragment() {
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().replace(R.id.home_Fragment, new Home()).commit();
}
public void switchToRemindersFragment() {
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().replace(R.id.reminders_Fragment, new Reminders()).commit();
}
public void switchToSettingsFragment() {
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().replace(R.id.settings_Fragment, new Settings()).commit();
}
#Override
public void onFragmentInteraction(Uri uri) {
}
}
Home Fragment XML
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/home_Fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".Fragments.Home">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_weight="1"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay"
app:title="#string/app_name">
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
style="#style/MyCustomTabLayout"
android:layout_height="wrap_content">
<android.support.design.widget.TabItem
android:id="#+id/tabItem_Today"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Today" />
<android.support.design.widget.TabItem
android:id="#+id/tabItem_ThisWeek"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This Week" />
<android.support.design.widget.TabItem
android:id="#+id/tabItem_ThisMonth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This Month" />
</android.support.design.widget.TabLayout>
</android.support.design.widget.AppBarLayout>
<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" />
</FrameLayout>
Home.java
public class Home extends Fragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
public Home() {
}
public static Home newInstance(String param1, String param2) {
Home fragment = new Home();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_home, container, false);
}
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
void onFragmentInteraction(Uri uri);
}
}
In Home.java all codes are auto generated code when I create the Home fragment.
in this line:
manager.beginTransaction().replace(R.id.reminders_Fragment, new Reminders()).commit();
R.id.reminders_Fragment
is a container id which will be wrapped around Remainders Fragment but i can not see any container in your Home layout with this id
even below code has same problem because you do not have any container with used
settings_Fragment id in your home layout:
manager.beginTransaction().replace(R.id.settings_Fragment, new Settings()).commit();
if you want every time one of your fragment be shown add one FrameLayout and use its id for container otherwise use one FrameLayout for every fragment and use id of FrameLayouts for transactions
You can use below code to select a default tab on resume:
onResume(){
super.onResume();
if(tabLayout.getSelectedTabPosition == -1)
tabLayout.getTabAt(0).select();
}
When loading my program on a device for testing, as I open different fragments using the bottom navigation nothing happens what so ever. If you need me to add more code please say so. I've posted my XML and Java for the Main Activity and the XML contains the mainFrame for my layout.
public class MainActivity extends AppCompatActivity {
private TextView mTextMessage;
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();
switch (item.getItemId()) {
case R.id.shareFrame:
transaction.replace(R.id.mainFrame, new shareFragment()).commit();
mTextMessage.setText(R.string.title_share);
return true;
case R.id.settingsFrame:
transaction.replace(R.id.mainFrame, new settingsFragment()).commit();
mTextMessage.setText(R.string.title_settings);
return true;
case R.id.helpFrame:
transaction.replace(R.id.mainFrame, new helpFragment()).commit();
mTextMessage.setText(R.string.title_help);
return true;
}
return false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextMessage = (TextView) findViewById(R.id.message);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.mainFrame, new shareFragment()).commit();
}
}
Here is the Java for my shareFragment.java
public class shareFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
public shareFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment shareFragment.
*/
// TODO: Rename and change types and number of parameters
public static shareFragment newInstance(String param1, String param2) {
shareFragment fragment = new shareFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_share, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
Toast.makeText(context, "Share", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
And here is the XML
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/shareFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.swapdrop.swapdrop.shareFragment">
</FrameLayout>
Looks like your calling the empty Constructor.
Change:
transaction.replace(R.id.mainFrame, new shareFragment()).commit();
to
transaction.replace(R.id.mainFrame, shareFragment.newInstance("arg 1","arg 2")).commit();
Also, java convention is to upper case class names. shareFragment -> ShareFragment
Try change your layout with 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.swapdrop.swapdrop.MainActivity"
android:background="#d3d3d3">
<FrameLayout
android:id="#+id/mainFrame"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<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>
Now mainFrame is the FrameLayout instead of the parent Layout
Your root layout shouldn't be the "mainFrame". You should have a child ViewGroup to contain the fragment. Something like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/mainFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/navigation"
android:background="#d3d3d3" />
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="?android:attr/windowBackground"
app:menu="#menu/navigation" />
</RelativeLayout>
Why not try something like:
transaction.replace(R.id.mainFrame, shareFragment().newInstance("param1", " param2")).commit();
since the default constructor is not returning any Fragment().
I have ONE activity that calls a FragmentParent. This contains a viewpager. The viewpager has 2 tabs. In each tab there is a fragment. In the first tab (TAB-A) there is a fragment that contains a Recyclerview. When I click over an item the app opens new fragment, but when I go back ALL the fragments inside the viewpager get empty.
I am using Fragments and support library v-13, I already tried with v-4 but I had the same issue.
This is my code:
activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_test);
initWithFragments(savedInstanceState);
}
public void initWithFragments(Bundle savedInstanceState) {
if (findViewById(R.id.fragment_container) != null) {
if (savedInstanceState != null) {
return;
}
// Create a new Fragment to be placed in the activity layout
MainFragment mainFragment = new MainFragment();
//Fragment transaction
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.fragment_container, mainFragment);
ft.commit();
}
}
MainFragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_app, container, false);
//Enabled menu
setHasOptionsMenu(true);
// Initialize Toolbar and View Pager
toolbar = (Toolbar) rootView.findViewById(R.id.toolbar);
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
// Create the adapter that will return a fragment for each section
SectionsPageAdapter mSectionsPagerAdapter = new SectionsPageAdapter(getFragmentManager());
// Set up the ViewPager with the sections adapter.
ViewPager mViewPager = (ViewPager) rootView.findViewById(R.id.container_view_pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
switch (position) {
case 0:
toolbar.setTitle("Home");
break;
case 1:
toolbar.setTitle("Downloads");
break;
default:
break;
}
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
// Set up tab layout
TabLayout tabLayout = (TabLayout) rootView.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
return rootView;
}
fragment_app
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/appbar_padding_top"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay">
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/container_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</LinearLayout>
This is the FragmentA inside the viewpager
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorGrayLight"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<LinearLayout
android:id="#+id/container_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="1">
<android.support.v7.widget.RecyclerView
android:id="#+id/video_recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
Also I have the PageAdapter
public class SectionsPageAdapter extends FragmentPagerAdapter {
private int NUM_PAGES = 2;
public SectionsPageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
switch (position) {
case 0:
return SearchFragment.newInstance();
case 1:
return DownloadFragment.newInstance();
default:
return new Fragment();
}
}
#Override
public int getCount() {
return NUM_PAGES;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Search";
case 1:
return "Downloads";
}
return null;
}
}
I am using FragmentTransaction to replace Fragments...
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container,settingFragment);
ft.addToBackStack(null);
ft.commit();
If you guys can help me, I will really appreciate
Thanks
This is what I want to:
change FragmentA layout
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorGrayLight"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<LinearLayout
android:id="#+id/container_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="1">
<android.support.v7.widget.RecyclerView
android:id="#+id/video_recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
</FrameLayout>
Now when you replace fragment with this
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container,settingFragment);
ft.addToBackStack(null);
ft.commit();
it will take R.id.fragment_container from FragmentA
I finally resolved using getChildFragments:
I used getChildFragmentManager instead of getFragmentManager. I passed to the constructor of the PageAdapter
SectionsPageAdapter mSectionsPagerAdapter = new SectionsPageAdapter(getChildFragmentManager());
In the view holder of the RecyclerView I created an Interface to communicate Nested Fragments with the Activity(main container). Using this way I could replace Fragments in the R.id.fragment_container
I found the solution in this link:
Adding child Fragment to Parent Fragment withing a ViewPager in Android
I have a ViewPager layout like the one below. However, the LinearLayout within the ViewPager disappears and is replaced by the content I'm loading into the ViewPager.
activity_main.xml
<LinearLayout
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:orientation="vertical"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<com.astuetz.PagerSlidingTabStrip
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="60dp"
app:pstsTabTextAlpha="150"
app:pstsIndicatorHeight="3dp"
app:pstsShouldExpand="true"
app:pstsUnderlineHeight="0dp"
app:pstsTabTextSize="14dp"
/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/tabs">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal">
<ImageView
android:layout_width="120dp"
android:layout_height="120dp"
android:id="#+id/image"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp"
android:background="#drawable/ic_image"
android:adjustViewBounds="true"
android:scaleType="centerCrop" />
</LinearLayout>
</android.support.v4.view.ViewPager>
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity
implements FirstFragment.OnFragmentInteractionListener,
SecondFragment.OnFragmentInteractionListener,
ThirdFragment.OnFragmentInteractionListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize the ViewPager and set an adapter
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(new PagerAdapter(getSupportFragmentManager()));
// Bind the tabs to the ViewPager
PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);
tabs.setViewPager(pager);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_group, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void onFragmentInteraction(Uri uri){
//
}
private class PagerAdapter extends FragmentPagerAdapter {
private final String[] TITLES = {"First", "Second", "Third"};
public PagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public CharSequence getPageTitle(int position) {
return TITLES[position];
}
#Override
public int getCount() {
return TITLES.length;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new FirstFragment();
case 1:
return new SecondFragment();
case 2:
return new ThirdFragment();
}
return null;
}
}
}
FirstFragment.java
public class FirstFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
String BASE_URL = "http://www.example.com/api";
private OnFragmentInteractionListener mListener;
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment FirstFragment.
*/
// TODO: Rename and change types and number of parameters
public static FirstFragment newInstance(String param1, String param2) {
FirstFragment fragment = new FirstFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
public FirstFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_first, container, false);
final ListView listView = (ListView) view.findViewById(R.id.listview_posts);
final ArrayList<Post> postArray = new ArrayList<Post>();
// REST API
final RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(BASE_URL)
.build();
final ApiEndpointInterface apiService = restAdapter.create(ApiEndpointInterface.class);
apiService.getData(1, new Callback<PostData>() {
#Override
public void success(PostData postData, Response response) {
final PostAdapter adapter = new PostAdapter(getActivity(), postArray);
postArray.addAll(postData.getData());
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
#Override
public void failure(RetrofitError retrofitError) {
retrofitError.printStackTrace();
}
});
return view;
}
class Deserializer implements JsonDeserializer<Post> {
#Override
public Post deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
throws JsonParseException {
// Get the "content" element from the parsed JSON
JsonElement content = je.getAsJsonObject().get("data");
// Deserialize it. You use a new instance of Gson to avoid infinite recursion
// to this deserializer
return new Gson().fromJson(content, Post.class);
}
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p/>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(Uri uri);
}
}
fragment_first.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.project.app.FirstFragment">
<ListView
android:id="#+id/listview_posts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:dividerHeight="0dp"
android:divider="#null" />
</LinearLayout>
Why is it replacing everything in the ViewPager? How can I instead append the data to the ViewPager, such that the data goes below the layout in the ViewPager?
You can't do that... The viewpager will always do this.. yiu may need to put the layouts outside the viewpager.. in a way the makes user feel they are inside...
you should include this components in Fragment layout
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.project.app.FirstFragment">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal">
<ImageView
android:layout_width="120dp"
android:layout_height="120dp"
android:id="#+id/image"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp"
android:background="#drawable/ic_image"
android:adjustViewBounds="true"
android:scaleType="centerCrop" />
</LinearLayout>
<ListView
android:id="#+id/listview_posts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:dividerHeight="0dp"
android:divider="#null" />
</LinearLayout>
or place them under ViewPager like this
<LinearLayout
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:orientation="vertical"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<com.astuetz.PagerSlidingTabStrip
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="60dp"
app:pstsTabTextAlpha="150"
app:pstsIndicatorHeight="3dp"
app:pstsShouldExpand="true"
app:pstsUnderlineHeight="0dp"
app:pstsTabTextSize="14dp"
/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/tabs">
</android.support.v4.view.ViewPager>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal">
<ImageView
android:layout_width="120dp"
android:layout_height="120dp"
android:id="#+id/image"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp"
android:background="#drawable/ic_image"
android:adjustViewBounds="true"
android:scaleType="centerCrop" />
</LinearLayout>
</LinearLayout>