My problem it's that I created a default Bottom Navigation Activity and I want to call a fragment method from MainActivity. The problem is that I 'm not able to take a reference of the fragment.
I tried all type of solution here in stackOverFlow.
a lot of method is deprecated.
//MAIN ACTIVITY
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
BottomNavigationView navView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(binding.navView, navController);
FragmentManager fm = getSupportFragmentManager();
HomeFragment fragment = (HomeFragment) fm.findFragmentById(R.id.navigation_home);
fragment.sayHi();
}
//FRAGMENT
public class HomeFragment extends Fragment {
private HomeViewModel homeViewModel;
private FragmentHomeBinding binding;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
homeViewModel =
new ViewModelProvider(this).get(HomeViewModel.class);
binding = FragmentHomeBinding.inflate(inflater, container, false);
View root = binding.getRoot();
final TextView textView = binding.textHome;
homeViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
textView.setText(s);
}
});
return root;
}
public void sayHi(){
Log.d("hi", "hi");
}
#Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
Related
Problem: Having a SwipeView inside a Fragment (So when the Fragment is active you can cycle through some other fargments)
What I tried: I tried implementing it the same way you would implement it normally but in the fragment:
NORMAL WAY:
public class MainActivity extends FragmentActivity {
ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewPager);
SwipeAdapter swipeAdapter = new SwipeAdapter(getSupportFragmentManager());
viewPager.setAdapter(swipeAdapter);
}
}
THE WAY I TRIED IT WITH A FRAGMENT:
public class SecondFragment extends Fragment {
ViewPager viewPager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_first, container, false);
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
viewPager = view.findViewById(R.id.VIEWPAGER);
SwipeAdapter swipeAdapter = new SwipeAdapter(getChildFragmentManager());
viewPager.setAdapter(swipeAdapter);
}
}
THE ERROR: It returns a "null object reference" when I try to set the adapter (I'm guessing it has problems with the FragmentManager)
ADAPTER FOR BOTH EXAMPLES:
public class SwipeAdapter extends FragmentStatePagerAdapter {
public SwipeAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Fragment fragment = new PageFragment();
Bundle bundle = new Bundle();
bundle.putInt("count", position+1);
fragment.setArguments(bundle);
return fragment;
}
#Override
public int getCount() {
return 5;
}
}
In the Main Activity I set up so you can switch fragments with buttons, and what I'm trying to implement in the second fragment is to be able to swipe through fragments with SwipeView
MAIN ACTIVITY CODE:
public class MainActivity extends AppCompatActivity {
Button firstFragment, secondFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
firstFragment = (Button) findViewById(R.id.firstFragment);
secondFragment = findViewById(R.id.secondFragment);
firstFragment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
loadFragment(new FirstFragment());
}
});
secondFragment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
loadFragment(new SecondFragment());
}
});
}
private void loadFragment(Fragment fragment) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.frameLayout, fragment);
fragmentTransaction.commit();
}
}
I don't know if this is the right way to do it, but if anyone has a way to make this work any help would be appreciated, thanks!
You cannot set the adapter because your view has not been created yet.
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? = inflater.inflate(R.layout.fragment_first, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewPager = view.findViewById(R.id.viewPager) as ViewPager
swipeAdapter = SwipeAdapter(childFragmentManager)
...
}
I have been investigating for like 4 hours about this problem, but I didnt get any help.
On summary, I am trying to navigate between fragments in Android Studio, using Navigation View. I want to go from Home Fragment to Services Fragment.
The first Home Fragment always load, but when I click on Services item, the fragment Services load, but the data from Home always keeps on the fragment too.
This is my code:
HOME FRAGMENT CLASS
public class HomeFragment extends Fragment {
private HomeViewModel homeViewModel;
private PieChart pieChart;
private UserService userService;
private Calendar calendar;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
homeViewModel = ViewModelProviders.of(this).get(HomeViewModel.class);
View root = inflater.inflate(R.layout.fragment_home, container, false);
pieChart = root.findViewById(R.id.pieChart);
userService = UserRepository.getUserService();
getData();
return root;
}
private void getData(){
calendar = Calendar.getInstance();
int month = calendar.get(Calendar.MONTH)+1;
Log.i("INT MONTH", String.valueOf(month));
userService.getHoursPerService(String.valueOf(UserCache.empleado.getId_emp()),String.valueOf(month)).enqueue(new Callback<List<Servicio>>() {
#Override
public void onResponse(Call<List<Servicio>> call, Response<List<Servicio>> response) {
if(response.body().size() == 0){
pieChart.setNoDataText("Sin horas actuales.");
pieChart.setNoDataTextColor(ContextCompat.getColor(getContext(), R.color.colorPrimaryDark));
pieChart.invalidate();
}else{
List<Servicio> list = response.body();
List<PieEntry> pieEntries = new ArrayList<>();
for(int cont=0;cont<list.size();cont++){
pieEntries.add(new PieEntry(list.get(cont).getTotalHoras(), list.get(cont).getLugarServicio()));
}
SimpleDateFormat sdf = new SimpleDateFormat("MMMM");
String actual_month = sdf.format(calendar.getTime());
PieDataSet dataSet = new PieDataSet(pieEntries, getResources().getString(R.string.txt_hours_of)+" "+actual_month);
dataSet.setSliceSpace(3f);
dataSet.setSelectionShift(5f);
dataSet.setColors(ColorTemplate.MATERIAL_COLORS);
PieData data = new PieData(dataSet);
data.setValueTextSize(10f);
data.setValueTextColor(ContextCompat.getColor(getContext(), R.color.colorPrimaryDark));
pieChart.getDescription().setEnabled(true);
pieChart.getDescription().setText(getResources().getString(R.string.txt_hours_of)+" "+actual_month+".");
pieChart.getDescription().setTextSize(12f);
pieChart.getDescription().setTextColor(ContextCompat.getColor(getContext(), R.color.colorPrimaryDark));
pieChart.setExtraOffsets(5, 10, 5, 5);
pieChart.setDragDecelerationFrictionCoef(0.99f);
pieChart.setDrawHoleEnabled(true);
pieChart.setHoleColor(Color.WHITE);
pieChart.setTransparentCircleRadius(61f);
pieChart.animateY(2000, Easing.EaseInOutCubic);
pieChart.setEntryLabelColor(ContextCompat.getColor(getContext(),R.color.colorPrimaryDark));
pieChart.setData(data);
pieChart.invalidate();
}
}
#Override
public void onFailure(Call<List<Servicio>> call, Throwable t) {
}
});
}
}
SERVICES FRAGMENT CLASS
public class ServicesFragment extends Fragment {
private ServicesViewModel servicesViewModel;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
servicesViewModel = ViewModelProviders.of(this).get(ServicesViewModel.class);
View root = inflater.inflate(R.layout.fragment_myservices, container, false);
final TextView textView = root.findViewById(R.id.text_gallery);
servicesViewModel.getText().observe(this, new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
textView.setText(s);
}
});
return root;
}
}
MAIN ACTIVITY
public class MainActivityView extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
private AppBarConfiguration mAppBarConfiguration;
private NavigationView navigationView;
private ActionBarDrawerToggle toggle;
private TextView userNameNav;
private TextView userEmailNav;
private DrawerLayout drawer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_view);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
/*FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});*/
drawer = findViewById(R.id.drawer_layout);
navigationView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_myservices, R.id.nav_startservice)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
View headerView = navigationView.getHeaderView(0);
navigationView.setNavigationItemSelectedListener(this);
userNameNav = headerView.findViewById(R.id.userNameNav);
userEmailNav = headerView.findViewById(R.id.userEmailNav);
userNameNav.setText(UserCache.empleado.getNombre()+" "+UserCache.empleado.getApellidos());
userEmailNav.setText(UserCache.empleado.getEmail());
navigationView.bringToFront();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_activity_view, menu);
return true;
}
#Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
#Override
public void onBackPressed() {
if(drawer.isDrawerOpen(GravityCompat.START)){
drawer.closeDrawer(GravityCompat.START);
}else{
AlertDialog.Builder alerta = new AlertDialog.Builder(this);
alerta.setTitle(getResources().getString(R.string.txt_dialog_exit_app));
alerta.setPositiveButton(getResources().getString(R.string.txt_yes_option), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
finish();
}
});
alerta.setNegativeButton(getResources().getString(R.string.txt_no_option), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
alerta.show();
}
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
switch (menuItem.getItemId()){
case R.id.nav_home:
getSupportFragmentManager().popBackStack(null,FragmentManager.POP_BACK_STACK_INCLUSIVE);
getSupportFragmentManager().beginTransaction().replace(R.id.nav_host_fragment,new HomeFragment()).commit();
case R.id.nav_myservices:
getSupportFragmentManager().popBackStack(null,FragmentManager.POP_BACK_STACK_INCLUSIVE);
getSupportFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, new ServicesFragment()).commit();
//NavHostFragment.findNavController(new ServicesFragment());
break;
case R.id.nav_startservice:
getSupportFragmentManager().popBackStack(null,FragmentManager.POP_BACK_STACK_INCLUSIVE);
getSupportFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, new StartServiceFragment()).commit();
break;
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
onNavigationItemSelected is where I do the navigation.
I tried everything, changing the ConstraintLayout to Relative, insert the fragments from xml into framelayout...
Also, I am using MVVM.
If more information is needed i can post here then.
PD: Sorry if I posting something wrong, this is my first time here.
SOLUTION: I forgot completly to break the first case onNavigationItemSelected.
I am using an androidx navigation drawer with (fragments), HomeFragment consists of a RecyclerView to show images.
I am trying to call the getMenu() method which updates those images from the MainActivity, but it doesn't work
I have tried to use this MainActivity,but it doesn't work
HomeFragment fragment=new HomeFragment();
fragment.getMenu();
============================HomeFragment================================
public class HomeFragment extends Fragment {
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home, container, false);
recycler_menu = (RecyclerView)view.findViewById(R.id.recycler_menu);
recycler_menu.setLayoutManager(new GridLayoutManager(context,2));
recycler_menu.setHasFixedSize(true);
mService = Common.getAPI();
getMenu();
return view;
}
public void getMenu() {
compositeDisposable.add(mService.getMenu()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Consumer<List<Category>>() {
#Override
public void accept(List<Category> categories) throws Exception {
displayMenuList(categories);
}
}));
}
private void displayMenuList(List<Category> categories) {
MenuAdapter adapter = new MenuAdapter(context,categories);
recycler_menu.setAdapter(adapter);
}
}
============================MainActivity================================
public class MainActivity extends AppCompatActivity {
private AppBarConfiguration mAppBarConfiguration;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
// Passing each menu_action_bar ID as a set of Ids because each
// menu_action_bar should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_send)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
}
#Override
public void onResume() {
super.onResume();
HomeFragment fragment=new HomeFragment();
fragment.getMenu();
}
}
you can't because the method is void and the result is returning back by another method and it's in your fragment.
you should create an interface to pass data from fragment to activity.
HomeFragment:
public class HomeFragment extends Fragment {
private OnAcceptListener listener;
//...
public void getMenu() {
compositeDisposable.add(mService.getMenu()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Consumer<List<Category>>() {
#Override
public void accept(List<Category> categories) throws Exception {
listener.onAccept(categories);
}
}));
}
public void setOnAcceptListener(OnAcceptListener listener) {
this.listener = listener;
}
public interface OnAcceptListener{
void onAccept(List<Category> categories);
}
}
activity:
public class MainActivity extends AppCompatActivity implements HomeFragment.OnAcceptListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//...
HomeFragment homeFragment = new HomeFragment();
homeFragment.setOnAcceptListener(this);
}
#Override
public void onAccept(List<Category> categories) {
//update here
}
}
After migrating my navigation to the new Jetpack Navigation Component, I found that after navigating back and forth using the the libraries, the content/layout of the first two fragments in my ViewPager disappears. After clicking through the tabs, it comes back though.
At first I thought it was because of the errors that I saw in the logcat, but after fixing them, the problem was still there.
Here is the code of my MainActivity:
private Toolbar toolbar;
private NavigationView navigationView;
private DrawerLayout drawerLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindResources();
// Setup Toolbar & Navigation Component
setSupportActionBar(toolbar);
setupNavigation();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_options, menu);
return super.onCreateOptionsMenu(menu);
}
private void setupNavigation() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph())
.setDrawerLayout(drawerLayout)
.build();
NavigationUI.setupWithNavController(toolbar, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
}
Here is the code of my ViewPagerAdapter:
private final List<Fragment> fragmentList = new ArrayList<>();
private final List<String> fragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(#NonNull FragmentManager fm) {
super(fm);
}
public void addFragment(#NonNull Fragment fragment, String title) {
fragmentList.add(fragment);
fragmentTitleList.add(title);
}
#NonNull
#Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
#Override
public int getCount() {
return fragmentList.size();
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return fragmentTitleList.get(position);
}
This is my HomeFragment:
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
bindResources(view);
// ViewPager
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getActivity().getSupportFragmentManager());
viewPagerAdapter.addFragment(new TodayFragment(), getString(R.string.tab_today_title));
viewPagerAdapter.addFragment(new PriorityFragment(), getString(R.string.tab_priority_title));
viewPagerAdapter.addFragment(new PlannedFragment(), getString(R.string.tab_planned_title));
viewPagerAdapter.addFragment(new TasksFragment(), getString(R.string.tab_tasks_title));
viewPager.setAdapter(viewPagerAdapter);
// TabLayout
tabLayout.setupWithViewPager(viewPager);
}
Java: I fixed the problem by replacing
= new ViewPagerAdapter(getActivity().getSupportFragmentManager());
with
= new ViewPagerAdapter(getChildFragmentManager());
Kotlin: By replacing
= ViewPagerAdapter(fragmentManager)
with
= ViewPagerAdapter(childFragmentManager)
I would like to put a fragment inside a custom dialog in activity.
I receive this error:
java.lang.IllegalArgumentException: No view found for id 0x7f0c007e (copyworld.rebootcw:id/container_schedule1) for fragment FragmentGiorno{418215c0 #0 id=0x7f0c007e}
This is my code:
layout.xml
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="200dp"
android:layout_below="#+id/spinner_dialog_schedulazione"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:id="#+id/container_schedule1">
</FrameLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Popup_schedule();
}
//******POPUP PER LA SCHEDULAZIONE******************
public void Popup_schedule() {
dialog_schedule=new Dialog(MainActivity.this);
dialog_schedule.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
dialog_schedule.setContentView(R.layout.dialog_schedule);
dialog_schedule.setCancelable(false);
lp = new WindowManager.LayoutParams();
window = dialog_schedule.getWindow();
lp.copyFrom(window.getAttributes());
lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
dialog_schedule.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
window = dialog_schedule.getWindow();
window.setAttributes(lp);
FragmentGiorno fragment = new FragmentGiorno();
android.support.v4.app.FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.container_schedule1, fragment);
fragmentTransaction.commit();
dialog_schedule.show();
}
}
How I add a fragment inside a custom dialog in MainActivity.java that extend Activity?
Try this
dialog_schedule.findViewById(R.id.container_schedule1)
Instead Of
R.id.container_schedule1
In your Code
If you want to load fragment inside dialog then you can use DialogFragment instead.
Below is the working example of using DialogFragment.
public class Demo extends DialogFragment{
View mainView;
LinearLayout layoutArrow;
Bundle bundle;
ArrayList<BookingDetail> bookingDetails;
View.OnClickListener onClickListener;
public static Demo newInstance(#NonNull ArrayList<BookingDetail> bookingDetails) {
Demo alertPopUpMapReservedBedInfo = new Demo();
Bundle args = new Bundle();
args.putSerializable("bookingDetails", bookingDetails);
alertPopUpMapReservedBedInfo.setArguments(args);
return alertPopUpMapReservedBedInfo;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(STYLE_NO_TITLE, R.style.InvitationDialogWithSimpleAnim);
bundle = getArguments();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mainView = inflater.inflate(R.layout.alert_info, container, false);
getDialog().setCanceledOnTouchOutside(true);
return mainView;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
init();
}
private void init() {
layoutArrow = (LinearLayout) mainView.findViewById(R.id.layoutArrow);
FragmentGiorno fragment = new FragmentGiorno();
android.support.v4.app.FragmentTransaction fragmentTransaction =
this.getChildFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.container_schedule1, fragment);
fragmentTransaction.commit();
}
#Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if(onClickListener!=null){
onClickListener.onClick(null);
}
}
}
And call it by,
Demo newFragment = Demo.newInstance(bookingDetails);
newFragment.show(ft,"dialog");