bottom navigation change orientation with fragments - android

I'm using bottom navigation view and when I change the orientation portrait to landscape. And current item and fragment change to one, but he was two or another. How to save item's position?

You can do something similar to this
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt("SelectedItemId", bottomNavigationView.getSelectedItemId());
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
int selectedItemId = savedInstanceState.getInt("SelectedItemId");
bottomNavigationView.setSelectedItemId(selectedItemId);
}

Related

Whenever i rotate the screen it jumps to main activity screen from fragment screen

I am beginner in android,I created application with fragment.In which when i rotate the screen(when in fragment screen) it leaves that fragment screen and jumps to main activity screen.Why?Please help me to solve this.
My Main activity,
Individualuser_Safmical.java:
public class IndividualUser_Safmical extends AppCompatActivity
{
FragmentManager fm;
#Override
protected void onCreate(Bundle savedInstanceState) {
fm = getFragmentManager();
super.onCreate(savedInstanceState);
setContentView(R.layout.i_activity_safmical);
}
public void shopbycategory(View v) {
fm.beginTransaction().replace(R.id.content_frame, new ShopFragment()).addToBackStack("shop").commit();
}
}
My fragment,ShopFrgment.java:
public class ShopFragment extends Fragment {
FragmentManager fm;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View rootview= inflater.inflate(R.layout.i_fragment_shop,container,false);
String[] list1={"Chemicals","Pigments","Uniforms","Safety Products"};
ListView listView= (ListView) rootview.findViewById(R.id.mainlist);
ArrayAdapter<String> listviewadapter=new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_1,list1);
listView.setAdapter(listviewadapter);
fm =getFragmentManager();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(position==0){
fm.beginTransaction().replace(R.id.content_frame,new Chemical_Fragment()).addToBackStack("shop").commit();
}
if(position==1){
fm.beginTransaction().replace(R.id.content_frame,new Pigments_Fragment()).addToBackStack("shop").commit();
}
if(position==2){
fm.beginTransaction().replace(R.id.content_frame,new Uniforms_Fragment()).addToBackStack("shop").commit();
}
if(position==3){
fm.beginTransaction().replace(R.id.content_frame,new SafetyProducts_Fragment()).addToBackStack("shop").commit();
}
}
});
return rootview;
}
}
You can use onConfigurationChanged
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
Also add this line your manifest
android:configChanges="keyboardHidden|orientation|screenSize"
OR
you can lock your activity to avoid orientation changes by adding this in your manifest
android:screenOrientation="portrait"
Check out saving activity state and restoring it again examples. You must apply your solution there. Here is the official documentation. https://developer.android.com/guide/topics/resources/runtime-changes.html
#Abdul Kawee wrote
Its because on rotating screen activity gets destroyed and recreated
He is right ofcourse. There are two ways you can handle this:
Either Override your Fragment's onConfigurationChanged(), onSaveInstanceState() and onRestoreInstanceState() callback methods.
Or you could add android:configChanges="keyboardHidden|orientation"in your app's manifest file.
For more detail see this SO Answer.

Fragment navigation using activity

I have one activity that contains a view pager with fragments in it. I also have a navigation drawer that has fragments. whenever I'm starting my app, in main activity, I'm adding the first fragment to the fragment manager, so it will shown whenever the app is starting.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
home = new FragmentHome();
mainToolbar = (Toolbar) findViewById(R.id.mainActivityToolBar);
setSupportActionBar(mainToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
if(savedInstanceState == null){
home = new FragmentHome();
FragmentManager manager = getSupportFragmentManager();
// changed the back stack here..
String Tag = "start";
manager.beginTransaction().add(R.id.layout_container, home, Tag).commit();
getSupportActionBar().setTitle("Home");
}
FragmentNavigationDrawer fragmentNavigationDrawer = (FragmentNavigationDrawer) getSupportFragmentManager().findFragmentById(R.id.fragment_contain_drawer);
fragmentNavigationDrawer.setUpDrawer(R.id.fragment_contain_drawer, (DrawerLayout) findViewById(R.id.drawer_layout), mainToolbar);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getSupportFragmentManager().putFragment(outState, "fragment", home);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if(savedInstanceState != null){
home = getSupportFragmentManager().getFragment(savedInstanceState, "fragment");
}
}
#Override
public void changeToolBarTitle(String title) {
getSupportActionBar().setTitle(title);
}
in the navigation drawer adapter I have a method that get the fragments and show or add them when needed. my main problem that I cant figure how to solve is that I'm trying to keep the state of first fragment(which contain a recycler view with array list of custom object), while switching to other fragments in the drawer and display their content
public void onNavigationDrawerItemSelected(int position){
// Add the fragments only once
if (getFragmentManager().findFragmentByTag(navigationDrawerFragmentsTags[position]) == null)
{
fragmentTransaction.add(R.id.layout_container,navigationDrawerFragments[position],navigationDrawerFragmentsTags[position]);
}
// Hiding & Showing fragments
for(int i=0;i<navigationDrawerFragments.length;i++)
{
if(i == position)
{
fragmentTransaction.show(navigationDrawerFragments[i]);
}
else
{
// Check if the fragment is added and then hide it
if (getFragmentManager().findFragmentByTag(navigationDrawerFragmentsTags[i]) != null) {
fragmentTransaction.hide(navigationDrawerFragments[i]);
}
}
}
fragmentTransaction.commit();
}
however the first fragment that was added is always exists beneath the other layers and I cant hide it. i want to keep it state, but also to hide when I'm going to another fragment and I need to keep its content to display the list when the user is going back to this fragment.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_navigation_drawer, container, false);
itemList = (ListView) v.findViewById(R.id.drawer_list_items);
adapter = new NavigationDrawerAdapter(getContext(), R.layout.drawer_item_views, addItemsToList());
itemList.setAdapter(adapter);
itemList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
onNavigationDrawerItemSelected(position);
myDrawerLayout.closeDrawers();
}
});
return v;
}
I tried to use interfaces, I tried to look in google but I cant find an answer to that.
//
to keep the state, add it to backstack
and instead of adding new fragment, just replace your fragment i.e. remove older and then add new one. i.e. fragmentTransaction.replace() instead of fragmentTransaction.add()

How to maintain a button style and click state after screen rotation?

I am trying creating an app on Android. When a user click on a button, the background color of the button changes to red. However, when I rotate the screen, the background color changes back to the original color.
I've used button.setBackgroundResource(R.drawable.button_red) to change the background to red when the user clicked on the button. I am trying to use onSaveInstanceState(Bundle savedInstanceState) to maintain the same background color and clicked state of the button after the screen rotation, but I don't know how to approach this.
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean(ANSWER_ONE_BUTTON_ISCLICKED, true);
super.onSaveInstanceState(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
if (savedInstanceState != null) {
button.setBackgroundResource(R.drawable.button_red);
//some codes to make the button becomes clicked.
}
}
Thanks!
Maintain a boolean that changes on the onClick of the button and save it on onSaveInstanceState like
#Override
public void onSaveInstanceState(Bundle savedInstanceState)
{
savedInstanceState.putBoolean(ANSWER_ONE_BUTTON_ISCLICKED, isButtonOneClicked);
super.onSaveInstanceState(savedInstanceState);
}
and on onCreateView check like this
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState)
{
if (savedInstanceState != null)
{
if (savedInstanceState.containsKey(ANSWER_ONE_BUTTON_ISCLICKED))
{
if (savedInstanceState.getBoolean(ANSWER_ONE_BUTTON_ISCLICKED))
button.setBackgroundResource(R.drawable.button_red);
else
button.setBackgroundResource(R.drawable.original_color);
}
//some codes to make the button becomes clicked.
}
}

Where Fragment save its State when FragmentTransaction.Replace?

Backgroud: i have a menu on the left, and different scrollable contents on the right. i wanted to save the scrolled position. But i failed. Then ...
I have set up a very simple project to test it.
In words, i have a menu on the left, and different contents all holding an <EditText> on the right. (of the same class though, they are of different instances)
In codes, (very simple)
content.xml
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Please save my text ..." />
ContentFragment.java
package ... import ...
public class ContentFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.content, container, false);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
System.out.println("Why this is NOT called ?");
Log.v("onSaveInstanceState()", "outState = " + outState);
}
}
and the program generated MenuFragment.java
package ... import ...
public class MenuFragment extends ListFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, new String[]{"Item 1", "Item 2", "Item 3"}));
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
((MainActivity) getActivity()).click();
}
}
Lastly, our MainActivity.java
package ... import ...
public class MainActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null)
getSupportFragmentManager().beginTransaction()
.add(R.id.menu, new MenuFragment()).commit();
}
public void click() {
getSupportFragmentManager().beginTransaction()
.replace(R.id.content, new ContentFragment() // everytime load a new instance
).addToBackStack(null).commit();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
System.out.println("... and this is NOT called neither :-/");
Log.v("onSaveInstanceState()", "outState = " + outState);
}
}
To test it, please DO NOT rotate your device.
First, choose an item from the menu, then type something in the textbox. Then choose another item and type something again. Repeat for a few times. Then navigate back and ...
you will find your texts previously typed ARE SAVED !!!
It is not surprised that the texts are saved ...
But it is surprised the texts are saved with all the onSaveInstanceState() functions NOT called.
When did Android save them while replaced by FragmentTransaction?
If i want to additionally save some data into each Fragment instance (like the scroll position), where should i put my codes?
By default, Edittext save their own instance. See Yalla T.'s answer.
How to retain EditText data on orientation change?

android : save fields value of tab while changing tabs

I have an Activity A with 2 tabs and each tab have its own Activity (B and C) . Activity B and Activity C each have 2 text fields . I want to save value of these text field in SharedPreferences when user changes tabs.
How can I do this?
What you probably want is save your activity state in onSaveInstanceState instead, like this:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(MY_KEY, myStringValue);
// ...
}
And then in onCreate:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// other stuff...
if(savedInstanceState != null) {
myStringValue = savedInstanceState.getString(MY_KEY);
}
}

Categories

Resources