How to use Nav Drawer and FragmentActivity together - android

The app won't build properly as I think its looking for fragment cruisespeed_Fragment which is actually a fragmentactivity when building a navigation drawer. The reason cruisespeed_Fragment is a fragment activity is it is a tabbed layout which I put together using this tutorial.
In MainActivity.java:
#Override
public void onNavigationDrawerItemSelected(int position) {
Fragment objFragment = null;
switch (position) {
case 0:
objFragment = new project_Fragment();
break;
case 1:
objFragment = new cruisespeed_Fragment();
break;
case 2:
objFragment = new satflow_Fragment();
break;
case 3:
objFragment = new network_Fragment();
break;
}
// update the main content by replacing fragments
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, objFragment)
.commit();
}
And in cruisespeed_Fragment.java:
public class cruisespeed_Fragment extends FragmentActivity implements ActionBar.TabListener {
private ViewPager viewPager;
private CSPagerAdapter mAdapter;
private ActionBar actionBar;
// Tab titles
private String[] tabs = {"Top Rated", "Games", "Movies"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initilization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new CSPagerAdapter(getFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
}
The error I'm getting is Error:(62, 31) error: incompatible types
required: Fragment
found: cruisespeed_Fragment
For some reason logcat isn't outputting anything at the moment but once I get that sorted again I will update.

Without testing your code personally it's difficult for me to speak conclusively, but my understanding is that FragmentActivity is an Activity used to host an android.support.v4.app.Fragment, not an android.app.Fragment
As such, you wont be able to launch a FragmentActivity with the following code:
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, objFragment)
.commit();
You will need to use an Intent. Also, ensure you are not accidentally mixing support Fragments with regular Fragments. This post goes into good detail on the differences.

FragmentActivity extends Activity and NOT Fragment you need to have your _Fragment() classes extend from some form of Fragment

Related

How to Stop Fragment from Reloading When Changing Tabs?

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.

How to prevent refreshing of webview in navigation drawer

From a while i had been using viewpager to display webview pages in activity, but now i have change from viewpager to navigation drawer with RecyclerView, to display webview, i have multiple webview loading in my activity.
Suppose activity starts on webview 1 and then i click on webview 2 if i go back to webview 1 it will be reloading(refresh) and i want to prevent that from happening.
Please help.
Here is my main activity.
public class MainActivity extends AppCompatActivity implements FragmentDrawer.FragmentDrawerListener {
private Toolbar toolbar;
private FragmentDrawer drawerFragment;
private static String TAG = MainActivity.class.getSimpleName();
#TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.tool_bar);
if (toolbar != null) {
toolbar.setTitle(R.string.app_name);
setSupportActionBar(toolbar);
}
drawerFragment = (FragmentDrawer)
getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
drawerFragment.setUp(R.id.fragment_navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout), toolbar);
drawerFragment.setDrawerListener(this);
displayView(0);
}
#Override
public void onDrawerItemSelected(View view, int position) {
displayView(position);
}
private void displayView(int position) {
Fragment fragment = null;
String title = getString(R.string.app_name);
switch (position) {
case 0:
fragment = new TopRatedFragment();
title = getString(R.string.title_home);
break;
case 1:
fragment = new GamesFragment();
title = getString(R.string.title_friends);
break;
case 2:
fragment = new MoviesFragment();
title = getString(R.string.title_messages);
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container_body, fragment);
fragmentTransaction.commit();
getSupportActionBar().setTitle(title);
}
}
}
Are you saying that you want to restore the same fragment? This is from developer.android.com
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
This enables the back navigation button to restore the same fragment that already loaded the webview. You are creating a new one each time in the switch statement.
Once you get the back button working how you want it you can easily learn how to manually pull the specific fragment off of the stack.
Edit:
I do not think you are refreshing the webview. You are creating a new fragment each time you select an item by calling the empty constructor. You need to only create each fragment one time and then use the same instance of that fragment when you go back to that webview. Using the back stack will enable it to stay loaded while you leave the application and come back to it later.
Also try using the static method YourFragment.newInstance(params) which returns a new instance of YourFragment. Do this instead of the empty constructor, as that is considered incorrect practice.

Dilemma with nested Fragment:eihter "Can not perform this action after onSaveInstanceState" or "Can't retain nested fragments"

I have a FragmentActivity that holds a Fragment(ContainerFragment) with a FragmentStatePagerAdapter that also nested two Fragments (a map and a list). For not getting a nullpointer after orientation change I have to set ContainerFragment setRetainInstance(true) the nested Fragments cannot be setRetainInstance(true), because there would be a exception "Can't retain nested fragments". Everything works fine with orientation change, but when i start a new Detail Fragment from the ListFragement I get "Can not perform this action after onSaveInstanceState"
I searched for answers for both exceptions but nothing worked for me.
in MainActivity:
containerFragment = new ContainerFragment();
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
if (findViewById(R.id.fragment_container) != null) {
transaction
.replace(R.id.fragment_container, containerFragment );
}
transaction.addToBackStack(null);
transaction.commit();
in ContainerFragment:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Retain this fragment across configuration changes.
// If not set, there is a NPE on orientation change
setRetainInstance(true);
// load slide menu items
mTabStrings = getResources().getStringArray(R.array.tabs_array);}
public class MyPagerAdapter extends FragmentStatePagerAdapter {
public MyPagerAdapter (FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
switch (i) {
case 0:
MapFragment mapFragment = (MapFragment ) Fragment
.instantiate(getActivity(),
MapFragment .class.getName());
return mapFragment ;
case 1:
ListFragment listFragment = (ListFragment ) Fragment
.instantiate(getActivity(),
ListFragment .class.getName());
return listFragment ;
default:
ListFragment listFragment = (ListFragment ) Fragment
.instantiate(getActivity(),
ListFragment .class.getName());
return listFragment ;
}
and this method in main activity is triggerd from ListFragment and works before orientation change but not after, with "Can not perform this action after onSaveInstanceState" after transaction.commit()
#Override
public void onItemSelected(int position) {
// Create fragment and give it an argument for the selected article
XYFragment xyFragment = new XYFragment ();
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
// Replace whatever is in the fragment_container view with this
// fragment,
// and add the transaction to the back stack so the user can
// navigate back
if (findViewById(R.id.fragment_container) != null) {
transaction.replace(R.id.fragment_container, xyFragment);
}
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}

Android Studio default "Tabbed Activity", how to swipe through fragments?

Complete beginner here..
I have used the "Tabbed Activity" default from the New Project Wizard.
I am trying to get it to swipe through 3 different fragments, however I simply cant see where to tell the program to do it. Do I load them in as an array, if yes where should I do it and how do I instantiate the different fragments?
Any pointers and/or solutions is very appreciated.
you can create a pager adapter from where you can call fragments based on tabs.
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
// Top Rated fragment activity
return new TopRatedFragment();
case 1:
// Games fragment activity
return new GamesFragment();
case 2:
// Movies fragment activity
return new MoviesFragment();
}
return null;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 3;
}
}
and initialize the tabs values in onCreate method of main activity to get tabs working
private String[] tabs = { "Top Rated", "Games", "Movies" };
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initilization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
}
I know that this question is old, but hopefully it can help someone. This was really frustrating for me as well since I'm trying my best to learn Android but the wizard seems to have provided an incomplete template.
Anyways,
In fragment_main.xml, add some text to the TextView and the pages will show up now that there's content.
<TextView android:id="#+id/section_label" android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Hello World" />

How to set a default fragment in Android Studio Navigation Drawer?

I'm looking for a way to se a default fragment in my navigation drawer which is not the item # 0. I've seen some solutions based on checking if savedInstanceState is null or not but I feel like I don't have access to this in my onNavigationDrawerItemSelected method. Here is my class:
public class Main extends ActionBarActivity
implements NavigationDrawerFragment.NavigationDrawerCallbacks {
/**
* Fragment managing the behaviors, interactions and presentation of the navigation drawer.
*/
private NavigationDrawerFragment mNavigationDrawerFragment;
/**
* Used to store the last screen title. For use in {#link #restoreActionBar()}.
*/
private CharSequence mTitle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNavigationDrawerFragment = (NavigationDrawerFragment)
getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
mTitle = getTitle();
// Set up the drawer.
mNavigationDrawerFragment.setUp(
R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout));
}
#Override
public void onNavigationDrawerItemSelected(int position) {
// update the Main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 0:
fragment = new HomeFragment();
break;
case 1:
fragment = new HomeFragment();
break;
case 2:
fragment = new HomeFragment();
break;
default:
fragment = new DiscoverFragment();
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, fragment).commit();
}
}
The answer is rather simple. Since the DrawerLayout leaves you to manage fragments on your own, you can just use the basic FragmentManager APIs that would be used in a normal FragmentActivity.
I use the following method to make it a little simpler, which will replace the current fragments even if there are none currently added to the container. Just call this method with the fragment you want to be default in your onCreate() method.
public void setFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, fragment)
.commit();
}
Note that it is technically more correct to use .add(fragment) for the first call rather than .replace since you aren't replacing anything, but it really doesn't matter because internally, it basically just removes any existing fragments and adds the new one using .add() for you
http://developer.android.com/reference/android/app/FragmentTransaction.html#replace(int,android.app.Fragment,java.lang.String)

Categories

Resources