I have an activity that opens PreferenceScreen. When I click 'back' - I expect that the preference screen will be closed and I'll go back to the activity, but instead - the current activity is closed and I go back to the previous activity. How can I fix that?
public class MyActivity extends Activity {
//....
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return (new Helper()).onOptionsItemSelected_menu(item,this,mFragmentManager);
}
}
public class Helper {
// ....
public boolean onOptionsItemSelected_menu(MenuItem item, Activity activity, FragmentManager mFragmentManager)
{
switch (item.getItemId()) {
case R.id.action_settings:
MenuHelper.settings(activity, mFragmentManager);
return true;
default:
return onOptionsItemSelected_menu(item, activity, mFragmentManager);
}
}
public static void settings(Activity activity, FragmentManager mFragmentManager) {
FragmentTransaction mFragmentTransaction = mFragmentManager
.beginTransaction();
PrefsFragment mPrefsFragment = new PrefsFragment(activity);
mFragmentTransaction.replace(android.R.id.content, mPrefsFragment);
mFragmentTransaction.commit();
}
public static class PrefsFragment extends PreferenceFragment {
Activity m_activity;
public PrefsFragment(Activity activity)
{
m_activity = activity;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
Daniel's answer is totally correct, though you can achieve same thing just by adding mFragmentTransaction.addToBackStack(null) right before transaction commit.
It looks like your issue is that you're replacing the fragment in the current activity with your Preferences screen.
You will have to re-factor your code a bit, but the key is to open a new Activity for your Preferences screen instead of replacing the fragment in the current Activity. This will add a new Activity to the Back Stack for the Preferences screen, and when you click back, it will pop the Preferences Activity from the Back Stack and return you to the previous Activity as you desire.
Edit: Don't re-factor your code, just do what #GnoX suggests.
For more info, see this guide: http://developer.android.com/guide/components/tasks-and-back-stack.html
Related
My app only has two activities: main and preferences
In the PreferenceActivity (or in my case SettingsActivity), the user can change some stuff, that affects the MainActivity.
This is my SettingsActivity:
public class SettingsActivity extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
public static class SettingsFragment extends PreferenceFragment implements Preference.OnPreferenceChangeListener {
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
return false;
}
}
}
Now I have two issue:
When the user presses the HomeButton the main screen does not seem to call the onCreate so the changed preferences are not loaded in the main activity. What do I need to change, to tell android to call the onCreate function?
Since android nougat there are these "activity-change-animations", so when switching to a new activity, the new screen kind of slides in. But when the user presses the HomeButton the expected animation would be slide out, but it is also slide in. How can I fix that?
Explanation for the first issue:
There's a difference between onCreate and onResume
onCreate: Activity launched for the first time. Here is where you may initialize your stuff.
onResume: User returns to the activity after another activity goes to the background. (onPause is called on the other activity)
For the second issue, try this:
Intent intent = NavUtils.getParentActivityIntent(this);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
NavUtils.navigateUpTo(this, intent);
Instead of
NavUtils.navigateUpFromSameTask(this);
I have a simple problem.
My problem is that I have two activities:
Activity A
Activity B
In Activity A I display 4-5 fragments. That is the main activity (Navigation Drawer) so I display 4-5 fragments in it.
From all fragments it redirects to Activity B.
But I want to display the last opened fragment when I come back from Activity B.
Now it directly opens the first fragment, which is the default. I want to open the last opened fragment when the user returns to the first activity.
Please help me...
You can use onSaveInstanceState in Activity A to save information about last opened fragment and onRestoreInstanceState/onCreate to restore this information. For example:
private static final String LAST_OPENED_FRAGMENT_REF = "LAST_OPENED_FRAGMENT_REF";
private static final int HOME_FRAGMENT = 0;
private static final int OTHER_FRAGMENT = 1;
private int currentOpenedFragment = HOME_FRAGMENT;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
if (savedInstanceState != null) {
currentOpenedFragment = savedInstanceState.getInt(LAST_OPENED_FRAGMENT_REF);
}
if (navigationView != null) {
Fragment fragment = initFragmentByType(currentOpenedFragment);
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit();
setupDrawerContent(navigationView);
}
...
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(LAST_OPENED_FRAGMENT_REF, currentOpenedFragment);
}
private Fragment initFragmentByType(int type) {
switch(type) {
case HOME_FRAGMENT: return new Home();
case OTHER_FRAGMENT: return new Other();
default: throw new IllegalArgumentException("There is no type: " + type);
}
}
And don't forget to update currentOpenedFragment field in onNavigationItemSelected callback.
If your first activity changes with the second one, then fragments of the former activity will destroy themself because of the activity lifecycle.
You should just open first activity using startActivity and store the last active fragment before it goes the letter activity.
You don't use finish while call second activity. For exp: `
Intent i = new Intent(getApplicationContext(), ActivityB.class);
startActivity(i);
//finish(); `
I am working on a project where I have come over a problem. My main activity is a list of sites I need to parse. I am making a preferences window. Inside of it I can choose which sites I want to see in the main activity and which I don't (checkboxes). I also have a couple more preferences (show the images or not) for other activities. The preference activity is accessible from any other activity through the NavigationDrawer. I haven't found a good answer on how to refresh the main page correctly so I have come to a conclusion that I need to restart the activity when I press the back button. The problem is I want to restart the activity that has opened the Preference Activity. Is there a way to pass the class through the intent so that I know what activity I want to open?
create a static activity in preference activity, and assign current activity to it before starting preference activity. and after finishing preference activity refresh current activity
preference Activity
public class PreferenceAtivity extends Activity {
public static Activity currentActivity;
pubic void save(View v) {
finish();
currentActivity.recreate();
}
}
another activity
public class AnotherAtivity extends Activity {
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.preference) {
PreferenceActivity.currentActivity = this;
startAtivity(new Intent(this, PreferenceActivity.class);
return true;
}
return super.onOptionsItemSelected(item);
}
}
I develop an app for video surveillance.
I use preferences to keep cameras settings.
In preferences I create main screen with list of cameras, when user click on current item, it opens subscreen with camera name, ip, port etc.
When user entered camera settings and clicked back button to return to main screen, I need to check that user entered all necessary data - name, ip, port, usr, pwd and if one of parameters missed, the app will show toast with warning.
The question is, how can I determine that user clicked on back button?
In PreferenceFragment, onBackPressed() and onKeyDown() not work, moreover I think it's not correct use this methods in my case...
http://4pda.ru/forum/dl/post/5659206/Screen-Main.gif - Main screen
http://4pda.ru/forum/dl/post/5659204/Screen-Sub.gif - Subscreen
My code:
public class MyFragments extends PreferenceFragment {
....
#Override
public void onCreate(Bundle savedInstanceState) {
root = getPreferenceManager().createPreferenceScreen(getActivity());
setPreferenceScreen(createMyPrefenceScreen());
}
private PreferenceScreen createMyPrefenceScreen() {
for (int i=1; i<=8; i++) {
PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(getActivity());
screen.setKey("screen_name_" + i);
screen.setTitle("Number " + i);
ip = new EditTextPreference(getActivity());
ip.setKey("ip_" + i);
ip.setTitle("IP ");
screen.addPreference(ip);
ip.setSummary(ip.getText());
....
root.addPreference(screen);
}
return root;
}
...
}
You have to implement onBackPressed in your Activity, not in the PreferenceFragment.
Following 2nd answer given to this question:
private final static String TAG_FRAGMENT = "TAG_FRAGMENT";
private void showFragment() {
final Myfragment fragment = new MyFragment();
final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment, fragment, TAG_FRAGMENT);
transaction.addToBackStack(null);
transaction.commit();
}
#Override
public void onBackPressed() {
final Myfragment fragment = (Myfragment) getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT);
if (fragment.insertedDataIsCorrect()) { // HERE you can check for correct data and allow back pressed or not
super.onBackPressed();
}
}
I am using a Fragment class.
I add it using
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Search fragment = new Search(maincontrolActivity.this);
fragmentTransaction.add(R.id.mainLayout,fragment , "MY_FRAG");
fragmentTransaction.commit();
this.FragmentObject = fragment
when I do refresh the control,I recall this code but by passing this.FragmentObject but I think it be garbage collected because the = refere to the same object , and when say add, it free the old fragement which is the same
so do I need a deep copy or any way to refresh ?
any idea
Ok. So what I would do is have an Interface defined and have each Fragment register with the Activity for a callback when the refresh button is clicked. Then in the fragment itself have it refresh its data. If that means getting new data, switch to a ProgressBar, get the data from the server, and repopulate the Views. Here is an entire article on creating Interfaces in Activities and calling Fragments from them.
Here is roughly what your code will look like...
The Activity:
public class RefreshActivity extends Activity implements View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
findViewById(R.id.refresh_button).setOnClickListener(this);
}
public interface OnRefreshPressedListener {
public void onRefreshPressed();
}
#Override
public void onClick(View v) {
((OnRefreshPressedListener)this.FragmentObject).onRefreshPressed();
}
}
The Fragment:
public class Search extends Fragment implements OnRefreshPressedListener {
#Override
public void onRefreshPressed() {
//TODO: Refresh your data!
}
}