Keep ActionBar from reverting changes - android

I'm using an activity with a webview and to keep it from refreshing whenever the device is rotated, I have android:configChanges="orientation|screenSize" in AndroidManifest.xml. The problem is that whenever the device is rotated, the changes I have made to the status bar dissapear. Does anyone know how to keep the webview from refreshing whenever rotated AND keep the changes I've made in the status bar?
This is the method that I use to make the changes to the statusbar
public static void changeActionBarFont(Activity activity) {
Typeface slab = Typeface.createFromAsset(activity.getAssets(),
"RobotoSlab.ttf");
int actionBarTitle = Resources.getSystem().getIdentifier(
"action_bar_title", "id", "android");
int actionBarSubTitle = Resources.getSystem().getIdentifier(
"action_bar_subtitle", "id", "android");
if (0 == actionBarTitle & 0 == actionBarSubTitle) {
actionBarTitle = com.actionbarsherlock.R.id.abs__action_bar_title;
actionBarSubTitle = com.actionbarsherlock.R.id.abs__action_bar_subtitle;
}
TextView title = (TextView) activity.getWindow().findViewById(
actionBarTitle);
TextView subtitle = (TextView) activity.getWindow().findViewById(
actionBarSubTitle);
if (title != null | subtitle != null) {
title.setTypeface(slab);
subtitle.setTypeface(slab);
subtitle.setTextColor(Color.parseColor("#FFFFFFFF"));
}
}
Edit: Removeing the configChanges from the AndroidManifest does in fact fix the problem with the ActionBar, but I need them to keep the webview from reloading whenever the device is rotated. Anyone have any ideas as to how I can keep them both?

It may not be what you want to hear right now, but it is better to try to recreate the layout in the new orientation, rather than just preventing the orientation change.
In your onCreate check whether there is a saved instance (as a result of the orientation change) e.g.
if (savedInstanceState == null) {
//recreate the current state
}
else {
//normal start
}
You might need to retain some values (either in Shared Prefs or onSavedInstanceState).
This approach is more difficult than locking the orientation, but it is a better approach in the long run and is well worth the investment (extra effort).

Related

VISIBLE EditText goes to INVISBLE on orientation change

I have a spinner that has numbers from 1 - 10. If the user selects anything above 1, a certain EditText that is INVISBLE becomes VISIBLE, this is what I want. But when I change it from portrait to landscape, it goes back to INVISIBLE.
This is where the changing happens
btn_Calc.setOnClickListener(new View.OnClickListener() {
#Override
if (split > 1) {
et_APP.setVisibility(View.VISIBLE);
tv_app.setVisibility(View.VISIBLE);
vis = 1;
}
else{
et_APP.setVisibility(View.INVISIBLE);
tv_app.setVisibility(View.INVISIBLE);
vis = 2;
}
});
And I tried to do onSaveInstanceState like this
if(savedInstanceState != null) {
int isVis = savedInstanceState.getInt("vis", 2);
if(isVis == 1){
et_APP.setVisibility(View.VISIBLE);
tv_app.setVisibility(View.VISIBLE);
}
else{
et_APP.setVisibility(View.INVISIBLE);
tv_app.setVisibility(View.INVISIBLE);
}
}
public void onSaveInstanceState(Bundle savedInstanceState){
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt("getVisible", vis);
}
Sorry for poor formatting, I cut out unrelated code.
It works that if the selected item in the spinner is greater than 1 and I click the calc button, it shows the fields I want but when I change orientation they dissapear again. Any ideas on how I can get to stay visible when I change the orientation?
The names of your keys don't match between save and load.
Saving:
savedInstanceState.putInt("getVisible", vis);
Restoring:
int isVis = savedInstanceState.getInt("vis", 2);
The layout is being recreated if you don't want Android to do anything add the following line:`android:configChanges="keyboardHidden|orientation|screenSize"' to the activity in the manifest.

How EditText Retains its value but not textview when phone orientation changes?

What is so special about Edittext that it can retain the value but not Textview and some other widgets and we have to use onSavedInstance() method for them.
What is the magic behind EditText specially that it can retain the values?
If someone can tell how it works internally.
<----Update---->
How it works internally, Please point to that part of the code which explains this scenario.
What is the magic behind EditText specially that it can retain the
values? How it works internally, Please point to that part of the code
which explains this scenario.
It is the selectable property which brings the difference. The following if condition in TextView.onSaveInstanceState takes care of it.
#Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
// Save state if we are forced to
boolean save = mFreezesText;
int start = 0;
int end = 0;
if (mText != null) {
start = getSelectionStart();
end = getSelectionEnd();
if (start >= 0 || end >= 0) {
// Or save state if there is a selection
save = true;
}
}
...
}
By default TextView can't be selected. Hence getSelectionStart() and getSelectionEnd() returns -1, there by save variable holds false value. To make it retain it's content on orientation change, set the attribute textIsSelectable to true.
Since EditText is selectable by default, getSelectionStart() and getSelectionEnd() always return value >=0, there by save variable holds true value and the content gets saved.
Note : By default freezesText is disabled. Hence mFreezesText value is false.
By default, EditText view saves its state - This is accomplished by setting flags in code telling the view to save state when view is not visible or lost focus. The text is automatically saved and restored after rotating device. The automatic saving of state of EditText view can be disabled in the XML layout file by setting the android:saveEnabled property to false:
android:saveEnabled="false"
Or programmatically, call view.setSaveEnabled(false).
saveEnabled controls whether the saving of this view's state is enabled (that is, whether its onSaveInstanceState() method will be called). Note that even if freezing is enabled, the view still must have an id assigned to it (via setId()) for its state to be saved. This flag can only disable the saving of this view; any child views may still have their state saved. saveEnabled attribute is part of android View - View Code. Here is related parts of code:
public boolean isSaveEnabled() {
return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
}
...
public void setSaveEnabled(boolean enabled) {
setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
}
...
void setFlags(int flags, int mask) {
int old = mViewFlags;
mViewFlags = (mViewFlags & ~mask) | (flags & mask);
int changed = mViewFlags ^ old;
if (changed == 0) {
return;
}
int privateFlags = mPrivateFlags;
/* Check if the FOCUSABLE bit has changed */
if (((changed & FOCUSABLE_MASK) != 0) &&
((privateFlags & HAS_BOUNDS) !=0)) {
if (((old & FOCUSABLE_MASK) == FOCUSABLE)
&& ((privateFlags & FOCUSED) != 0)) {
/* Give up focus if we are no longer focusable */
clearFocus();
} else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
&& ((privateFlags & FOCUSED) == 0)) {
/*
* Tell the view system that we are now available to take focus
* if no one else already has it.
*/
if (mParent != null) mParent.focusableViewAvailable(this);
}
}
....
Quoting from this article:https://tekeye.uk/android/examples/saving-activity-state
"Switching the device from portrait to landscape causes Android to stop and restart the Activity, allowing Activities the opportunity to redraw a screen for the different dimensions. With stopping and starting an Activity a common occurrence users would be annoyed if input kept being lost. Android activites have a pair of methods called onSaveInstanceState(Bundle) and onRestoreInstanceState(Bundle) which are automatically used by input Views to save their data. These methods only work if the Views that take data can be identified, hence the need for the EditText (and all screen items) to have an id. A bonus is that this method pair can be overridden in an Activity so that state variables not associated with input fields can also be saved and restored."
Remove the id from an edittext and try it :)
Try this for your textview I think it may help you
<TextView
...
android:freezesText="true" />
Android View class have protected methods
protected Parcelable onSaveInstanceState ()
protected void onRestoreInstanceState (Parcelable state)
so any view can override those methods and save View's state information with them.
TextView extends View class and have implementation of protected Parcelable onSaveInstanceState() and protected void onRestoreInstanceState (Parcelable state) within it.
lets look at implementation of onSaveInstanceState()
#Override
public Parcelable onSaveInstanceState()
{
Parcelable superState = super.onSaveInstanceState();
// Save state if we are forced to
boolean save = mFreezesText;
int start = 0;
int end = 0;
if (mText != null)
{
start = getSelectionStart();
end = getSelectionEnd();
if (start >= 0 || end >= 0)
{
// Or save state if there is a selection
save = true;
}
}
...
}
as you can see here save feature is depending on single flag "save"
so if user explicitly specify mFreezesText = true then it will save
the text
another possiblity if there is selection cursor then it will at least return getSelectionStart() = 0 and not -1 that will cause TextView to make save=true to save state of TextView and thats what happening with EditText as EditText have selection cursor and it does extends TextView.

Application label font not preserved on orientation change

I am not able to preserve the font for my application label on screen orientation change. Currently I am setting the font using the below code in the onCreate method of SherlockFragmentActivity.
titleId = Resources.getSystem().getIdentifier("action_bar_title", "id", "android");
if(titleId == 0)
titleId = com.actionbarsherlock.R.id.abs__action_bar_title;
mAppName = (TextView) findViewById(titleId);
Typeface face = Typeface.createFromAsset(getAssets(), "fonts/handsean.ttf");
mAppName.setTypeface(face);
On Orientation change the font reverts back to the default. I tried preserving state using manifest.xml but it didnot help. it preserves everything except the label font. Can someone suggest how this can be done ?
Thanks for stopping by and reading this post.
Did you tried setting android:configChanges="orientation" and handling the orientation change with onConfigurationChanged()?
edit: also explained here why it's not functioning.
**Yes we can do this.
Override onConfigurationChanged
set the action bar title inside a handler with a delay of 200.**
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//your code to set the action bar title
setActionBarTitle(title);
}
}, 200);
}

only change layout color while orientation change android

I have create dialog box which will be displayed first when i start application (which is coded in onCreate method ) and then question and answer will be displayed on textview
so to solve problem of orientation (so dialog box again not displayed when orientation change) i have used Manifest with:
android:configChanges="keyboardHidden|orientation"
I have res/layout-land, res/layout-port
but to change only COLOR of background
I have used onConfigurationChanged in my Activity (it get's called on rotation).
so now when orientation change the dialog box will not appear again and background is redrawn but the question and answer which is initialized on onCreate() will not display
so how to maintain
Using android:configChanges="keyboardHidden|orientation" means that your activity handles a configuration change itself, and the system will not change the layout.. take a lokk at http://developer.android.com/guide/topics/resources/runtime-changes.html
To reset the text view, in case of not using android:configChanges="keyboardHidden|orientation":
#Override
public Object onRetainNonConfigurationInstance() {
final MyDataObject data = collectMyLoadedData();
//here get the text from the text view, and any other info
return data;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final MyDataObject data = (MyDataObject) getLastNonConfigurationInstance();
if (data != null) {
//get the text and set it in the text view
}
}
When you change the orientation of the devide, android continue the execution without calling onCreate again, but if you put the code in onResume, this code will executed again.
In OnCreate add for your main layout as
LinearLayout lv=(LinearLayout)findViewById(R.id.mainlayout);
lv.setBackgroundColor(android.R.color.black); // for default potrait or landscape view and after that add this in that activity
#Override
public void onConfigurationChanged(Configuration newConfig) {
Configuration c = getResources().getConfiguration();
if(c.orientation == Configuration.ORIENTATION_PORTRAIT ) {
// portrait
lv.setBackgroundColor(android.R.color.black);
} else if(c.orientation == Configuration.ORIENTATION_LANDSCAPE ){
// landscape
lv.setBackgroundColor(android.R.color.white);
}
}
and also add this in menifest in your activity defined
android:configChanges="keyboardHidden|orientation"
Did you use onSaveInstanceState to save the data and onRestoreInstanceState for retriving the data?
If you have done this then you can display the same dialog box in onRestoreInstanceState.
Well I have a question for you. How did you kept the background color unchanged when changing the orientations? And what to do if the color is unknown or a random color?

ActionBarSherlock (ABS): how to customize the text of action mode close item?

I'm using ABS vers. 4 and I need to simply change the default "Done" text that is displayed besides the action mode close icon, but I really can't figure out how to do it.
I think that text needs to be customizable for at least two good reasons:
"Done" is not appropriate for all contexts (e.g. "Cancel" could be more appropriate, and I've seen some apps, such as the "My Files" app on Galaxy Tab, use it)
"Done" needs to be localized according to the user's language
Is it possible to do customize that text? If so can anyone tell me how to do it?
Thanks in advance.
EDIT
I've found a temporary workaround, that I post in the following:
private TextView getActionModeCloseTextView() {
// ABS 4.0 defines action mode close button text only for "large" layouts
if ((getResources().getConfiguration().screenLayout &
Configuration.SCREENLAYOUT_SIZE_MASK) ==
Configuration.SCREENLAYOUT_SIZE_LARGE)
{
// retrieves the LinearLayout containing the action mode close button text
LinearLayout action_mode_close_button =
(LinearLayout) getActivity().findViewById(R.id.abs__action_mode_close_button);
// if found, returns its last child
// (in ABS 4.0 there is no other way to refer to it,
// since it doesn't have an id nor a tag)
if (action_mode_close_button != null) return (TextView)
action_mode_close_button.getChildAt(action_mode_close_button.getChildCount() - 1);
}
return null;
}
That's the method I came up with. Please NOTE that it does heavily rely upon the structure of the abs__action_mode_close_item.xml of ABS 4.0.
This works for my scenario, but, as you can see, it cannot be considered sufficiently satisfying to promote it to a real "answer", that's why I only edited my previous post.
Hope that helps someone else, but I also hope that someone could share a better and cleaner solution.
You can use a theme to override the default icon:
<item name="actionModeCloseDrawable">#drawable/navigation_back</item>
<item name="android:actionModeCloseDrawable">#drawable/navigation_back</item>
I edited the code from PacificSky to be able to customize the color and font size of the close button, both in pre ICS and >ICS.
I created a method named customizeActionModeCloseButton
private void customizeActionModeCloseButton() {
int buttonId = Resources.getSystem().getIdentifier("action_mode_close_button", "id", "android");
View v = getGSActivity().findViewById(buttonId);
if (v == null) {
buttonId = R.id.abs__action_mode_close_button;
v = getGSActivity().findViewById(buttonId);
}
if (v == null)
return;
LinearLayout ll = (LinearLayout) v;
if (ll.getChildCount() > 1 && ll.getChildAt(1) != null) {
TextView tv = (TextView) ll.getChildAt(1);
tv.setText(R.string.close_action_mode);
tv.setTextColor(getResources().getColor(R.color.white));
tv.setTextSize(18);
}
}
and I call it just after calling startActionMode()
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
actionMode = getActivity().startActionMode(this);
customizeActionModeCloseButton();
return true;
}
It's been a while, but here's a slightly less hacky solution - putting it out there for posterity.
For Android versions < ICS
Put the following line in your application's strings.xml:
<string name="abs__action_mode_done">Cancel</string>
This overrides the TextView's (defined in ActionBarSherlock/res/layout-large/abs__action_mode_close_item.xml) android:text attribute.
For Android versions ICS and above
The native ActionBar functionality is used on ICS and up. You need to find and override the string associated with the done button, using the following code:
int buttonId = Resources.getSystem().getIdentifier("action_mode_close_button", "id", "android");
if (buttonId != 0)
{
View v = findViewById(buttonId);
if (v != null)
{
LinearLayout ll = (LinearLayout)v;
View child = ll.getChildAt(1);
if (child != null)
{
TextView tv = (TextView)child;
tv.setText(R.string.cancel);
}
}
}
Thanks for PacificSky's answer. It's useful for my case.
Something needs to be explained here is that findViewById(buttonId) might return null in some cases such as called in onCreateActionMode() function, because the LinearLayout for ActionMode close button not yet initialized at that time I guess.
I want to hide the action mode close button, so i just sendEmptyMessageDelayed in onCreateActionMode() and call PacificSky's 200ms later. It works for me.
Here is my approach with Java code:
private void customizeActionModeCloseButton(String title, int iconID) {
int buttonId = Resources.getSystem().getIdentifier("action_mode_close_button", "id", "android");
View v = findViewById(buttonId);
if (v == null) {
buttonId = R.id.abs__action_mode_close_button;
v = findViewById(buttonId);
}
if (v == null)
return;
LinearLayout ll = (LinearLayout) v;
if (ll.getChildCount() > 1 && ll.getChildAt(1) != null) {
//custom icon
ImageView img = (ImageView) ll.getChildAt(0);
img.setImageResource(iconID);
//custom text
TextView tv = (TextView) ll.getChildAt(1);
tv.setText(title);
tv.setTextColor(Color.WHITE);
}
}
com.actionbarsherlock.view.ActionMode contains method:
setTitle
It is used to change text near Close Icon in the ActionBar.
ActionMode is available in your com.actionbarsherlock.view.ActionMode.Callback interface implementation methods, like onCreateActionMode.
What you can do - is save incoming ActionMode reference and use it later to change title as your like. Or, if it is not dynamic - you can setup at with your constant in onCreateActionMode.

Categories

Resources