I have a BottomNavigationView where I can navigate between fragments. The third fragment is a PreferenceFragment while the other two extend Fragment. I have a simple switch case for replacing fragments but I get an error that SettingsFragment cannot be converted to Fragment.
How can I navigate between these fragments?
BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment selectedFragment = null;
switch (item.getItemId()) {
case R.id.navigation_home:
toolbar.setTitle("Home");
selectedFragment = HomeFragment.newInstance();
break;
case R.id.navigation_dashboard:
toolbar.setTitle("Dashboard");
selectedFragment = DashboardFragment.newInstance();
break;
case R.id.navigation_settings:
toolbar.setTitle("Settings");
selectedFragment = SettingsFragment.newInstance();
break;
}
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragmentContainer, selectedFragment);
transaction.commit();
return true;
}
};
Unless you're using the support preference library, PreferenceFragment extends android.app.Fragment, so you need to also extend android.app.Fragment for your other Fragments.
However, since Fragment and PreferenceFragment have been deprecated in API 28, you might want to just convert to the support Fragment and PreferenceFragmentCompat. Be aware that this will mean any Preference libraries you might be using will probably not work until they've been updated.
Related
I have an Activity with a BottomNavigationView, which consists of 4 Fragments, the Fragments reload whenever I change tabs, this is my Activity's code
public class MainHomeActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_home);
BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation);
bottomNavigationView.setOnNavigationItemSelectedListener(navigationItemSelectedListener);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new HomeFragment()).commit();
}
private BottomNavigationView.OnNavigationItemSelectedListener navigationItemSelectedListener = new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull #NotNull MenuItem item) {
Fragment selectedFragment = null;
switch (item.getItemId()){
case R.id.nav_home:
selectedFragment = new HomeFragment();
break;
case R.id.nav_list:
selectedFragment = new UsersFragment();
break;
case R.id.nav_profile:
selectedFragment = new ProfileFragment();
break;
case R.id.nav_settings:
selectedFragment = new SettingsFragment();
break;
}
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, selectedFragment).commit();
return true;
}
};
}
In the Fragments im loading data from parse
I know that the mistake im doing is that I'm creating a new instance of the Fragment whenever I switch tabs, but I do not how to fix it or where to start from
I saw some people saying that a ViewPagerAdapter should be used in this case but i cant manage to find a place where its explained properly.
Any assistance would be very appreciated!
Here's an article which describes your case perfectly and in detail.
Basically, it creates a fragment for each tab in memory, and saves them as a local variable in the activity:
final Fragment fragment1 = new HomeFragment();
final Fragment fragment2 = new DashboardFragment();
final Fragment fragment3 = new NotificationsFragment();
final FragmentManager fm = getSupportFragmentManager();
Fragment active = fragment1;
You add all 3 fragments to the manager, but hide 2 of them, so only 1 will be visible:
fm.beginTransaction().add(R.id.main_container, fragment3, "3").hide(fragment3).commit();
fm.beginTransaction().add(R.id.main_container, fragment2, "2").hide(fragment2).commit();
fm.beginTransaction().add(R.id.main_container,fragment1, "1").commit();
You implement the OnNavigationItemSelectedListener of the BottomNavigationView, check which item was pressed, and then show that fragment while hiding the previous:
case R.id.navigation_dashboard:
fm.beginTransaction().hide(active).show(fragment2).commit();
active = fragment2;
Instead of replacing the fragment, use add/remove and create a mechanism for adding and removing fragment stack, also it is not recommended but for the sake of question you can create a singleton fragment, instead of using a new Keyword everything tab is changed, along with that you can have a look at pageOffSet
companion object{
private lateinit var INSTANCE?: HomeFragment() = null
}
fun getInstance(): HomeFragment(){
if(INSTANCE == null){
INSTANCE = HomeFragment()
}
return INSTANCE
}
As we know the ViewPager recreates the fragments when we switch the pages with our BottomNavigationView. I know how to prevent this, use one of these 2 Options:
As i can see your amount of fragments is small and fixed, add in your onCreate() of your
MainHomeActivity.java:
mViewPager = (ViewPager)findViewById(R.id.pager);
mViewPager.setOffscreenPageLimit(limit); //limit is a fixed integer
Use a FragmentPagerAdapter as part of your ViewPager. (example provided in link)
UPDATE
In #moalzoabi's case the 2nd option worked. Follow along this post.
I am new to Android Developing and I am trying to create an app based on the BottomNavgiationView. One of the bottom navigation Items have an editText so when I switch to another fragment the previous fragment where I wrote something gets overlapped due to replacing.
This is my OnNavigationItemSelectedListener
private void enableNavigation(){
bottomNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch(item.getItemId()){
case R.id.btnHome:
HomeFragment homeFragment = new HomeFragment();
android.support.v4.app.FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().replace(R.id.container, homeFragment).commit();
return true;
case R.id.btnChats:
ChatsFragment chatsFragment = new ChatsFragment();
android.support.v4.app.FragmentManager manager1 = getSupportFragmentManager();
manager1.beginTransaction().replace(R.id.container, chatsFragment).commit();
return true;
case R.id.btnPost:
PostsFragment postsFragment = new PostsFragment();
android.support.v4.app.FragmentManager manager2 = getSupportFragmentManager();
manager2.beginTransaction().replace(R.id.container, postsFragment).commit();
return true;
case R.id.btnFavourites:;
FavouritesFragment favouritesFragment = new FavouritesFragment();
android.support.v4.app.FragmentManager manager3 = getSupportFragmentManager();
manager3.beginTransaction().replace(R.id.container, favouritesFragment).commit();
return true;
case R.id.btnProfile:
ProfileFragment profileFragment = new ProfileFragment();
android.support.v4.app.FragmentManager manager4 = getSupportFragmentManager();
manager4.beginTransaction().replace(R.id.container, profileFragment).commit();
return true;
}
return false;
}
});
Anyone having any solution please let me Know..
I assume you meant instance. Each time you switch fragment, you make a new instance and open that. So to stop doing that, you have to keep the first instance built and give that to the fragment manager when you want to switch to it.
For example, let's use your ChatFragment.
Instead of inside the switch statement, you put your ChatsFragment chatsfragmentdeclaration to the top of the Activity, so it's an instance-wide variable. Inside your switch statement, instead of building a new instance every time, you go
case R.id.btnChats:
if(chatsFragment == null) chatsFragment = new ChatsFragment();
android.support.v4.app.FragmentManager manager1 = getSupportFragmentManager();
manager1.beginTransaction().replace(R.id.container, chatsFragment).commit();
return true;
Now you only rebuild your fragment once, when it is first called. From then on, the old instance is reused.
I would like to get some input on the best way to structure my app's architecture when using Android's Bottom Navigation View.
Currently I define my BottomNavigationView in my MainActivity. It looks something like this.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView bottomNavigationView = (BottomNavigationView)findViewById(R.id.bottom_navigation);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment selectedFragment = null;
switch (item.getItemId()){
case R.id.action_home:
selectedFragment = HomeFragment.newInstance();
break;
case R.id.action_search:
selectedFragment = SearchFragment.newInstance();
break;
case R.id.action_message:
selectedFragment = MessageFragment.newInstance();
break;
case R.id.action_profile:
selectedFragment = ProfileFragment.newInstance();
break;
}
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_layout, selectedFragment);
transaction.commit();
return true;
}
});
//Manually displaying the first fragment - one time only
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_layout, HomeFragment.newInstance());
transaction.commit();
}
The problem is that once I click on one tab, it opens up a fragment, and I would like to have those Fragments open up other Fragments/Activities (i.e:
I open the profile tab (`ProfileFragment` loads)
I click on a button from `ProfileFragment`, and from this the `SignUpFragment` loads
After running into many bugs, I've researched on how to architect my app, but i've found mixed results. Would anyone know the correct way of using a BottomNavigationView with Fragments, and in those fragments I can load more Activities/fragments. A huge thanks in advance.
Main Activity:
switch (item.getItemId()) {
case R.id.action_item1:
selectedFragment = MeetingsFragment.newInstance();
break;
case R.id.action_item2:
selectedFragment = FriendsFragment.newInstance();
break;
case R.id.action_item3:
selectedFragment = PreferenceFragment.newInstance();
break;
}
//selectedFragment.setArguments(bundle);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_layout, selectedFragment);
transaction.commit();
All the fragments extend android.support.v4.app.Fragment except PreferenceFragment(extends android.preference.PreferenceFragment).
Compiler is looking for android.support.v4.app.Fragment. I want to show preferences in one of the tab. Is their any solution to this?
Let your PreferenceFragment extend PreferenceFragmentCompat.
use PreferenceFragmentCompat which is included in the support-v7 library
this class inherit from Fragment in v4 so it should work for you
I created an activity with a bottom navigation bar.
I googled a lot things about it but now I don't know how to handle this exactly.
Before, I just started another activity when the user clicks the bottom navigation but I think it's not good.
How can I switch between the tabs?
Do I have to work with fragments? And what about 'setContentView(int layoutResID)'? How can I do that? I'm confused...
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
return true;
case R.id.navigation_dashboard:
startActivity(dashboardActivity);
return true;
case R.id.navigation_notifications:
startActivity(dashboardActivity);
return true;
}
return false;
}
};
Thank you very much for your help - I hope, you understood what I mean.
Activity transition is always expensive and we should switch from one activity to another only when we are switching the context. A fragment is a portion of UI in an activity. Same fragment can be used with multiple activities. Just like activity a fragment has its own lifecycle and setContentView(int layoutResID) can be set to different layout in OnCreate of fragment.
This link explains more on when to use activity or fragment.
Android developer guide on Fragments
Code path tutorial on bottom navigation views.
Please refer to :-
https://github.com/waleedsarwar86/BottomNavigationDemo
and complete explanation in
http://waleedsarwar.com/posts/2016-05-21-three-tabs-bottom-navigation/
You will get a running code with the explanation here.
Bottom Navigation View is a navigation bar introduced in android library to make it easy to switch between views with a single tap. It can although be used for almost any purpose, but is most commonly used to switch between fragments with a single tap. Its use for opening activities is somewhat absurd, since it ignores its most important functionality of switching the views with a single tap. There are many good articles and blogs out there in this regard, one of which is:
https://medium.com/#hitherejoe/exploring-the-android-design-support-library-bottom-navigation-drawer-548de699e8e0
Hope this solves your doubt..
bottomNavigationView.setOnNavigationItemSelectedListener
(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment selectedFragment = null;
switch (item.getItemId()) {
case R.id.action_item1:
selectedFragment = ItemOneFragment.newInstance();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_layout, selectedFragment);
transaction.commit();
// selectedFragment.getChildFragmentManager().beginTransaction();
break;
case R.id.action_item2:
selectedFragment = ItemTwoFragment.newInstance();
FragmentTransaction transactiona = getSupportFragmentManager().beginTransaction();
transactiona.replace(R.id.frame_layout, selectedFragment);
transactiona.commit();
// selectedFragment = ItemThreeFragment.newInstance();
break;
case R.id.action_item3:
// selectedFragment = ItemOneFragment.newInstance();
Intent intent=new Intent(MainView.this, YoutActivityLive.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
// selectedFragment = ItemTwoFragment.newInstance();
break;
case R.id.action_item5:
selectedFragment = ItemOneFragment.newInstance();
FragmentTransaction transactionb = getSupportFragmentManager().beginTransaction();
transactionb.replace(R.id.frame_layout, selectedFragment);
transactionb.commit();
// selectedFragment = ItemFiveFragment.newInstance();
break;
}
return true;
}
});