android navigation drawer recreating fragments everytime - android

I am loading a simple navigation drawer with 3 fragments inside. When i go to 1st fragment and click a button in that fragment then the buttons background color is changed then i am navigating to second fragment and again i am coming back to the 1st fragment i want my fragment (With color changed button) in the backstack. But it is recreated everytime. I have tried multiple ways no luck. Since i am new to fragments i am stuck with this.
public class SampleActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener, Fragment1.OnFragmentInteractionListener,
Fragment2.OnFragmentInteractionListener, Fragment3.OnFragmentInteractionListener {
static Fragment fragment = null;
private static final String FRAGMENT1_TAG = "FRAGMENT1_TAG";
private static final String FRAGMENT2_TAG = "FRAGMENT2_TAG";
private static final String FRAGMENT3_TAG = "FRAGMENT3_TAG";
#Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sample);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
// getMenuInflater().inflate(R.menu.dashboard, 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);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
int id = item.getItemId();
navigateToFragment(id);
return true;
}
#Override
public void onFragmentInteraction(Uri uri) {
}
public void navigateToFragment(int itemId) {
// Handle navigation view item clicks here.
String FRAGMENT_TAG="";
switch (itemId) {
case R.id.nav_fragment1:
FRAGMENT_TAG = FRAGMENT1_TAG;
fragment = Fragment1.newInstance();
break;
case R.id.nav_fragment2:
FRAGMENT_TAG = FRAGMENT2_TAG;
fragment = Fragment2.newInstance();
break;
case R.id.nav_fragment3:
FRAGMENT_TAG = FRAGMENT3_TAG;
fragment = Fragment3.newInstance();
break;
default:
FRAGMENT_TAG = FRAGMENT1_TAG;
fragment = Fragment1.newInstance();
break;
}
FragmentManager supportFragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
Fragment inputFragment = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG);
if (inputFragment == null) {
fragmentTransaction.replace(R.id.content_frame, fragment, FRAGMENT_TAG).addToBackStack(null).commit();
} else {
fragmentTransaction.replace(R.id.content_frame, inputFragment, FRAGMENT_TAG).addToBackStack(null).commit();
}
DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerLayout.closeDrawer(GravityCompat.START);
}
}

You should add the code of Fragment2.newInstance(); to know better the behaviour.
This code probably solve your problem:
public class SampleActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener, Fragment1.OnFragmentInteractionListener,
Fragment2.OnFragmentInteractionListener, Fragment3.OnFragmentInteractionListener {
static Fragment fragment1 = null;
static Fragment fragment2 = null;
static Fragment fragment3 = null;
private static final String FRAGMENT1_TAG = "FRAGMENT1_TAG";
private static final String FRAGMENT2_TAG = "FRAGMENT2_TAG";
private static final String FRAGMENT3_TAG = "FRAGMENT3_TAG";
#Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sample);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
// getMenuInflater().inflate(R.menu.dashboard, 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);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
int id = item.getItemId();
navigateToFragment(id);
return true;
}
#Override
public void onFragmentInteraction(Uri uri) {
}
public void navigateToFragment(int itemId) {
// Handle navigation view item clicks here.
String FRAGMENT_TAG="";
Fragment fragment = null;
switch (itemId) {
case R.id.nav_fragment2:
FRAGMENT_TAG = FRAGMENT2_TAG;
if(fragment2 == null) fragment2 = Fragment2.newInstance();
fragment = fragment2;
break;
case R.id.nav_fragment3:
FRAGMENT_TAG = FRAGMENT3_TAG;
if(fragment3 == null) fragment3 = Fragment3.newInstance();
fragment = fragment3;
break;
default:
FRAGMENT_TAG = FRAGMENT1_TAG;
if(fragment1 == null) fragment1 = Fragment1.newInstance();
fragment = fragment1;
break;
}
FragmentManager supportFragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
Fragment inputFragment = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG);
if (inputFragment == null) {
fragmentTransaction.replace(R.id.content_frame, fragment, FRAGMENT_TAG).addToBackStack(null).commit();
} else {
fragmentTransaction.replace(R.id.content_frame, inputFragment, FRAGMENT_TAG).addToBackStack(null).commit();
}
DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerLayout.closeDrawer(GravityCompat.START);
}
}
I recommend you to refactor a little bit your code to get a more elegant solution.
Be sure that you're using fragmentTransaction.add() to add a fragment for the first time.

Use stack to keep track on fragment.
Check below link for reference.
https://github.com/rathodchintan/Fragment-Back-Stack
1.do not use replace method if you don't want to reload your fragment.
Instead you it use add method with keeping fragment object in the stack.
if you want to use replace, than check whether fragment is their in the memory by using findFragmentByTag method, and if it's not null use it else create new fragment.

Related

How to implement setDrawerLockMode or disable navigation drawer

I have a navigation drawer activity with fragments within it by using a fragment container. I have three fragments within it and I need one of it named locate_login to not contain my navigation drawer.
MainActivity.java
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); //nav drawer
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Set the fragment initially
locate_login fragment = new locate_login();
android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.commit();
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
public void onSelectFragment(View v){ //ignore this
Fragment newFragment;
if(v == findViewById(R.id.trigger)){
newFragment = new locate_after();
}
else{
newFragment = new locate_before();
}
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
transaction.commit();
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#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, 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);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_camera) {
// Handle the camera action
} else if (id == R.id.nav_gallery) {
} else if (id == R.id.nav_slideshow) {
} else if (id == R.id.nav_manage) {
} else if (id == R.id.nav_share) {
} else if (id == R.id.nav_send) {
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
Here is my locate_login fragment
public class locate_login extends Fragment{
public locate_login () {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.locate_login, container, false);
// Inflate the layout for this fragment
return rootView;
}
}
I will highly appreciate it if the answer will be detailed since I'm a beginner on Android Studio.
Create a class for some constant parameter. Declare some constant variable like:
Let say StringConstant.java :
public static final int LOCK_DRAWER = 1;
public static final int SHOW_DRAWER = 2;
When navigating from the drawer, use an Intent object as:
If you want to show the drawer, use:
intent.putExtra("SHOW_DRAWER", StringConstant.SHOW_DRAWER);
OR
If you do not want to show the drawer, use:
intent.putExtra("SHOW_DRAWER", StringConstant.LOCK_DRAWER);
Retrieve intent from your fragment class, you say locate_login.
int status = getActivity.getIntent().getIntExtra("SHOW_DRAWER", 0);
Check status:
if (status == String.Constant.LOCK_DRAWER){
lockDrawer();
}
public void lockDrawer() {
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
}
To unlock the drawer:
public void unlockDrawer() {
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
}

how to call single fragment from the second navigation drawer activity

I have a main navigation drawer using which I call signin fragment. Also there are other fragment which I can easily call. But when I log in, a second navigation drawer opens up and I am not able to call same fragments which I can easily call while using main navigation drawer.
This is my mainactivity where the navigation drawer being called
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private View.OnClickListener mOnClickListener;
SessionManager session;
private NavigationView navigationView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
session = new SessionManager(getApplicationContext());
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
Fragment homeFragment;
if(!session.isLoggedIn()){
homeFragment = new SigninFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.content_main, homeFragment, String.valueOf(homeFragment.getClass())).addToBackStack(null).commit();
getSupportActionBar().setTitle(getResources().getString(R.string.signin_title));
}
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#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, 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);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
Fragment fr;
FragmentManager supportFragmentManager = getSupportFragmentManager();
ActionBar supportActionBar = getSupportActionBar();
supportActionBar.setTitle("productAga");
int id = item.getItemId();
switch (id){
case R.id.home_nv:
fr = new HomeFragment();
supportFragmentManager.beginTransaction().replace(R.id.content_main, fr, String.valueOf(fr.getClass())).addToBackStack(null).commit();
supportActionBar.setTitle(getResources().getString(R.string.home_title));
break;
case R.id.signup_nv:
fr = new SignupFragment();
supportFragmentManager.beginTransaction().replace(R.id.content_main, fr, String.valueOf(fr.getClass())).addToBackStack(null).commit();
supportActionBar.setTitle(getResources().getString(R.string.signup_title));
/*Intent it = new Intent(getApplicationContext(), SignupActivity.class);
startActivity(it);*/
break;
case R.id.signin_nv:
fr = new SigninFragment();
supportFragmentManager.beginTransaction().replace(R.id.content_main, fr, String.valueOf(fr.getClass())).addToBackStack(null).commit();
supportActionBar.setTitle(getResources().getString(R.string.signin_title));
break;
case R.id.about_nv:
fr = new AboutusFragment();
supportFragmentManager.beginTransaction().replace(R.id.content_main, fr, String.valueOf(fr.getClass())).addToBackStack(null).commit();
supportActionBar.setTitle(getResources().getString(R.string.about_title));
break;
case R.id.logout_nv:
session.logoutUser();
Intent it = new Intent(getApplicationContext(), MainActivity.class);
startActivity(it);
break;
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
Now when I logged in I am using this code and notice there is the same aboutus fragment
public class LoggedinMainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
SessionManager session;
private String gname;
private String gemail;
private static final String TAG = "TAG_LOG_IN" ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_loggedin_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
session = new SessionManager(getApplicationContext());
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawerlg_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_login_view);
navigationView.setNavigationItemSelectedListener(this);
/*Fragment homeFragment;
if(session.isLoggedIn()){
homeFragment = new DashboardFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.content_main, homeFragment, String.valueOf(homeFragment.getClass())).addToBackStack(null).commit();
getSupportActionBar().setTitle(getResources().getString(R.string.signin_title));
}*/
session.checkLogin();
HashMap<String, String> user = session.getUserDetails();
gname = user.get(SessionManager.KEY_NAME);
gemail = user.get(SessionManager.KEY_EMAIL);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.loggedin_main, 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);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
Fragment fr;
FragmentManager supportFragmentManager = getSupportFragmentManager();
ActionBar supportActionBar = getSupportActionBar();
supportActionBar.setTitle("productAga");
int id = item.getItemId();
switch (id){
case R.id.homelg_nv:
fr = new HomeFragment();
supportFragmentManager.beginTransaction().replace(R.id.content_main, fr, String.valueOf(fr.getClass())).addToBackStack(null).commit();
supportActionBar.setTitle(getResources().getString(R.string.home_title));
break;
case R.id.aboutlg_nv:
Log.d(TAG +"_ABOUT", ": about");
fr = new AboutusFragment();
supportFragmentManager.beginTransaction().replace(R.id.content_main, fr, String.valueOf(fr.getClass())).addToBackStack(null).commit();
supportActionBar.setTitle(getResources().getString(R.string.about_title));
break;
case R.id.logout_nv:
session.logoutUser();
Intent it = new Intent(getApplicationContext(), MainActivity.class);
startActivity(it);
break;
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawerlg_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
I am also using session management using sharedpreference in order to log in
Also, I got on the android monitor following error when I click on about us
java.lang.IllegalArgumentException: No view found for id 0x7f0d008a (com.roomi.productagaapplication:id/content_main) for fragment AboutusFragment{35e39e5d #0 id=0x7f0d008a}

Android DrawerLayout does not close untill fragment is replaced

I got a problem that DrawerLayout does not close smoothly and it stops in the middle for a while, it totally closes after finish replacing fragment. In coding I close DrawerLayout before replacing fragment (productList class). In productList class, it calls asynctask to get all the product list from server meanwhile running progress bar. Ideally when user clicks menu, DrawerLayout will close at once and productList fragment will be loading all the product list. It seems to me DrawerLayout close event waits for productList's asynctask. Any suggestion greatly appreciated.
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener, View.OnClickListener {
public String tag = "MainActivity";
Context mContext;
//User Object
User user;
//Control
TextView txtName, txtPosition, txtLogout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
user = Constants.getUser();
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
//NavigationView Header
View headerView = navigationView.getHeaderView(0);
txtName = (TextView) headerView.findViewById(R.id.nav_header_main_name) ;
txtName.setText(user.getName().toString());
txtLogout = (TextView) headerView.findViewById(R.id.nav_header_main_logout);
txtLogout.setOnClickListener(this);
navigationView.setNavigationItemSelectedListener(this);
//Add Menu in navigationView
Menu myMenu = navigationView.getMenu();
myMenu.clear();
myMenu.add(0,Integer.parseInt("01"),0,"Product List");
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#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, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
//close drawer
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
// replace fragment
int id = item.getItemId();
FragmentManager fragmentManager = getSupportFragmentManager();
if(Constants.DEBUG) {
Toast.makeText(mContext, " Menu Id " + String.valueOf(id), Toast.LENGTH_LONG).show();
}
fragmentManager.beginTransaction()
.replace(R.id.container,new productList())
.commit();
return true;
}
#Override
public void onClick(View v) {
//Log out onclick
if(v.getId() == R.id.nav_header_main_logout){
this.finish();
}
}
}
This probably happens beacuse the Navigation Drawer's animation and the creation of the Fragment happens at the same time.
You can solve it by starting your Fragment with a small delay-
handler.postDelayed(new Runnable() {
#Override
public void run() {
// replace fragment
int id = item.getItemId();
FragmentManager fragmentManager = getSupportFragmentManager();
if(Constants.DEBUG) {
Toast.makeText(mContext, " Menu Id " + String.valueOf(id), Toast.LENGTH_LONG).show();
}
fragmentManager.beginTransaction()
.replace(R.id.container,new productList())
.commit();
}
}, 300);

How to show a text from one fragment in another fragment?

I WAS WORKING BY THE EXAMPLE YOU JUST GAVE ME AS DUPLICATE, READ THE ENTIRE POST, TY
I'm making a simple app with sliding menu by using the template provided by android studio. And I have to use fragments to switch between items of the sliding menu.
What I wanna do? (check app design at the bottom)
When I click on button pass data it should set the text in the Fragment B to the text that I entered in a Fragment A but without going directly to the Fragment B. So when I press the button pass data then I wanna go to the sliding menu and select item that containts fragment B and then I wanna see the text from Fragment A. Thanks in advance.
public class MainActivity extends AppCompatActivity implements FragmentA.DataPassListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.nav_camera) {
// Handle the camera action
displayFragmentA();
} else if (id == R.id.nav_gallery) {
displayFragmentB();
} else if (id == R.id.nav_slideshow) {
} else if (id == R.id.nav_manage) {
} else if (id == R.id.nav_share) {
} else if (id == R.id.nav_send) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
});
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#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, 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);
}
#Override
public void passData(String data) {
FragmentB fragmentB = new FragmentB();
Bundle args = new Bundle();
args.putString("data", data);
fragmentB.setArguments(args);
//getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, fragmentB).commit();
//it works with the commented part but I dont wanna go directly to the fragment when I press pass data button
}
public void displayFragmentA() {
FragmentA frag = new FragmentA();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, frag);
fragmentTransaction.commit();
}
public void displayFragmentB() {
FragmentB frag = new FragmentB();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, frag);
fragmentTransaction.commit();
}
}
Fragment A code:
public class FragmentA extends Fragment {
DataPassListener mCallback;
public interface DataPassListener {
public void passData(String data);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Make sure that container activity implement the callback interface
try {
mCallback = (DataPassListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement DataPassListener");
}
}
public FragmentA() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_a, container, false);
final EditText input = (EditText) view.findViewById(R.id.etInputID);
Button passDataButton = (Button) view.findViewById(R.id.bPassDataID);
passDataButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mCallback.passData(input.getText().toString());
}
});
return view;
}
}
Fragment B code:
public class FragmentB extends Fragment {
TextView showReceivedData;
public FragmentB() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_fragment_b, container, false);
showReceivedData = (TextView) view.findViewById(R.id.showReceivedData);
Bundle args = getArguments();
if (args != null) {
showReceivedData.setText(args.getString("data"));
} else {
Toast.makeText(getActivity(), "didnt get the bundle from mainactivity", Toast.LENGTH_LONG).show();
}
return view;
}
}
Design of the app:
If these two fragments use same activity,
to set value to fragment :
getActivity().getIntent().putExtra("key", "value");
To get value from fragment :
getActivity().getIntent().getExtras().getString("key");

Google Navigation Drawer, handling backpress to set correct checked ite

Currently Used Google Navigation Drawer, having some problem when user backpress.
When user backpress, they didn't update menu Item
Example When I click the App. The sequence are A>B>C>B>C ,if I backpress I wanted to be C>B>A. How should I code this way out ?
My code
public class MainActivity extends AppCompatActivity {
private String appTitle;
private Toolbar toolbar;
private NavigationView navigationView;
private DrawerLayout drawerLayout;
private TextView toolbarTitle;
private Fragment fragment;
private FragmentManager fragmentManager;
private Title title;
private MenuItem menuItem2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Actionbar
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbarTitle = (TextView) toolbar.findViewById(R.id.toolbar_title);
toolbarTitle.setTextColor(Color.parseColor("#FFFFFF"));
setTitle("");
fragmentManager = getSupportFragmentManager();
fragment= new HomeFragment();
title = new Title(getApplicationContext());
fragmentManager.beginTransaction().replace(R.id.content_frame,fragment , title.getStrHome()).commit();
navigationView = (NavigationView) findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
menuItem2 = menuItem;
menuItem.setChecked(true);
drawerLayout.closeDrawers();
if (menuItem.getItemId() == R.id.nav_home) {
fragment = new HomeFragment();
appTitle = title.getStrHome();
} else if ((menuItem.getItemId() == R.id.nav_direction)) {
fragment = new DirectionFragment();
appTitle = title.getStrDirection();
} else if ((menuItem.getItemId() == R.id.nav_more)) {
fragment = new MoreFragment();
appTitle = title.getStrMore();
} else if((menuItem.getItemId()==R.id.nav_directory)){
fragment = new DirectoryFragment();
appTitle = title.getStrDirectory();
}
else {
Toast.makeText(getApplicationContext(), "Error", Toast.LENGTH_SHORT).show();
}
replaceFragment(fragment,appTitle);
return true;
}
});
drawerLayout = (DrawerLayout) findViewById(R.id.drawer);
ActionBarDrawerToggle actionBarDrawerToggle =
new ActionBarDrawerToggle
(this,drawerLayout,toolbar,R.string.drawer_open,R.string.drawer_close){
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
}
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
};
drawerLayout.setDrawerListener(actionBarDrawerToggle);
actionBarDrawerToggle.syncState();
}
public void onBackPressed() {
if(drawerLayout.isDrawerOpen(GravityCompat.START)){
drawerLayout.closeDrawer(GravityCompat.START);
}
else {
if (fragmentManager.getBackStackEntryCount() > 0 ){
fragmentManager.popBackStack();
toolbarTitle.setText(appTitle);
menuItem2.setChecked(true);
} else {
finish();
}
}
}
public void replaceFragment(Fragment fragment, String tag){
toolbarTitle.setText(tag);
FragmentTransaction ft = fragmentManager.beginTransaction().replace(R.id.content_frame, fragment, tag);
ft.addToBackStack(tag);
ft.commit();
}
#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_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
As stated on the official page on Android tasks and back stack you can see how you can accomplish your desired behaviour using the FLAG_ACTIVITY_CLEAR_TOP in your Intent flags. This picture demonstrates it very well.
Your regular back button proceeds as:
When you specify this flag, you get a behavior like you need
Edit:
The official documentation states:
FLAG_ACTIVITY_CLEAR_TOP
If the activity being started is already running in the current task, then instead of launching a new instance of that activity, all of the
other activities on top of it are destroyed
This means, there will be no duplicates of your different Activities, and you will have a clean Back Stack.
In your example A>B>C>B>C would not be possible. Instead it would be A>B>C, since B and C already exist in the stack, they will not be added, but replaced instead.
Study the Android Activity Launch Mode.
here is the clear Explanation available.
Just take a look.

Categories

Resources