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.
Related
I have been on this problem for a while now.
I am hoping to gather top trending keywords and place into an ArrayList.
Each keyword is to be placed on a toggleButton, (user selects keyword and it enhances search). I need the buttons to be in a grid like form on the Android mobile app, I also need the buttons to be placed in an ArrayList so I can reference later. I've tried so many different loops, for loops and loops in loop and keep hitting the same two problems:
prob 1) either the keywords are not read, or repeated in each column if I create the buttons within the layout loop.
prob 2) I create the buttons first and then reference to them in the layout loop and I get a error message:
"java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first"
I've scanned the internet, I've tried different methods and I think its just something I am missing in my code (this layer of code is one of many layers, this one holds the buttons...any pointers will be appreciated.
trending = new ArrayList<String>() {
{
add("one"); add("two"); add("three") ;add("four");add("five");
add("six");add("seven");add("eight");add("nine");add("ten");
add("eleven");
}};
//LAYOUT SETTINGS 5
TableLayout rLayout5 = new TableLayout(this);
rLayout5.setOrientation(TableLayout.VERTICAL);
LayoutParams param7 = new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
param7.addRule(RelativeLayout.BELOW, rLayout4.getId());
rLayout5.setBackgroundColor(Color.parseColor("#EEEBAA"));
rLayout5.setLayoutParams(param7);
// List<ToggleButton> togButtStore = new ArrayList<ToggleButton>();
int i = 0 ;
while (i < trending.size()){
if (i % 3 == 0){
tr = new TableRow(this);
rLayout5.addView(tr);
}
toggBtn = new ToggleButton(this);
toggBtn.setText(trending.get(i));
toggBtn.setId(i);
toggBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//something here
}
});
tr.addView(toggBtn);
i++;
}
rLayout5.addView(tr); ///<---error points to this line
root.addView(rLayout1);
rLayout1.addView(text1);
root.addView(rLayout4);
root.addView(rLayout3);
root.addView(rLayout5);
setContentView(root);
}
You are adding tr twice to the rLayout5. Delete the line where your error is....
I've tried a lot of different ways, most of the suggestions found here, but none of them seems to work. What I'm trying to achieve is at chat area below my game area, a SurfaceView. It is supposed to scroll upwards as new lines are added to the textview.
At first, it looks like a really simple task, but having tried all kinds of suggestions, like a TextView in a ScrollView, like a TextView in a TableRow in a TableLayout in a ScrollView, and so on...I've still not made it happen. Of course this must be something easily achieved in Android, right??
The task is to display like 6 lines of text in the bottom of the screen, and as a new message is added last it should scroll the rest upwards, like a terminal window. The important thing is that it should add the latest message after the other and, when reached the bottom line, scroll the text upwards and add the new line(s) at the end.
Any kind of help or suggestions would be highly appreciated!!
I needed the same behavior in one of my apps and I achieved in just with one command:
view.setGravity(Gravity.BOTTOM);
Or, analogously, setting this attribute in your layout:
android:gravity="bottom"
Then simply add your lines using:
your_text_view.append(newLine);
Suppose, you declared your ScrollView as follows...
private ScrollView mScrollView;
you initialized it as...
mScrollView = (ScrollView) findViewById(R.id.scroll_view_chat_window);
Now, create a method to perform scroll down when you call the method. Inside the method implement a thread which will do the scroll down independently. And call the method after every chat message update thats will do the auto-srcoll functionality.
private void scrollDown() {
mScrollView.post(new Runnable() {
#Override
public void run() {
mScrollView.smoothScrollTo(mScrollView.getScrollY(), mScrollView.getScrollY()
+ mScrollView.getHeight());
}
});
}
I've achieved this (crudely!) by maintaining my own list, deleting the lowest element then adding at the end each time. Here i've just got a 3 line window:
public class MessageWindow {
private ArrayList <String> msgs;
private Activity parentActivity;
public MessageWindow(Activity act, int allMsgsMax) {
this.parentActivity = act;
msgs = new ArrayList <String> ();
// create empty list elements for initial display
for (int i = 0; i < allMsgsMax; i++){
msgs.add("");
}
}
//
public void put (String msg){
msgs.remove(0);
msgs.add(msg);
// get a handle to the textview 'messages', a 3-line box
TextView t2v = (TextView) parentActivity.findViewById(R.id.messages);
// crappy but you get the idea:
t2v.setText(msgs.get(0) + "\n" + msgs.get(1) + "\n" + msgs.get(2) );
}
then in the activity:
protected MessageWindow messageWindow;
// setup splash screen
messageWindow = new MessageWindow(this, 3);
// write some stuff - row1 will disappear off the top of the box
messageWindow.put ("row1")
messageWindow.put ("row2")
messageWindow.put ("row3")
messageWindow.put ("row4")
From the title it might be a little unclear what I want to ask so allow me to explain.
In my project, I need to make a dynamic view in a while loop. Like so;
private void loadCheckPointQuantity() {
final LinearLayout rgLayoutContainer = (LinearLayout)findViewById(R.id.quantityAnswers);
_answerCursor.moveToFirst();
while(_answerCursor.isAfterLast() == false) {
LinearLayout rgContainer = new LinearLayout(this);
rgContainer.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
rgContainer.setOrientation(LinearLayout.HORIZONTAL);
final ImageView checked = new ImageView(this);
checked.setMinimumHeight(30);
checked.setMinimumWidth(30);
if(_answerCursor.getInt(CPA_IS_CHECKED_COL) == 1) {
checked.setBackgroundResource(R.drawable.btn_check_buttonless_on);
} else {
checked.setBackgroundResource(R.drawable.ic_delete);
}
checked.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
TextView txtAmount = new TextView(this);
txtAmount.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
txtAmount.setText((_answerCursor.getPosition() + 1) + "/" + _answerCursor.getCount());
txtAmount.setTextSize(22);
RadioGroup rgAnswer = new RadioGroup(this);
rgAnswer.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
rgAnswer.setOrientation(RadioGroup.HORIZONTAL);
rgAnswer.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch(checkedId) {
case 0:
checked.setBackgroundResource(R.drawable.ic_delete);
break;
case 1:
checked.setBackgroundResource(R.drawable.btn_check_buttonless_on);
break;
}
}
});
RadioButton rbYes = new RadioButton(this);
rbYes.setText(R.string.yes);
rbYes.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
rbYes.setId(1);
RadioButton rbNo = new RadioButton(this);
rbNo.setText(R.string.no);
rbNo.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
rbNo.setId(0);
ImageButton camButton = new ImageButton(this);
camButton.setImageResource(R.drawable.ic_menu_camera);
camButton.setLayoutParams(new LayoutParams(70, 70));
final EditText txtNote = new EditText(this);
txtNote.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
txtNote.setEnabled(false);
txtNote.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean hasFocus) {
if(!hasFocus) {
txtNote.setSingleLine(true);
} else {
txtNote.setSingleLine(false);
}
}
});
rgAnswer.addView(rbYes);
rgAnswer.addView(rbNo);
rgContainer.addView(checked);
rgContainer.addView(txtAmount);
rgContainer.addView(rgAnswer);
rgContainer.addView(camButton);
rgContainer.addView(txtNote);
rgLayoutContainer.addView(rgContainer);
if(_answerCursor.getInt(CPA_ANSWER_COL) == 1) {
rbYes.setChecked(true);
} else if(_answerCursor.getInt(CPA_ANSWER_COL) == 0) {
rbNo.setChecked(true);
}
if(_answerCursor.getInt(CPA_ANSWER_COL) == 0 || _answerCursor.getInt(CPA_ANSWER_COL) == 1) {
txtNote.setEnabled(true);
}
_answerCursor.moveToNext();
}
_answerCursor.moveToFirst();
}
What happens is, There is a field in the databasethat determines how many times the loop should be crossed. A quantity. So if quantity is 5. The components should be made 5 times.
The problem is,
Because I do all that in a method, I can't access the individual views.
For example, and this is what needs to happen in reality as well;
I click a button. Then I need to save all results in the database.
Ie for the EditText's and isChecked's radiogroup results.
The problem is, I don't know how I can access each individual view.
I have thought of several things to solve this. But they all end up creating question marks above my head
I tried, making a class to represent an answer(isChecked, note, etc(with getters and setters)
create an array list, put them all in an arraylist.
this should work. Putting the answers in an arraylist. But that leaves me with the next problem. What i a text changes? How can I handle this?
if I use observables, should I make the answer class observable, should I call setChanges() for every member, and implement observable in the class containing the loadCheckPointQuantity?
I have exactly 0,4 experience with observables.
How would I go about saving the latest data when pressing the next button?
I am absolutely clueless...
Since it might be vague:
What I try to achieve: Save the latest data from all views to the database
how: help needed
when: on button click
The time you took to understand/look at/read this post is highly appreciated. Answers even more highly.
If you need more code or explanation. Let me know and I will do my best.
I solved my issue.
I assigned eventlisteners to all things that need to eventuall end up in a database.
On focus change, I save the data to the database. So I don't hold any lists whatsoever holding answers. I update the database on the fly. Unfortunately, it is bad for performance. Fortunately, we can afford this performance.
I tried to run this code telling the while loop to execute it 3000 times. Apart from the view generation taking some time(about 3-4seconds on average), all ran fine. So I don't need to keep track of the generated objects outside of the method. android/java does that for me.
I am trying to dynmically move several rows around at once within a specific view based on user input.
The use-case is that the user picks an option and based on the option, certain rows are show/hidden and the rows need to be rearranged to make sense to the user.
The TableLayout is instantiated in XML, but the TableRow and it's layout(s) are instantiated in code. I have tried several different methods, with varying levels of success.
Code which works for hiding/disabling properly:
private void updateTimeRow(TargetType goalTarget)
{
TableRow timeRow = (TableRow)this.findViewById(timeId + 100);
EditText timeText = (EditText)this.findViewById(timeId);
if (goalTarget == TargetType.daysRowedWeek
|| goalTarget == TargetType.metersDay
|| goalTarget == TargetType.metersSeason
|| goalTarget == TargetType.metersWeek)
{
timeRow.setVisibility(View.GONE);
timeRow.setEnabled(false);
timeText.setEnabled(false);
}
else if (goalTarget == TargetType.splitForDistance
|| goalTarget == TargetType.unknown)
{
setTimeText(currentTarget.recalcTime().toString());
timeRow.setVisibility(View.VISIBLE);
timeRow.setEnabled(false);
timeText.setEnabled(false);
}
else
{
timeRow.setVisibility(View.VISIBLE);
timeRow.setEnabled(true);
timeText.setEnabled(true);
}
}
Based on questions answered here, I tried removing/re-adding rows, with this piece of code:
int rowNum = -1;
tableLayout.removeView(timeRow);
switch (goalTarget)
{
case unknown:
case timeForDistance:
rowNum = 2;
break;
case splitForDistance:
rowNum = 4;
break;
case splitForTime:
rowNum = 3;
break;
}
tableLayout.addView(timeRow, rowNum);
Two things break here:
The disable code fails (whether this code is run before of after the enable/disable code above
The rows in my layout get all screwed up.
So, how do I move the rows around dynamically, while properly hiding/showing/enabling/disabling the different rows?
After a lot of frustrating trial and error, I finally figured out the only way to do this with solid results:
I had to adjust the way my UI was updating, to a 3-step process:
- Update the values for the Inputs (enforces formatting, re-calcs, etc)
- Re-layout the rows
- Enable/disable the different inputs based on the selections
The nuts and bolts is that anytime the goalTarget changes I have to remove all of the TableRows from the TableLayout and add
them back in the correct order, with the appropriate row numbers as part of the addView() call.
This is definitely not the prettiest way I could see it being done, but apparently the TableLayout doesn't like you just trying
to move things around one at a time.
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.