Wrong value in EditText when changing screen orientation - android

Im confused.
I have a layout (LinearLayout) holding a TextView and EditText.
Somewhere in my code i create (programatically) a RelativeLayout and push in it several of this LinearLayouts. To each one of them i set an ID and values for TextView and EditText.
The problem is when i change screen orientation. All EditText controls gets the same value (from the last EditText). If i set a breakpoint all seems fine. I even inspected all elemets before setContentView is called and all values seem fine.
Any idea?
Here is the relevant part of code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
csWgs84 = getCoordinateSystem();
wgs84C = getCoordinates();
sView = new ScrollView(this);
layout = getLayoutInflater().inflate(R.layout.location_calculator, null);
View control1 = getLayoutInflater().inflate(R.layout.text_edit, null);
control1.setId(1);
TextView title1 = (TextView) control1.findViewById(R.id.title);
title1.setText(csWgs84.axisInfo.yAxisAbbreaviation + " [°] :");
EditText value1 = (EditText) control1.findViewById(R.id.input);
value1.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
value1.setText(cutValue(RSimpleFormatter.formatNumber(wgs84C.y, 1, 7, '.'), 12));
RelativeLayout.LayoutParams viewLayoutParams1 = new RelativeLayout.LayoutParams
(RelativeLayout.LayoutParams.FILL_PARENT,RelativeLayout.LayoutParams.WRAP_CONTENT );
viewLayoutParams1.addRule(RelativeLayout.BELOW, group.getId());
((RelativeLayout) layout).addView(control1, viewLayoutParams1);
View control2 = getLayoutInflater().inflate(R.layout.text_edit, null);
control2.setId(2);
TextView title2 = (TextView) control2.findViewById(R.id.title);
title2.setText(csWgs84.axisInfo.xAxisAbbreaviation + " [°] :");
EditText value2 = (EditText) control2.findViewById(R.id.input);
value2.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
value2.setText(cutValue(RSimpleFormatter.formatNumber(wgs84C.x, 1, 7, '.'), 12));
RelativeLayout.LayoutParams viewLayoutParams2 = new RelativeLayout.LayoutParams
(RelativeLayout.LayoutParams.FILL_PARENT,RelativeLayout.LayoutParams.WRAP_CONTENT );
viewLayoutParams2.addRule(RelativeLayout.BELOW, control1.getId());
((RelativeLayout) layout).addView(control2, viewLayoutParams2);
sView.addView(layout, scrollViewLayoutParams);
setContentView(sView);
}

I had the same problem. I don't know why it happens; it happens in one of my activities but not in another one that I think is almost identical. I haven't investigated it extensively though.
However, I came up with a workaround: Populate the EditTexts in onResume() instead of in onCreate(). (I also tried to populate them in onStart, but then I got the same fault.) I hope that may work for you or anyone else reading this thread.

If the (admittedly usually very clever) default onPause() method isn't dealing well your activity being pushed to memory and being reloaded from it then you need to override it.
Use onPause to save the value's of your programatically created fields in a bundle. In your onCreate method check for the presence of a Bundle and create you're view's from this.
Activity Lifecycle

Be careful with the references. Maybe you are creating all the EditText "programatically", and then just modifying the last one several times.
Posting the code will be helpful.

Check this or this. I think you are not saving EditText content during orientation change.

The underlying problem is that the views in your custom layout, which is inflated and added multiple times, all have the same IDs (R.id.title and R.id.input). When Android saves their state, each one overwrites the previous one because of the same ID.
What you could do is to define some unique IDs which are generated by Android and assign those to the fields programmatically.

Not sure if this is the case, but I was able to fix this issue by removing
android:textIsSelectable="true"
from my XML layout.

Related

Contents of textView change when contents are selectable

I am currently working on a project which requires me to dynamically add textView objects to a LinearLayout based on the contents of an array.
chapter = Home.chapters.get(index);
layout.removeAllViews();
String dataText = chapter.content;
String[] dataArray = dataText.split("~");
for (int i = 0; i < dataArray.length; i++) {
String paragraph = dataArray[i];
String outputParagraph = paragraph.replace("`", "\n");
View view = getLayoutInflater().inflate(R.layout.ttc_text, null);
final TextView tv = (TextView) view.findViewById(R.id.textView);
tv.setText(outputParagraph);
//tv.setTextIsSelectable(true);
layout.addView(view);
}
TextView titleView = (TextView) findViewById(R.id.title);
titleView.setText("Chapter " + chapter.title);
layout.setOnTouchListener(new OnSwipeTouchListener(getBaseContext()) {
public void onSwipeRight() {
retreatBackward();
}
public void onSwipeLeft() {
advanceForward();
}
});
I have configured saveOnItemStateChanged in order to restore the correct contents of the textViews when the screen is rotated.
if (savedInstanceState != null) {
index = savedInstanceState.getInt("Chapter");
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putInt("Chapter", index);
super.onSaveInstanceState(savedInstanceState);
}
However, whenever the screen is rotated, the textViews present within the parent layout do not display their original contents. Instead, the same number of textViews in the original layout all display identical contents, that is, the contents of the final textView added to the layout.
This issue only presents when the text within the TextViews is designated as selectable, either through the setTextIsSelectable() function or through the XML markup. As such, the selectability of the text must be somewhat impacting the way in which the contents of the TextViews are repopulated after a rotation, although I cannot seem to establish exactly why. Any assistance would be much appreciated.
I think the problem is due to your device's configuration change. When you rotate your device a configuration change event occur. Add the following code to your Manifest.xml and your activity class. Hope, that will solve your problem.
Changes to Manifest.xml file ---> (Suppose XYZ is your activity class)
<activity android:name=".activities.XYZ"
android:configChanges="orientation|screenSize"/>
Add this to your XYZ activity class --->
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
1st
super.onSavedInstanceState(...) should be the first thing called. Your 'save' stuff should come after.
2nd
You will most likely need to save all of the textviews, so you can repopulate them, or save the array and repopulate based on that.
I found this site to be very good for explaining the ins and out of save-instance-state handling.
http://www.intertech.com/Blog/saving-and-retrieving-android-instance-state-part-1/

onPause() & onSaveInstanceState() for created UI

First off I have searched for this info for about a week and found very little. So hopefully this long read helps some other new people.
I have created a UI from JSON. This UI has all kinds of Views. Such as EditText, RadioButton, CheckBox, Spinner, etc. Now I need to account for certain inevitable scenarios. Screen rotation, phone call, back button, home button etc. Since all these Views are created after a network call/response and this takes time I do not want to repeat this action each time. So saving the actual RadioButton or EditText and what was selected on the RadioButton or typed into the EditText is extremely important. From what I've read for screen rotation I use onSaveInstanceState(). For anything else I would use onPause() because it is the only thing that is garunteed to be called.
The problem is I have no idea how to store programatically created Views with no id's in sharedprefs or a bundle let alone the values they hold. Lets look at my code and then discuss what I think is currently possible.
allEdit = new ArrayList<EditText>();
else if (map.get(TAG_FIELD).equals(et)) {
Log.v("RESPONSE", "About to create an EditText");
// find
LinearLayout content = (LinearLayout) getActivity()
.findViewById(R.id.add);
// create
TextView tv = new TextView(getActivity());
EditText et = new EditText(getActivity());
LinearLayout ll1 = new LinearLayout(getActivity());
// set
tv.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.MATCH_PARENT));
et.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
ll1.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
tv.setText(map.get(TAG_NAME));
ll1.setOrientation(LinearLayout.HORIZONTAL);
// add
ll1.addView(tv);
ll1.addView(et);
allEdit.add(et);
content.addView(ll1);
}
So in the example above I have created an EditText and stored it in an ArrayList<EditText>. Now my thought is that in onPause() I could do something like this.
for (int i = 0; i < allEdit.size(); i++) {
EditText et = allEdit.get(i);
String input = et.getText().toString();
prefsEdit.put(input);
}
Which I think might work, it also might overwrite the String "input" inside shared preferences over and over again. Not totally sure how that works. It also still does not solve how to save the actual EditText so that it does not have to be recreated.
Now in onSavedInstanceState() I think I may be able to get away with just inserting the whole ArrayList<EditText> as serializable, right? Like this...
putSerializable("key", allEdit)
However that does not save the values inside them.
So how do I save these Views and their values in onSavedInstanceState() and onPause()? Perhaps more importantly, do I need both? Can I get away with just using onPause()?
Thank you
I havent tried this, but it sounds like it would work in practice. When creating the activity (before the JSON populates) create your own ViewGroup. From there, read the JSON and add every view that you get to the VeiwGroup. Then, when you want to save the information or whatever do this
int viewCount = mViewGroup.getChildCount();
for(i=0;i<viewCount;i++) {
newView = mViewGroup.getChildAt(i);
if (newView instanceOf EditText) {
EditText newEditText = (EditText)newView
string value = newEditText.getText();
}
else if (newView instanceOf RadioButton) {
same as above ^
etc...
}
}
Then, for each of the values you pull add them to an array, maybe even a NamedPair to store their ID and value (by ID I mean index of which view it is). So
public List<String> lstEditTextValues = new ArrayList<String>();
After all that is said and done, then you can itterate through each one, and save it as an individual value through the bundle, save in a shared pref, or put into a static class level variable (not the safest way to retain information, but does work).
Hope this helps. Let me know if im completely off topic

Android check boxes change text when switched to landscape

I have a view in android that shows a number of check boxes. They are all added dynamically and I set a text for each one in part.
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout layout = (LinearLayout) findViewById(R.id.layout);
LayoutInflater inflater = getLayoutInflater();
for (String string : getResources().getStringArray(R.array.string_array)) {
LinearLayout searchField = (LinearLayout) inflater.inflate(R.layout.cb, null);
CheckBox checkBox = (CheckBox) searchField.findViewById(R.id.checkBox1);
checkBox.setText(string);
layout.addView(searchField, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
}
}
}
AS you can see from the code, I have an array of strings and for each of the strings in the array I add an check box. When the view is first shown, all the check boxes have the correct text, but after I rotate the device to landscape or portrait mode, all the check boxes have the same text (from the last check box). Any rotations (to redraw the screen) do not affect the text anymore. All of them remain with the text of the last check box.
I have looked in the debugger, the check box object is a new one for each string, so I am not working with the same instance of an object. I am currently out of ideas.
Do you have any idea why this is happening?
When you rotate the screen, runtime Resource is changed, and Activity is relaunched. Two ways to fix your problem:
Hold the value of all your checkbox in OnCheckedChangeListener and reset them back in onResume.
Handle onConfigurationChanged by yourself, according to https://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange

Retrieve values of a dynamic form in Android

I created a dynamic form without much problems, but I need to recover the values from the fields (controls) of the form, but I'm not sure of how to do this.
For example, I have this piece of code:
if(tipoP.equals("TEXTAREA")){
EditText ta = new EditText(this);
ta.setId(i);
LayoutParams params3 = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, (float) 0.3);
params3.setMargins(20, 0, 20, 0);
ta.setLayoutParams(params3);
ta.setLines(3);
ta.setRawInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE);
ll.addView(ta);
}
How do I add a listener that captures the text of the EditText and put it inside a Vector variable?
I tried this:
ta.setOnClickListener(new OnClickListener(){
public void onClick(View view){
EditText t = (EditText) findViewById(i);
res.add(t.getText().toString);
}
});
But I'm not getting the id (variable i) because its in another execution environment. How do I solve this? Any help would be appreciated!!
You should not use setId for dynamically created views but setTag and findViewByTag.
You could create a button dynamically and set an onClickListener on it. Inside the listener, you can just reference the EditText directly (no need for tags or ids) as long as you have made it final.

Android application view containers are sticky

I need help, my layouts and containers are lingering on after I have used the code bellow to remove them.
For example I have page 1 that adds a small text that explains how to use the part of the program under scrutiny, and then the next page allows the user to add a name where there is a label with text Name: and a EditText to add the name in next to it.
Both the components 'stick' but the EditText is reproduced multiple times and I have no idea why! I would also like to stop the sticking.
By sticking I simply mean that the view does not leave view like it should(still visible).
Here is some code.
if(pageCount == lastPageCount--)
{
page2Layout.removeAllViews();
//page2Layout.setVisibility(View.GONE);
//Reset all text views.
helpText.setText("");
}
helpText.setLayoutParams(params);
helpText.setText("You cannot view this part sorry :S\n\n" +
"You cannot view this part sorry :S.\n" +
"You cannot view this part sorry :S");
page1Layout.addView(helpText);
page1Layout.setVisibility(View.VISIBLE);
}
else if(pageNumber == 2)
{
if(pageCount == lastPageCount++)
{
//page1Layout.setVisibility(View.GONE);
page1Layout.removeAllViews();
}
else if (pageCount == lastPageCount++)
{
page3Layout.setVisibility(View.GONE);
}
//Name Position + Containers etc
LinearLayout nameLayout = new LinearLayout(this);
nameLayout.setOrientation(LinearLayout.HORIZONTAL);
nameLayout.setLayoutParams(params);
TextView nameLabel = new TextView(this);
nameLabel.setLayoutParams(params);
nameLabel.setText("Name: ");
EditText nameTextField = new EditText(this);
nameTextField.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
//All to name layout.
nameLayout.addView(nameLabel);
nameLayout.addView(nameTextField);
page2Layout.addView(nameLayout);
page2Layout.setVisibility(View.VISIBLE);
}
Beware of the stupid mistakes coders can make when they stare at code too long.
if(pageCount == lastPageCount++)
For anyone who is also stuck similarly, lastPageCount++ will increment lastPageCount after the statement has run.
Therefore the wrong code is run.

Categories

Resources