All data from that ListView is provided by a CursorAdapter.
Whenever I pressed back button and return to activity, then click on the activity to start my fragment, all previous data still there stacking on top of each other.
1) Create an interface BackPressedListener:
public interface BackPressedListener {
void onBackPressed();
}
2) In your activity, you can override onBackPressed():
#Override
public void onBackPressed() {
List<Fragment> fragmentList = getSupportFragmentManager().getFragments();
if (fragmentList != null) {
for(Fragment fragment : fragmentList){
if(fragment instanceof BackPressedListener){
((BackPressedListener)fragment).onBackPressed();
}
}
}
}
3) Implement the interface BackPressedListener, on your fragment. You would override the onBackPressed method in your fragment, clear your list containing the elements and then notify the adapter of the changes as below:
#Override
public void onBackPressed()
{
arrayList.clear();
adapter.notifyDataSetChanged();
finish();
}
Make public a method in fragment which will clear your list and call that method from its parent activity's On onBackPressed using fragment's instance.
When returned to the activity after pressing back button call:
arraylist.clear();
adapter.notifyDataSetChanged();
you can try
try {
arraylist.clear();
listView.removeAllViews();
}catch (Exception e){
}
Related
In my fragment, I have a search bar with a burger menu. When the latter is clicked, the navigation drawer must be opened. But it is defined in the activity.
To access the activity's drawer from my fragment:
I've created an interface containing the method clickOnBurgerMenu
In my activity, I have implemented this interface with a method that opens its drawer
In my activity, I have implemented the method onAttachFragment and here I call the fragment's method setUpMaterialSearchBar
In my fragment: in the method setUpMaterialSearchBar(final ClickOnBurgerMenu activity): I call activity.clickOnBurgerMenu();
But the problem is that in the fragment's method setUpMaterialSearchBar, the call to activity.clickOnBurgerMenu(); is executed in a listener set on the search bar. The latter being defined in the method onCreateView of this fragment.
So when the fragment is attached, the activity executes its setUpMaterialSearchBar method in order to set the listener with the activity's drawer, but the material search bar doesn't exist at this time: the listener is set on a null reference and a NullPointerException is thrown. In other words, more concretly: material_search_bar is defined only in onCreateView, called after the activity's onAttachFragment - that's the problem.
How could I solve this problem?
Sources
The interface
public interface ClickOnMaterialSearchBarBurgerMenu {
void clickOnMaterialSearchBarBurgerMenu();
}
The activity (implementing this interface)
#Override
public void onAttachFragment(Fragment fragment) {
if (fragment instanceof HomeFragment) {
HomeFragment home_fragment = (HomeFragment) fragment;
home_fragment.setUpMaterialSearchBar(this);
}
}
#Override
public void clickOnMaterialSearchBarBurgerMenu() {
drawer_layout.openDrawer(Gravity.START);
}
The fragment (material_search_bar for example is defined only in onCreateView, called after the activity's onAttachFragment - that's the problem)
public void setUpMaterialSearchBar(final ClickOnMaterialSearchBarBurgerMenu activity) {
material_search_bar.setOnSearchActionListener(new SimpleOnSearchActionListener() {
#Override
public void onButtonClicked(int buttonCode) {
switch (buttonCode){
case MaterialSearchBar.BUTTON_NAVIGATION:
activity.clickOnMaterialSearchBarBurgerMenu();
break;
case MaterialSearchBar.BUTTON_BACK:
etc. etc. etc.
In order to untangle your logic, you can introduce a
private SimpleOnSearchActionListener sosActionListener; in HomeFragment.
Change setUpMaterialSearchBar() as follows:
public void setUpMaterialSearchBar(final ClickOnMaterialSearchBarBurgerMenu activity) {
sosActionListener = new SimpleOnSearchActionListener() {
#Override
public void onButtonClicked(int buttonCode) {
switch (buttonCode){
case MaterialSearchBar.BUTTON_NAVIGATION:
activity.clickOnMaterialSearchBarBurgerMenu();
break;
case MaterialSearchBar.BUTTON_BACK:
// etc. etc. etc.
}
}
};
if (material_search_bar != null){
material_search_bar.setOnSearchActionListener(sosActionListener);
}
}
And modify onCreateView() by adding the following line after you initialise material_search_bar
material_search_bar.setOnSearchActionListener(sosActionListener);
I'm building a pretty simple app. At it's core are 2 screens:
1) list-screen: a list of items
2) detail-screen: a detailed view of an item
I used one Activity (which extends AppCompatActivity) with an Action-Bar, a Navigation-Drawer and a main-content part (a FrameLayout).
I used 2 different fragments for the 2 screens:
When opening the app I inflate the list-fragment into the main-content part.
When an item in the list is clicked I inflate the detail-fragment into the main-content part and it all works well.
On the detail-screen I want the Action-Bar to display an up-button that goes back to the list-screen.
Considering the fact that I am using fragments, rather than separate activites, how can I achieve that?
You can enable the up button each time the Detail Fragment loads, and disable it whenever any of the other Fragments load.
First define these methods in your Activity, which you can call from the Fragments in order to show/hide the up button:
public void showUpButton() {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
public void hideUpButton() {
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
}
You will probably want to just enable the up button in on Resume() of the detail Fragment (MainActivity is just an example, change to the name of your Activity) .....
#Override
public void onResume() {
super.onResume();
MainActivity activity = (MainActivity)getActivity();
if (activity != null) {
activity.showUpButton();
}
}
Then in the other Fragments:
#Override
public void onResume() {
super.onResume();
MainActivity activity = (MainActivity)getActivity();
if (activity != null) {
activity.hideUpButton();
}
}
The next thing is to make the up button actually go back. First ensure that you're adding the Fragment with the up button to the back stack, and then add this to that Fragment.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
((MainActivity)getActivity()).onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Then in the Activity, override onBackPressed() and pop from the back stack if the FragmentManager has any entries:
#Override
public void onBackPressed() {
FragmentManager fragmentManager = getSupportFragmentManager();
if (fragmentManager.getBackStackEntryCount() > 1) {
fragmentManager.popBackStackImmediate();
} else {
super.onBackPressed();
}
}
I have one fragment in which a listview is created. When the list is clicked the same list is refreshed and its child elements are loaded on the same. Could anyone please tell me how to enable the backbutton in android to get the parent list?
You can override your activity's onBackPressed() and get the fragment instance by FragmentManager, and do what you want.
Use the method onResume()
#Override
public void onResume() { // TODO Auto-generated method stub
super.onResume();
}
You have to take callback from onBackPressed of Activity to Fragment and check in Fragment if there is child elements open or not.
In Activiity
public void onBackPressed()
{
if(!fragment.onBackPressed())//onBackPressed in fragment is your own function
{
super.onBackPressed();
}
}
In Fragment
public boolean onBackPressed() //your custom onBackPressed not overrided
{
if(childListOpen)
{
//close the child list
return true;
}
else
{
// whatever to do in back pressed of list
return false;
}
}
For your simplicity, Define one static variable in your activity that track the which fragment is currently visible, like
public static fragIndex = 0;
then in your fragment oncreateView before returning view set it accordingly to fragments. like in list view fragment
MainActivity.fragIndex = 0;
and for detailed fragment
MainActivity.fragIndex = 1;
now on your activities onbackpressed method do like
if(fragIndex == 0){
//whatever you want to do.
}else if(fragIndex == 1){
// change the fragment back to list view
}
I have a Activity that transitions between fragments. Fragment 1 to fragment 2. Fragment 1 has a listview. When the user goes to fragment 2 the user has the option to make changes to the data that fills the listview. When the user presses the back button it takes them back to the first fragment. When the user returns the listview has to be updated to show the changes that were made in fragment 2. How can i do this?
Frag2 pfrag = new Frag2();
pfrag.setArguments(bundle);
ft=fm.beginTransaction();
ft.add(R.id.fragment_swap, pfrag,"Profile");
ft.show(pfrag);
ft.addToBackStack("pfrag");
ft.commit();
You would do this by calling notifyDataSetChanged(); on the ListView's adapter.
For more info
You could use Robins answer or if you want to pass the data in fragment 2 to fragment 1 you could call a method in fragment 1 class:
YourFragmentClass.refreshList( your data)
and in Fragment 2 the method:
puplic void refreshList(your data) {
// set the adapter with your data
}
In you fragment, include the code as like below.
(isPaused)boolean variable is used to track current fragment is paused while navigating to next activity.
While resuming back call the webservice (or) call the method to refresh the list by calling notifydatasetchanged() from adapter.
#Override
public void onResume() {
super.onResume();
if(isPaused) {
isPaused=true;
fetchDirectories();
// call the adapter method to notify the data set.
}
}
#Override
public void onPause() {
super.onPause();
isPaused=true;
}
private boolean isPaused=false;
I think the best way to achieve this, is to load the list in the fragment's onResume()-Method. So, the code looks something like this:
#Override
public void onResume() {
super.onResume();
initializeList();
}
...
private void initializeList() {
adapter = new MessageTemplateAdapter(getActivity(), datasource.getTemplateList());
setListAdapter(adapter);
}
I have an Activity with few tabs managed by ViewPager. And there is one tab where i'd like to prevent closing activity when users click BACK button. Instead it loads upper level of data.
So my code in FragmentActivity looks like this
#Override
public void onBackPressed() {
boolean allowQuit = true;
if (mTabsAdapter != null){
if(mTabsAdapter.getItem(mTabsAdapter.selectedTab) instanceof backPressOverrider){
allowQuit = ((backPressOverrider)mTabsAdapter.getItem(mTabsAdapter.selectedTab)).onCustomBackPressed();
}
}
if (allowQuit) {
super.onBackPressed();
}
}
And it works - activity not finished and I see my fragment, but getActivity()in my fragment returns null. None of onDetach,onStop, onDestroy,.. was fired in fragment.
Is there any way to overcome this problem?