I've 4 different fragments, however it doesn't show the title for any of the fragments. When i created the fragments, everything was working fine, however now no title shows up on the actionBar. I've done all the changes which i found on the stackoverflow, but non of them worked for me
the code for my main activity is :-
private ActionBar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = getSupportActionBar();
toolbar.setTitle("Home");
loadFragment(new home());
BottomNavigationView navigation = (BottomNavigationView)findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
Fragment fragment;
switch (menuItem.getItemId()){
case R.id.navigation_home:
toolbar.setTitle("Home");
fragment = new home();
loadFragment(fragment);
return true;
case R.id.navigation_dashboard:
toolbar.setTitle("Dashboard");
fragment = new Dashboard();
loadFragment(fragment);
return true;
case R.id.navigation_notifications:
toolbar.setTitle("Notifications");
fragment = new Notification();
loadFragment(fragment);
return true;
case R.id.navigation_profile:
toolbar.setTitle("Profile");
fragment = new Profile();
loadFragment(fragment);
return true;
}
return false;
}
};
private void loadFragment(Fragment fragment){
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_container, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
the code for one of the fragments which contains widgets(Rest of them are yet empty) is below :-
private OnFragmentInteractionListener mListener;
Button AskForHelp, Drafts, LogOut, Settings;
View view;
public Dashboard() {
// Required empty public constructor
}
public static Dashboard newInstance(String param1, String param2) {
Dashboard fragment = new Dashboard();
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) {
view = inflater.inflate(R.layout.fragment_dashboard, container,false);
AskForHelp = (Button)view.findViewById(R.id.askHelp);
AskForHelp.setOnClickListener(this);
Drafts = (Button)view.findViewById(R.id.drafts);
Drafts.setOnClickListener(this);
LogOut = (Button)view.findViewById(R.id.logOut);
LogOut.setOnClickListener(this);
Settings = (Button)view.findViewById(R.id.settings);
Settings.setOnClickListener(this);
return view;
}
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.askHelp:
Intent intent = new Intent(getContext(), Questions.class);
startActivity(intent);
break;
case R.id.drafts:
Toast.makeText(getContext(),"Function not enabled", Toast.LENGTH_SHORT).show();
break;
case R.id.logOut:
Toast.makeText(getContext(),"Function not enabled", Toast.LENGTH_SHORT).show();
break;
case R.id.settings:
Toast.makeText(getContext(),"Function not enabled", Toast.LENGTH_SHORT).show();
break;
}
}
public interface OnFragmentInteractionListener {
void onFragmentInteraction(Uri uri);
}
I've tried almost everything mentioned below. But it's still the same
In fragment just put this line in onCreatView so it will set your fragment title each time when you load your fragment.
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
getActivity().setTitle("you title here");
...
}
Related
I'm making an android application on Java. The problem with this app is that when I'm in the main fragment and press the back button, I want it to go back to login (which happens) but the fields of username and password show the data from the last user and I want those fields to show empty like if the app was restarted.
This is my loginuser function inside of my login class.
public void loginUser() {
String url = MeuSingleton.servidor + "/login";
loginemail = email.getText().toString().trim();
loginpass = pass.getText().toString().trim();
StringRequest stringRequest = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
if (response.length() == 9){
Toast.makeText(Login.this, "Login efectuado com sucesso!", Toast.LENGTH_SHORT).show();
Intent i = new Intent(Login.this, MainActivity.class);
startActivity(i);
} else {
mostrarErro(getString(R.string.tituloerro), getString(R.string.login_errado));
}
} catch (Exception e) {
mostrarErro(getString(R.string.tituloerro), getString(R.string.backenderro));
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
mostrarErro(getString(R.string.tituloerro), getString(R.string.interneterro));
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> map = new HashMap<String, String>();
map.put("email", loginemail);
map.put("password", loginpass);
return map;
}
};
MeuSingleton.getInstance(this).addToRequestQueue(stringRequest);
stringRequest.setRetryPolicy(new DefaultRetryPolicy(350, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
}
And this is my main activity class:
public class MainActivity extends AppCompatActivity implements
NavigationView.OnNavigationItemSelectedListener{
MainFragment mainFragment;
FragmentManager fragmentManager;
FragmentTransaction fragmentTransaction;
DrawerLayout drawer;
NavigationView navigationView;
ActionBarDrawerToggle toggle;
Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
navigationView = findViewById(R.id.nested);
navigationView.setNavigationItemSelectedListener(this);
drawer = findViewById(R.id.drawer);
toggle = new ActionBarDrawerToggle(this,drawer,toolbar,R.string.open,R.string.close);
drawer.addDrawerListener(toggle);
toggle.setDrawerIndicatorEnabled(true);
toggle.syncState();
mainFragment = new MainFragment();
fragmentManager = getSupportFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragmentContainer,mainFragment);
fragmentTransaction.commit();// add the fragment
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
closeDrawer();
if(menuItem.getItemId() == R.id.submeteralerta){
loadFragment(new InsAlertaFragment());
}
if(menuItem.getItemId() == R.id.veralertas){
loadFragment(new SecondFragment());
}
if(menuItem.getItemId() == R.id.logout){
finish();
}
if(menuItem.getItemId() == R.id.sobremim){
loadFragment(new SobreMimFragment());
}
if(menuItem.getItemId() == R.id.ajuda){
loadFragment(new AjudaFragment());
}
return true;
}
private void loadFragment(Fragment secondFragment) {
fragmentManager = getSupportFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragmentContainer,secondFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
private void closeDrawer() {
drawer.closeDrawer(GravityCompat.START);
}
}
And finally my main fragment, which is where I want to press back and go to Login:
public class MainFragment extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main,container,false);
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
}
Thanks for the help!
If you want a Login activity with empty text fields when you go back, you could just clear the text fields out before you launch MainActivity. For example:
Toast.makeText(Login.this, "Login efectuado com sucesso!", Toast.LENGTH_SHORT).show();
email.setText("");
pass.setText("");
Intent i = new Intent(Login.this, MainActivity.class);
startActivity(i);
I've read countless topics regarding saving and retrieving the state of Fragments by now. Unfortunately nothing has worked for me and Bundle savedInstanceState is always returning null. What i wanna do is implement a "shopping cart" which remembers the items the user selected. To make that possible I just want to save one variable of the Fragment and retrieve it once the Fragment is called again.
Not only do I want to make the fragment retain it's state when called from the backstack, but also when opening it from the BottomNavigationView. Or does it even make any difference?
Here is the parent Activity class of all the Fragments:
public class ShopMainViewScreen extends AppCompatActivity implements ShopFragment.OnFragmentInteractionListener, SearchFragment.OnFragmentInteractionListener, ... {
Fragment mContent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity_layout);
loadFragment(new ShopFragment());
mContent = getSupportFragmentManager().findFragmentById(R.id.fragmentplace);
}
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment fragment;
switch (item.getItemId()) {
case R.id.navigation_home:
fragment = new ShopFragment();
loadFragment(fragment);
return true;
case R.id.navigation_search:
fragment = new SearchFragment();
loadFragment(fragment);
return true;
case R.id.navigation_shoppingCart:
fragment = new CartFragment();
loadFragment(fragment);
return true;
case R.id.navigation_settings:
fragment = new SettingsFragment();
loadFragment(fragment);
return true;
}
return false;
}
};
private boolean loadFragment(Fragment fragment) {
if (fragment != null) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragmentplace, fragment)
.addToBackStack(null)
.commit();
}
return false;
}
This is the Fragment containing the variable (mShoppingCart which ought to be stored and retrieved).
public class CartFragment extends Fragment {
private String mTitle;
private int mQuantity;
ArrayList < String > mShoppingCart;
private OnFragmentInteractionListener mListener;
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
Log.i("onSaveInstanceState", "entered");
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putStringArrayList("CART", mShoppingCart);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
Log.i("onActivityCreated", "entered");
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
Log.i("SavedInstanceState", " not null");
mShoppingCart = savedInstanceState.getStringArrayList("CART");
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
Log.i("onCreate", "entered");
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mTitle = getArguments().getString("PRODUCTTITLE");
mQuantity = getArguments().getInt("QUANTITY");
}
if (savedInstanceState == null) {
Log.i("InstanceState", "is null");
mShoppingCart = new ArrayList < > ();
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
validateCart(mTitle, mQuantity);
return inflater.inflate(R.layout.shoppingcart_fragment_layout, container, false);
}
#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;
}
Any help is appreciated.
savedInstanceState is only hydrated during configuration changes or when the app is backgrounded & brought back to the foreground. To save the state of a shopping cart throughout a user's session consider using a view model attached to the parent activity. You could also try persisting the cart in SQLite if you'd like that data to be retained across multiple sessions.
I have a navigation drawer with fragments. At start, I display Home fragment as default.
There are options on navigation menu. In 2 fragments I have SwipeRefreshLayout. Until all recyclerview data are fetched then I display data and invisible SwipeRefreshLayout.
One of these fragments (included SwipeRefReshLayout) works fine but, in Home fragment something is wrong.
For example(use case)
You started app and you saw Home fragment
You clicked Profile fragment on navigation menu
You run onBackPressed(back button).
In this case data never loads and SwipeRefReshLayout is always spinning. (I also tried without refreshlayout, still same)
Any idea how to fix this? My thought is, its about displaying default fragment.
Navigation Drawer Activity
public class Page_Navigation extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
Fragment fragment;
FragmentManager fragmentManager = getSupportFragmentManager();
NavigationView navigationView;
SharedPreferences mSharedPref;
DrawerLayout drawer;
private Tracker mTracker;
FragmentTransaction fragmentTransaction;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_page__navigation);
//
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
TextView toolbar_head = findViewById(R.id.toolbar_head);
ImageView toolbar_image = findViewById(R.id.toolbar_image);
ImageView toolbar_profile = findViewById(R.id.toolbar_profile);
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
//
AnalyticsApplication application = (AnalyticsApplication) getApplication();
mTracker = application.getDefaultTracker();
mTracker.setScreenName("page_navigation");
mTracker.send(new HitBuilders.ScreenViewBuilder().build());
//FIRST SETTINGS
setSupportActionBar(toolbar);
Typeface customFont = Typeface.createFromAsset(getAssets(), "Montserrat-Medium.ttf");
toolbar_head.setTypeface(customFont);
//Get Sessions
mSharedPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
String session_user_name = mSharedPref.getString("session_user_name", "");
String session_user_photo = mSharedPref.getString("session_user_photo", "");
//Navigation Drawer
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
navigationView.setItemIconTintList(null);
//
View headerView = navigationView.getHeaderView(0);
TextView nav_userName = (TextView) headerView.findViewById(R.id.textView_nav_userName);
CircleImageView imageView_navigation = (CircleImageView) headerView.findViewById(R.id.imageView_navigation);
Glide.with(getApplicationContext()).load(session_user_photo).into(imageView_navigation);
nav_userName.setText(session_user_name);
headerView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (drawer.isDrawerOpen(Gravity.START)) {
drawer.closeDrawer(Gravity.START);
}
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
showProfileFragment();
}
}, 300);
}
});
toolbar_image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
drawer.openDrawer(GravityCompat.START);
}
});
toolbar_profile.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment fragment;
FragmentManager manager = getSupportFragmentManager();
fragment = new Nav_Profile();
fragmentTransaction = manager.beginTransaction();
fragmentTransaction.replace(R.id.navContent, fragment).addToBackStack(null).commit();
}
});
displayDefaultFragment();
}
#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.page__navigation, 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.
final int id = item.getItemId();
drawer.closeDrawer(GravityCompat.START);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
switch (id) {
case R.id.nav_home:
fragment = new Nav_Home();
break;
case R.id.nav_contact:
fragment = new Nav_Contact();
break;
case R.id.nav_articles:
fragment = new Nav_Article();
break;
case R.id.nav_about:
fragment = new Nav_AboutUs();
break;
case R.id.nav_suggest:
fragment = new Nav_Suggest();
break;
case R.id.nav_share:
fragment = new Nav_Share();
break;
case R.id.nav_rateApp:
fragment = new Nav_RateApp();
break;
}
fragmentManager.beginTransaction()
.replace(R.id.navContent, fragment)
.addToBackStack(null)
.commit();
}
}, 350);
return true;
}
public void displayDefaultFragment() {
fragment = new Nav_Home();
fragmentManager.beginTransaction().replace(R.id.navContent, fragment).commit();
}
public void showProfileFragment() {
fragment = new Nav_Profile();
fragmentManager.beginTransaction().replace(R.id.navContent, fragment).addToBackStack(null).commit();
}
}
Home Fragment
public class Nav_Home extends Fragment implements View.OnClickListener{
SharedPreferences mSharedPref;
private SwipeRefreshLayout swipeRefresh_home;
private CardView item_homeTop_coupons, item_homeTop_draws, item_homeTop_event;
private LinearLayout layout_all_article, layout_all_999;
private ScrollView shimmer_home;
private List<Model_ListItem> listNewItems;
private RecyclerView recyclerView_item_home;
private List<Model_Article> articleList;
private RecyclerView recyclerView_article_home;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fetchItemsNew();
fetchArticlesNew();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_nav__home, container, false);
item_homeTop_coupons = view.findViewById(R.id.item_homeTop_coupons);
item_homeTop_draws = view.findViewById(R.id.item_homeTop_draws);
item_homeTop_event = view.findViewById(R.id.item_homeTop_event);
recyclerView_item_home = view.findViewById(R.id.recyclerView_item_home);
recyclerView_article_home = view.findViewById(R.id.recyclerView_article_home);
layout_all_article = view.findViewById(R.id.layout_all_article);
layout_all_999 = view.findViewById(R.id.layout_all_999);
swipeRefresh_home = view.findViewById(R.id.swipeRefresh_home);
shimmer_home = view.findViewById(R.id.shimmer_home);
item_homeTop_coupons.setOnClickListener(this);
item_homeTop_draws.setOnClickListener(this);
item_homeTop_event.setOnClickListener(this);
layout_all_999.setOnClickListener(this);
layout_all_article.setOnClickListener(this);
//first settngs
mSharedPref = PreferenceManager.getDefaultSharedPreferences(view.getContext());
String session_user_email = mSharedPref.getString("session_user_email","");
swipeRefresh_home.setRefreshing(true);
return view;
}
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.item_homeTop_coupons:
startActivity(new Intent(getContext(), Page_Coupon.class));
break;
case R.id.item_homeTop_draws:
startActivity(new Intent(getContext(), Page_Draw.class));
break;
case R.id.item_homeTop_event:
startActivity(new Intent(getContext(), Page_Event.class));
break;
case R.id.layout_all_999:
//999 city search activity
startActivity(new Intent(getContext(), Page_SearchCity.class));
break;
case R.id.layout_all_article:
//article fragment
Fragment fragment;
FragmentManager fragmentManager = getFragmentManager();
fragment = new Nav_Article();
fragmentManager.beginTransaction().replace(R.id.navContent, fragment).addToBackStack(null).commit();
break;
}
}
public void fetchItemsNew(){
listNewItems = new ArrayList<>();
API_Service api_service = Client.getRetrofitInstance().create(API_Service.class);
Call<List<Model_ListItem>> call = api_service.fetchItemsNew();
call.enqueue(new Callback<List<Model_ListItem>>() {
#Override
public void onResponse(Call<List<Model_ListItem>> call, Response<List<Model_ListItem>> response) {
if(response.code() == 200){
listNewItems = response.body();
Adapter_HomeItem adapter_homeItem = new Adapter_HomeItem(getContext(), listNewItems);
LinearLayoutManager layoutManager
= new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
recyclerView_item_home.setHasFixedSize(true);
recyclerView_item_home.setLayoutManager(layoutManager);
recyclerView_item_home.setAdapter(adapter_homeItem);
SnapHelper helper = new LinearSnapHelper();
helper.attachToRecyclerView(recyclerView_item_home);
}
}
#Override
public void onFailure(Call<List<Model_ListItem>> call, Throwable t) {
}
});
}
public void fetchArticlesNew(){
articleList = new ArrayList<>();
API_Service api_service = Client.getRetrofitInstance().create(API_Service.class);
Call<List<Model_Article>> callArticle = api_service.fetchArticlesNew();
callArticle.enqueue(new Callback<List<Model_Article>>() {
#Override
public void onResponse(Call<List<Model_Article>> call, Response<List<Model_Article>> response) {
if(response.code() == 200){
articleList = response.body();
Adapter_HomeArticles adapter_homeArticles = new Adapter_HomeArticles(getContext(), articleList);
LinearLayoutManager layoutManager
= new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
recyclerView_article_home.setLayoutManager(layoutManager);
recyclerView_article_home.setHasFixedSize(true);
recyclerView_article_home.setAdapter(adapter_homeArticles);
}
}
#Override
public void onFailure(Call<List<Model_Article>> call, Throwable t) {
}
});
}
}
Firstly you must disable SwipeRefreshLayout spinning when successfully or not fetched data:
swipeRefresh_home.setRefreshing(false);
If you do not do this spinner will be spinning all the time.
Another problem is that you have one fragment and you try to assign to it Nav_Home fragment and Nav_Profile fragment.
Fragment fragment;
public void displayDefaultFragment() {
fragment = new Nav_Home();
fragmentManager.beginTransaction().replace(R.id.navContent, fragment).commit();
}
public void showProfileFragment() {
fragment = new Nav_Profile();
fragmentManager.beginTransaction().replace(R.id.navContent, fragment).addToBackStack(null).commit();
}
Try to separate them and show like this:
Fragment homeFragment;
Fragment profileFragment;
public void displayDefaultFragment() {
homeFragment = new Nav_Home();
fragmentManager.beginTransaction().replace(R.id.navContent, homeFragment).commit();
}
public void showProfileFragment() {
profileFragment = new Nav_Profile();
fragmentManager.beginTransaction().replace(R.id.navContent, profileFragment).addToBackStack(null).commit();
}
This is the first time I work with Fragments and I don't understand very well how to manage them. In this case I have two fragments that I show dinamically in a FrameLayout with id fragment_place. The issue is probably with the fragmentTransaction(addtobackstack / popbackstack).
In Fragment2 I show a popupmenu when I press the menubutton on the mobile and it works as expected the first time, but after I go back to the previous fragment and return to fragment2 now If I press the menubutton I get the following error
java.lang.NullPointerException
at android.support.v7.view.menu.MenuBuilder.<init>(MenuBuilder.java:216)
at android.support.v7.widget.PopupMenu.<init>(PopupMenu.java:103)
at android.support.v7.widget.PopupMenu.<init>(PopupMenu.java:78)
at android.support.v7.widget.PopupMenu.<init>(PopupMenu.java:63)
at package.Fragment2.showPopup(Fragment2.java:93)
Below is the code for the mainactivity and fragment2, this is driving me crazy, any help will be much appreciated.
public class MainActivity extends AppCompatActivity implements Fragment1.onEvent {
Fragment1 frag;
Fragment2 frag2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
frag = new Frag1();
// Begin the transaction
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment_place, frag);
ft.commit();
}
#Override
public void onEventSelected(String key) {
frag2 = new Frag2();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment_place,frag2);
ft.addToBackStack(null);
ft.commit();
}
#Override
public void onBackPressed(){
FragmentManager ft = getSupportFragmentManager();
if (ft.getBackStackEntryCount() > 0) {
ft.popBackStack();
} else {
super.onBackPressed();
}
}
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
int action = event.getAction();
int keyCode = event.getKeyCode();
switch (keyCode) {
case KeyEvent.KEYCODE_MENU:
if (action == KeyEvent.ACTION_UP) {
Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_place);
if (f instanceof Fragment2) {
sendBroadcast();
}
}
return true;
default:
return super.dispatchKeyEvent(event);
}
}
private void sendBroadcast(){
Intent intent = new Intent("popup_menu");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}}
This is the problematic fragment. The error lines are basically the method showPopup
public class Fragment2 extends Fragment {
private String key;
private View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment, parent, false);
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mMessageReceiver,
new IntentFilter("popup_menu"));
return view;
}
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
showPopup(view);
}
};
public void showPopup(View v) {
Button b = (Button) view.findViewById(R.id.b_attach);
PopupMenu popup = new PopupMenu(getActivity(), b);
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
//dosomething
}
});
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.menu_popup, popup.getMenu());
popup.show();
}}
this is the way i do and it works for me:
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame,new fragment() ).commit();
I solved the issue getting rid of sendbroadcast() and broadcastReceiver(), instead of that now I call showPopup() directly from the mainActivity when I need it.
I'm a beginner with java and android development but managed to create a navigation drawer activity which switches between five fragment with ListViews using AsycTask. The AsycTask starts again when ever I switch between the fragments. I have gone through many of the post here but none seems to work. Any help.
Here is My Navigation Drawer Activity
public class Home extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private static String website = "https://www.website.com", fbPage = "https://www.facebook.com",
twitter = "https://twitter.com",
private android.support.v4.app.FragmentManager fragmentManager;
private android.support.v4.app.FragmentTransaction fragmentTransaction;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_holder, new HomeFragment(), "Home Fragment")
.commit();
fragmentManager = getSupportFragmentManager();
}
private void customNavgation() {
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
navigationView.getMenu().getItem(0).setChecked(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();
}
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_home) {
HomeFragment homeFragment = new HomeFragment();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_holder, homeFragment, "HomeFragment");
fragmentTransaction.commit();
} else if (id == R.id.nav_message) {
MessageFragment messageFragment = new MessageFragment();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_holder, messageFragment, "MessageFragment");
fragmentTransaction.commit();
} else if (id == R.id.nav_word) {
WordFragment wordFragment = new WordFragment();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_holder, wordFragment, "WordFragment");
fragmentTransaction.commit();
} else if (id == R.id.nav_events) {
EventsFragment eventsFragment = new EventsFragment();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_holder, eventsFragment, "EventsFrangment");
fragmentTransaction.commit();
} else if (id == R.id.nav_service) {
ServiceFragment serviceFragment = new ServiceFragment();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_holder, serviceFragment, "Service Fragment");
fragmentTransaction.commit();
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
And here is one of my Fragment class
public class EventsFragment extends Fragment {
ArrayList<EventsFields> eventsFieldsList;
private ListView eventlist;
static final String EVENT_LINK = "http:www.website.com";
private ProgressBar pb;
private View view;
public EventsFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_events, container, false);
eventlist = (ListView) view.findViewById(R.id.event_frag_listView);
pb = (ProgressBar) view.findViewById(R.id.progressBar);
pb.setVisibility(View.INVISIBLE);
if (isOnline()) {
requestData(EVENT_LINK);
} else {
Toast.makeText(EventsFragment.this.getActivity(), "No Internet Connection", Toast.LENGTH_LONG).show();
}
return view;
}
protected void updateDisplay() {
EventsListAdapter adapter = new EventsListAdapter(EventsFragment.this.getActivity(), R.layout.event_list_layout, eventsFieldsList);
eventlist.setAdapter(adapter);
eventlist.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(EventsFragment.this.getActivity(), EventDetail.class);
EventsFields selectedEvent = eventsFieldsList.get(position);
intent.putExtra("selectedEvent", selectedEvent);
startActivity(intent);
}
});
}
private void requestData(String uri) {
MyTask task = new MyTask();
task.execute(uri);
}
protected boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netinfo = cm.getActiveNetworkInfo();
if (netinfo != null && netinfo.isConnectedOrConnecting()) {
return true;
} else {
return false;
}
}
public class MyTask extends AsyncTask<String, String, ArrayList<EventsFields>> {
#Override
protected void onPreExecute() {
pb.setVisibility(View.VISIBLE);
}
#Override
protected ArrayList<EventsFields> doInBackground(String... params) {
String data = HttpManager.getData(params[0]);
eventsFieldsList = EventsJsonParser.parseFeed(data);
return eventsFieldsList;
}
#Override
protected void onPostExecute(ArrayList<EventsFields> results) {
pb.setVisibility(View.INVISIBLE);
if (results == null) {
Toast.makeText(EventsFragment.this.getActivity(), "Web service not available", Toast.LENGTH_LONG).show();
return;
}
eventsFieldsList = results;
updateDisplay();
}
}
JsonPaser Class
public class EventsJsonParser {
public static ArrayList<EventsFields> parseFeed(String content) {
try {
JSONArray ar = new JSONArray(content);
ArrayList<EventsFields> eventList = new ArrayList<>();
for (int i = 0; i < ar.length(); i++) {
JSONObject obj = ar.getJSONObject(i);
EventsFields events = new EventsFields(null);
events.setId(obj.getInt("id"));
events.setEventName(obj.getString("EventName"));
events.setStartDate(obj.getString("StartDate"));
events.setEventDesc(obj.getString("EventDesc"));
events.setTime(obj.getString("Time"));
events.setVenue(obj.getString("Venue"));
eventList.add(events);
}
return eventList;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Thanks
One approach is to persist the data and then don't call the AsyncTask if you've already received the data.
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putParcelableArrayList("eventsFieldsList", eventsFieldsList);
super.onSaveInstanceState(outState);
}
then in onCreateView():
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_events, container, false);
eventlist = (ListView) view.findViewById(R.id.event_frag_listView);
pb = (ProgressBar) view.findViewById(R.id.progressBar);
pb.setVisibility(View.INVISIBLE);
if (savedInstanceState != null) {
eventsFieldsList = savedInstanceState.getParcelableArrayList("eventsFieldsList");
}
if (eventsFieldList == null) {
if (isOnline()) {
requestData(EVENT_LINK);
} else {
Toast.makeText(EventsFragment.this.getActivity(), "No Internet Connection", Toast.LENGTH_LONG).show();
}
}
return view;
}
You would need to make your EventsFields class implement Parcelable. There are lots of online tutorials and SO answers on this. If you have problems with implementing Parcelable, post a new question.