How to save state of MapView in 3 situation 1) Rotate the device 2) Start new fragment and return to previous 3) Start new Fragment and rotate device. The following code resolves 2 Event:
public void onPause() {
Log.d(TAG, "onPause");
mMapView.onPause();
View view = mActivity.getCurrentFocus();
if (view != null) {
InputMethodManager imm = (InputMethodManager)mActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
super.onPause();
cameraPosition = mGoogleMap.getCameraPosition();
}
#Override
public void onResume() {
Log.d(TAG, "onResume");
super.onResume();
mMapView.onResume();
mMapView.getMapAsync(this);
}
This for 1 event:
#Override
public void onSaveInstanceState(Bundle outState) {
Log.d(TAG, "onSaveInstanceState");
if(mSearchString !=null && !mSearchString.equals("")) {
outState.putString("search", mSearchString);
}
final Bundle mapViewSaveState = new Bundle();
mMapView.onSaveInstanceState(mapViewSaveState);
outState.putBoolean("firstStart", false);
outState.putBundle("mapState", mapViewSaveState);
super.onSaveInstanceState(outState);
}
But in 3 event mMapView == null and NPE. How to solve?
You have to do the two main task while change the orientation of device
1>In activity at manifest file you have to put this code
android:configChanges="keyboardHidden|orientation|screenSize"
2> you have to override
#Override
protected void onSaveInstanceState (Bundle outState) {
super.onSaveInstanceState(outState);
outState.putCharSequence("key", "save the value" );
}
and now check in on create of activity
if(bundle !=null)
{
String saveValue=bundle.getCharSequence("key");
}
now use saveValue after orientation.
If you want to prevent activity from restarting, simply add this to your manifest.
into your activity tag
<activity
android:configChanges="orientation|keyboardHidden|screenSize"
/>
EDIT:
This code will load the layout as per your orientation changes.
Add this code in your activity:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
setContentView(R.layout.landscapeView);
} else {
setContentView(R.layout.portraitView);
}
}
Related
I have simple Fragment and I use RecylerView to list my elements. I want to keep scroll position when I change screen rotation.
Regarding the answer here I added these lines to my Fragment code;
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("position", recyclerView.getVerticalScrollbarPosition());
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null) {
recyclerView.scrollToPosition(savedInstanceState.getInt("position"));
}
}
But I have a special case here. Because I have to refresh my adapter when I rotate my screen. I use these lines to refresh:
#Override
public void onConfigurationChanged(#NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
refreshAdapter();
}
private void refreshAdapter() {
if (adapter != null) {
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
adapter.notifyDataSetChanged();
}
}
When I comment out refreshAdapter(); line, I can keep my scroll position. But I have to use refreshAdapter(); line.
How can I keep my scroll position with these methods ?
I am using XWalkView to show a mobile web site as an application. My problem is when application goes background and comes back it reloads the page it shows. I want to keep it state and continue from that state when it comes from background. Here is my code:
public class MainActivity extends AppCompatActivity {
static final String URL = "https://www.biletdukkani.com.tr";
static final int MY_PERMISSIONS_REQUEST_ACCESS_LOCATION = 55;
static final String SHOULD_ASK_FOR_LOCATION_PERMISSION = "shouldAskForLocationPermission";
static final String TAG = "MainActivity";
static final String COMMAND = "/system/bin/ping -c 1 185.22.184.184";
static XWalkView xWalkWebView;
TextView noInternet;
static Bundle stateBundle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
stateBundle = savedInstanceState.getBundle("xwalk");
}
setContentView(R.layout.activity_main);
initNoInternetTextView();
}
public void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);
stateBundle = savedInstanceState.getBundle("xwalk");
Log.d(TAG, "onRestoreInstanceState");
}
/**
* İnternet yok mesajı gösteren TextVidew'i ayarlar.
*/
private void initNoInternetTextView() {
Log.d(TAG, "initNoInternetTextView");
noInternet = (TextView) findViewById(R.id.no_internet);
if (noInternet != null) {
noInternet.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
checkInternetConnection();
}
});
}
}
/**
* WebView'i ayarlar.
*/
private void initWebView() {
Log.d(TAG, "initWebView");
if (xWalkWebView == null) {
ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar);
xWalkWebView = (XWalkView) findViewById(R.id.webView);
//xWalkWebView.clearCache(true);
xWalkWebView.load(URL, null);
xWalkWebView.setResourceClient(new BDResourceClient(xWalkWebView, progressBar));
}
}
#Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume");
checkLocationPermissions();
checkInternetConnection();
if (xWalkWebView != null && stateBundle != null) {
xWalkWebView.restoreState(stateBundle);
}
}
#Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause");
if (xWalkWebView != null) {
stateBundle = new Bundle();
xWalkWebView.saveState(stateBundle);
}
}
public void onSaveInstanceState(Bundle savedInstanceState) {
Log.d(TAG, "onSaveInstanceState");
// Save the user's current game state
savedInstanceState.putBundle("xwalk", stateBundle);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
#Override
public void onBackPressed() {
Log.d(TAG, "onBackPressed");
if (xWalkWebView != null && xWalkWebView.getNavigationHistory().canGoBack()) {
xWalkWebView.getNavigationHistory().navigate(XWalkNavigationHistory.Direction.BACKWARD, 1);
} else {
super.onBackPressed();
}
}
}
I have also tried to add following lines to manifest but didn't work.
android:launchMode="singleTask"
android:alwaysRetainTaskState="true"
How can i do that?
Thanks in advcance.
One way would be to initialize the view inside a fragment which is set to retain it's instance.
I would like to not reload the RecyclerView after screen rotation from portrait to landscape.
I'm using onSaveInstanceState to save list from adapter, and restore it inside onActivityCreated
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if(mAdapter != null) {
outState.putParcelableArrayList("key", mAdapter.getOriginalList());
}
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if(savedInstanceState != null) {
mList = savedInstanceState.getParcelableArrayList("key");
mAdapter.notifyDataSetChanged();
}
}
But there is problem, the RecyclerView is reconstructed after each screen rotation. What is wrong ?
You need to set adapter on configuration changed programetically then only it can be possible to set data without reloading.
Something like below,
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.main);
if(mAdapter != null)
your_recycle_view.setAdapter(mAdapter);
}
I'm struggling to recover my position in a listview on screen rotation configuration change.
Amongst the many things I've tried I came to this:
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState == null) {
...
mVisibleItem = -1;
} else {
if (savedInstanceState.containsKey(LV_VISIBLE_ITEM)) {
mVisibleItem = savedInstanceState.getInt(LV_VISIBLE_ITEM);
}
}
setRetainInstance(true);
}
and here I'm trying to set the position in the listview
#Override
public void onResume() {
super.onResume();
if (mVisibleItem > 0) {
mlvDictionaryIndex.setSelectionFromTop(mVisibleItem, 0);
}
}
However, much to my surprise, after rotating the screen and watching mVisibleItem gets set with the correct value, in onResume I see that mVisibleItem equals -1. How come?
use onSavedInstanceState to write in the bundle the returned value of ListView.onSaveInstanceState(), and restored it onActivityCreated
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mListView != null) {
outState.putParcelable(LISTVIEW_INTERNAL_STATE_KEY, mListView.onSaveInstanceState());
}
}
after the data are reload then you can call
mListView.onRestoreInstanceState(savedInstanceState.getParcelable(LISTVIEW_INTERNAL_STATE_KEY));
Override onSaveInstanceState such as below"
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt("pos", pos);
}
Then in your onCreate method have read the savedInstanceState to check if this is an orientation change or a new activity.
private int pos = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
//This is a new activity
}else{
pos = savedInstanceState.getInt("");
}
Now you have the position in the list, and you can scroll to this in configuration change.
Maybe after the data in the listview is reloaded,the code below will work.
mlvDictionaryIndex.setSelectionFromTop(mVisibleItem, 0);
So you can use post() method, just like below:
post(new Runnable() {
public void run() {
mlvDictionaryIndex.setSelectionFromTop(mVisibleItem, 0);
}
});
is it possible to detect screen rotation? I mean - rotation only, which is clearly distinguishable from activity initialization from another activity?
The onXxx methods seem not to be useful for this, I have tried adding/removing a flag from the starting Intent (the removing seems not to be reflected, on rotate the flag is there), and have tried adding android:configChanges="orientation" for the activity in the manifest, however the onConfigurationChanged method seems to be called every second rotation... wired.
I guess I am missing something... but haven't found clear solution in the other related threads.
Any ideas?
Manifest:
<activity android:name=".MyActivity" android:configChanges="screenSize|orientation|screenLayout|navigation"/>
Activity:
#Override
public void onConfigurationChanged(Configuration newConfig)
{
Log.d("tag", "config changed");
super.onConfigurationChanged(newConfig);
int orientation = newConfig.orientation;
if (orientation == Configuration.ORIENTATION_PORTRAIT)
Log.d("tag", "Portrait");
else if (orientation == Configuration.ORIENTATION_LANDSCAPE)
Log.d("tag", "Landscape");
else
Log.w("tag", "other: " + orientation);
....
}
try this link also
How do I detect screen rotation
Use onConfigurationChanged method to detect the screen rotation isn't good idea. Configuration Change in this activity wouldn't works correctly when user rotate the screen.
So I use this solution to solve this problem.
public class SampleActivity extends AppCompatActivity {
public static final String KEY_LAST_ORIENTATION = "last_orientation";
private int lastOrientation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
if (savedInstanceState == null) {
lastOrientation = getResources().getConfiguration().orientation;
}
}
#Override
protected void onStart() {
super.onStart();
checkOrientationChanged();
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
lastOrientation = savedInstanceState.getInt(KEY_LAST_ORIENTATION);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(KEY_LAST_ORIENTATION, lastOrientation);
}
private void checkOrientationChanged() {
int currentOrientation = getResources().getConfiguration().orientation;
if (currentOrientation != lastOrientation) {
onScreenOrientationChanged(currentOrientation);
lastOrientation = currentOrientation;
}
}
public void onScreenOrientationChanged(int currentOrientation) {
// Do something here when screen orientation changed
}
}
But code still not good enough to use it in my project, so I applied this code to my own library (https://github.com/akexorcist/ScreenOrientationHelper).
compile 'com.akexorcist:screenorientationhelper:<latest_version>'
You can create base activity class like this
public class BaseActivity extends AppCompatActivity implements ScreenOrientationHelper.ScreenOrientationChangeListener {
private ScreenOrientationHelper helper = new ScreenOrientationHelper(this);
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
helper.onCreate(savedInstanceState);
helper.setScreenOrientationChangeListener(this);
}
#Override
protected void onStart() {
super.onStart();
helper.onStart();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
helper.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
helper.onRestoreInstanceState(savedInstanceState);
}
#Override
public void onScreenOrientationChanged(int orientation) {
}
}
Then extend the activity with this base class
public class MainActivity extends BaseActivity {
...
#Override
public void onScreenOrientationChanged(int orientation) {
// Do something when screen orientation changed
}
}
Done!
Why don't you try this?
in onCreated get the orientation of the phone:
Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
myOrientation = display.getOrientation();
then, override the method onConfigurationChanged and check if the orientation has changed:
#Override
public void onConfigurationChanged(Configuration newConfig) {
if(newConfig.orientation != myOrientation)
Log.v(tag, "rotated");
super.onConfigurationChanged(newConfig);
}
Don't forget to add into the manifest android:configChanges="orientation" in the activity.