I have this button on GridLayout called addnewTask. When you create this button, it will create an EditText.
private GridLayout gridLayout;
int rowIndex = 3;
int colIndex = 1;
int i=0;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_set_task);
gridLayout = (GridLayout) findViewById(R.id.taskLayout);
}
This function to create EditText when the button is clicked -->
public void addView(View view) {
i++;
String tname = "task" + Integer.toString(i);
EditText editText = new EditText(this);
GridLayout.LayoutParams param = new GridLayout.LayoutParams();
param.height = ViewGroup.LayoutParams.WRAP_CONTENT;
param.width = GridLayout.LayoutParams.MATCH_PARENT;
param.rowSpec = GridLayout.spec(rowIndex);
param.columnSpec = GridLayout.spec(colIndex);
editText.setLayoutParams(param);
if (rowIndex > 3) {
editText.setTag(tname);
}
gridLayout.addView(editText);
rowIndex++;
}
My problem is that i want to set the android:id of EditText i created.
like this: When the button is clicked, EditText is created, in row 3, column 1 and id name task1.
When the button is clicked again, another EditText is created, in row 4, column 1 and id name task2.
When the button is clicked again, another EditText is created, in row 5, column 1 and id name task3.
ANS SO ON.....
Ids in android aren't strings - they are always numbers. Even if you write in xml #+id/textId, a number is generated for this text. You can see that in your R file.
What you can do is assign id to your edit texts by using editText.setId(int) method. If you want to be able to easily refer to the edit texts, you can either:
assign the ids sequentially: 1, then 2, 3 etc. Then id of the item would be (row-1) * <columnsCount> + column) (so if you have 3 columns, then second item in fifth row would have id 4 * 3 + 2)
create a map field of type Map<String, Integer>, and again assigns ids sequentially, and save them in.
String tname = "task" + Integer.toString(i);
EditText editText = new EditText(this);
editText.setId(i);
idsMap.put(tname, i);
You then get edittext's id by calling idsMap.get("task3")
Third option is to just keep reference to your EditText in a map: you'd then have a Map<String, EditText> map, and then call
String tname = "task" + Integer.toString(i);
EditText editText = new EditText(this);
editTextsMap.put(tname, editText);
You can keep references of these edit text in an array representing cells of your grid.
declare arraylist like this:
ArrayList<EditText> etArray = new ArrayList<>();
and keep reference to your EditText in array list at the end of your addView method like this:
etArray.add(i,edittext);
now refer these view like this:
etArray.get(i);
this way you will be able to refer them for accessing text.
assigning ids dynamically can cause problems as id is an integer and your assigned ids may cause conflict with system assigned ids to other components.
You can't set id as a String. You can only assign integer as Id. But if you want to use String as id for the ease of use then - in res/values/ids.xml file
<item name="edit_text_hello" type="id"/>
And then use it as:
edText.setId(R.id.edit_text_hello);
So you can do what you need.
Related
I have one EditText and a TextView
and Buttons to perform addition and number Buttons, I want the values from the EditText and perform operations like add, multiply, divide, etc..., so I just need help with retrieving two values from single EditText, my friend suggested me to use split(), but I don't have an idea how to implement it.
How to get text from edittext?
initialize edittext:
EditText editText = findViewById(R.id.edittext);
String[] editTextValues = edittext.getText().toString().split(" ");
now use editTextValues like this
int firstValue = Integer.parse(editTextValues[0]);
int secondValue = Integer.parse(editTextValues[1]);
int sum = firstValue + secondValue;
I'm trying to create a function that pulls together information that is currently scattered around different parts of my project.
As part of this task, I have a layout file with something like the following content... basically a set of rows, with each row having a label (TextView) and a UI element (e.g. CheckBox, Spinner or EditText) to collect information from the user:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="#style/MyLinearLayout.Section"
android:id="#+id/section_pressure" >
<TableLayout style="#style/MyTableLayout"
android:id="#+id/table_pressure" >
<TableRow style="#style/MyTableRow" >
<TextView
style="#style/MyTextView.Label.WithHelp"
android:tag="label_show"
android:text="#string/label_show" />
<CheckBox
style="#style/MyCheckBox"
android:id="#+id/pressure" />
</TableRow>
<TableRow style="#style/MyTableRow" >
<TextView
style="#style/MyTextView.Label.WithHelp"
android:tag="label_unit"
android:text="#string/label_unit" />
<Spinner
style="#style/MySpinnerStyle"
android:id="#+id/pressureUnit" />
</TableRow>
</TableLayout>
</LinearLayout>
I already have an array of all the android:id values for the UI elements, and from that I want to generate another array of the corresponding android:text labels.
e.g. from R.id.pressureUnit I want to find the associated R.string.label_unit from that TableRow, so that I have a central record of what label is used for each UI element... currently that information is scattered across lots of different layout files.
Is this possible programmatically?
From what I understand you want to find #string resource ID of a sibling view of a given view.
Assuming you have the xml file already inflated, you can do the following:
private int getSiblingStringId(#IdRes int viewId) {
View uiElement = findViewById(viewId);
ViewGroup parent = (ViewGroup) uiElement.getParent();
// iterate through the siblings
for (int i = 0; i < parent.getChildCount(); i++) {
View view = parent.getChildAt(i);
if (view instanceof TextView) {
String value = ((TextView) view).getText().toString();
// found
return getStringIdFromValue(value);
}
}
throw new IllegalArgumentException("no TextView sibling for " + viewId);
}
private int getStringIdFromValue(String value) {
// get all fields using reflection
Field[] fields = R.string.class.getDeclaredFields();
for (Field field : fields) {
int stringResId = getResources().getIdentifier(field.getName(), "string", getPackageName());
String s = getString(stringResId);
if (s.equals(value)) return stringResId;
}
throw new IllegalArgumentException("no matching string for " + value);
}
The above code will work inside an activity. You might need to modify it a bit for other classes. (You will need to call findViewById, getResources and getString)
Well, I would set an ID to each table row. Then, programmatically get every child view under each row by iterating over the row's children. From there, you can easily manipulate every view by simply determining which one are you at by using instanceof. But, let's assume you cannot change this, you can still be doing it but it might not be efficient.
Since I don't really know the structure of your array of ids, I just assume its an array of integers called uiIds. Then, you would have to do something like
TableLayout layout = findViewById(R.id.table_pressure);
TableRow tr = null;
View rowChild = null;
TextView tv = null;
View secondaryView = null;
int tableChildCount = layout.getChildCount();
int rowChildCount = 0;
// Since I don't really know the structure of your array of ids,
// I just assume its an array of integers called uiIds
//This will contain the corresponding text strings of every textview
List<String> textLabels = Arrays.asList(new String[uiIds.length]);
// Go over all the rows on your table
for (int i = 0; i < tableChildCount; i++) {
// I'm assuming that you only have rows as the children of your table
tr = (TableRow) layout.getChildAt(i); //This is the row
rowChildCount = tr.getChildCount();
tv = null;
secondaryView = null;
// Now go over all the children of the current row i
for (int j = 0; j < rowChildCount; j++) {
// Here I'm also assuming you only have two children on every row
rowChild = getChildAt(j);
// At this point, the view v could be any type of the ones you have
// used. Since we are interested in TextView simply do an instanceof
if ( rowChild instanceof TextView ) {
tv = (TextView) v;
} else {
// This is the other view in the row. The ones from which you alreade have its ids
// e.g. the spinner with id pressureUnit
secondaryView = rowChild; //We do not need to cast
}
}
// Now we construct the array
if (tv != null && secondaryView != null) {
// The id we just obtained is one from the ones you have already saved
// in an array called uiIds
int secondaryViewId = secondaryView.getId();
//Now, we need to find the index of this id in uiIds
for (int idx = 0; idx < uiIds.length; idx++) {
if ( uiIds[idx] == secondaryViewId ) {
//We have found a match. Then just add the text of the textview in the corresponding index of our new array
textLabels.set(idx,tv.getText().toString());
}
}
}
}
// At this point, textLabels should contain the text of the text view on every row
// such that the ith element in the array you already have corresponds to
// ith element of the array we just created.
// In other words, if uiIds[0] is equals to R.id.pressureUnit, then,
// textLabels.get(0) is equals to R.string.label_unit
I have edited the answer directly on the text editor so it might have some sintax erros. Hopefully this solves your problem or at least gives you an idea.
To get overview of your label mappings, I suggest to code more systematically, in this case to name the label just like the id.
#+id/pressure => #string/label_pressure
#+id/pressureUnit => #string/label_pressureUnit
I know this is not a direct answer to your question. However I think, if you work in this way, you don't need a central table of your mappings at all and your layouts become more readable. Android Studio makes it really easy to do this kind of changes.
I know to get a string of a specific TextView in a ListView, I can do this:
ReviewUser = ((TextView) rowView.findViewById(R.id.labelUser))
.getText().toString();
What if I want to get the TextView itself?
The TextView is an integer and I simply want to get the TextView and add 1 to it.
So you already specified that you know how to get the specific text from your ListView. Since you want to modify that same TextView, the rest is simple. This code is lengthier just to show the steps.
TextView textView = (TextView) rowView.findViewById(R.id.labelUser)
String text = textView.getText().toString();
int num = Integer.valueOf (text).intValue() + 1;
textView.setText (""+num);
Also, if you are working with a String ArrayAdapter and you know the index of the row you want to modify, what you can do is (assuming arrayAdapter is initialized and index is your index variable):
String text = arrayAdapter.get(index);
arrayAdapter.remove (text);
arrayAdapter.insert ((Integer.valueOf (text).intValue() + 1 ) + "", index);
I'm new, so sorry if this turns out so simple that I should have solved myself. I've spent a couple days thinking about it. I've researched a ton and searched many other posts here, but no success.
I have a dialog with DatePicker, Buttons, EditText fields, and Spinners. I can populate everything i need from the stored items in my DB to the dialog. But when i try to get the numbers entered into some of the EditText fields, it throws NumberFormatException. I can hard code values into variables to store, and hide my attempt to get the value in a try and it will run fine. The values get stored and when I open the dialog again they populate into the right areas.
Here's partial code-
EditText et = new EditText(getContext());
for(int i=0; i<=etcount; i++){
placed = -1; //reset for next iteration
//try to get number from edittext
et.findViewById(i);
placed = Integer.parseInt(et.getText().toString());
awake++;
/*
try {
//et.findViewById(i);
placed = Integer.parseInt(findViewById(i).toString());
//placed = Integer.parseInt(et.getText().toString());
} catch(NumberFormatException nfe) {
System.out.println("Could not parse " + nfe);
}*/
I commented out the try block cause I wanted to troubleshoot quickly.
etcount variable is initialized at onCreate with -1 value, before getting values from DB. If there are values stored in the DB it gets incremented by 1, then code is called to dynamically add an EditText and Spinner to the layout. Also the EditText id is set to the value of etcount. Here is that code-
//this will be ran when +placement button pressed, or if there are items in db stored
//adds 2 rows to dialog, one for textview to label items, one row for edittext with number
//and spinner with what item it is
private void createTableRow(int numPlaced, int itmPlaced){
etcount++; //used to count how many edittext fields there are so that they can be saved later
spincount++; //to count how many spinner there are
tl = (TableLayout)findViewById(R.id.tableLayoutVisit); //the tablelayout name
//need to create row for textview, then another row for edittext and spinner
tr1 = new TableRow(this.getContext()); //table row 1, for textview
tr1.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
TextView tv = new TextView(this.getContext());
tv.setText("Amount Placed");
tv.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
tr1.addView(tv); //add textview to tablerow1
tl.addView(tr1, new TableLayout.LayoutParams( //add row to tablelayout
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
tr2 = new TableRow(this.getContext()); //tablerow2: edittext and spinner
tr2.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
EditText et = new EditText(this.getContext());
et.setId(etcount);
et.setInputType(InputType.TYPE_CLASS_NUMBER);
if(numPlaced!=0){ //if being populated from previous visit
et.setText(Integer.toString(numPlaced));
//et.setText("" +numPlaced);
}
//need to have listener to read data
et.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
Spinner spin = new Spinner(this.getContext());
spin.setId(spincount);
spinArray = getContext().getResources().getStringArray(R.array.itemplaced);
ArrayAdapter adapter = new ArrayAdapter(getContext(),
android.R.layout.simple_spinner_item, spinArray);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spin.setAdapter(adapter);
if(itmPlaced!=-1){
spin.setSelection(itmPlaced); //assign correct value
}
spin.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
tr2.addView(et);
tr2.addView(spin);
tl.addView(tr2, new TableLayout.LayoutParams( //add row to tablelayout
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
}
I pass it (0,-1) if it is a new item and not currently stored in DB. Also you probably noticed I forced it to accept TYPE_CLASS_NUMBER. But I don't think the issue is there. Again, if I hard code values it will save into the DB and the next time I open it it dynamically creates EditText/Spinner row in layout and populates the EditText with the value in the DB.
So... something is wrong with the first section I think, the et.findViewById(i); or placed = Integer.parseInt(et.getText().toString());. The value of "etcount" should be -1 if nothing was populated from DB, and 0 etc(etcount++) each time something is populated from DB.
Sorry if this is longwinded, wanted to be specific. Hope this is enough info! Any help would be great!!! Thanks in advance.
Try this:
EditText et = new EditText(this);
for (int i = 0; i <= etcount; i++) {
placed = -1;
et = (EditText) this.findViewById(i);
placed = Integer.parseInt(et.getText().toString());
//...
}
It seems to me that I've found an error.
The main problem in your code that you do not assign unique values in setId methods. In your case some editTexts and spins can have the same IDs. This is wrong. Every element must have a unique identifier. This is the first what you should correct in your code.
After that you can use my approach. But it seems to me that something wrong in this approach. It is not beautiful ) Try to find best practices in this field.
Few suggestions from my side:
1) try to check whether getText method not giving you empty string"" or null.
2) place your EditText et; to class variable not a local instance.
example public class ExampleActivity extends Activity
{
EditText et;//place it here instead in oncreate methods.
}// or make it final if defining in oncreate.
according to your code, issues seems in your for loop
for(int i=0; i<=etcount; i++){
placed = -1; //reset for next iteration
//try to get number from edittext // which edit text you are trying to access. am sure it is returning null to you.
et.findViewById(i);
placed = Integer.parseInt(et.getText().toString());
My app is getting a little bloated, I would like to 'compress' some code by changing some of my variables into arrays and using some for loops to process my variables.
My first target is initializing my EditText boxes
My original code (working fine) included:
EditText miBox1, spBox1 ;
EditText miBox2, spBox2 ;
...
miBox1 = (EditText)this.findViewById(R.id.miBox1);
spBox1 = (EditText)this.findViewById(R.id.spBox1);
miBox2 = (EditText)this.findViewById(R.id.miBox2);
spBox2 = (EditText)this.findViewById(R.id.spBox2);
I actually have twenty mi boxes and 20 sp boxes to setup
I am trying to create an array, and loop through them
In my main.xml I have renamed my EditText boxes to
miBox[1] spBox[1], etc.
I'm declaring in my activity with:
EditText[] miBox = new EditText[20] ;
EditText[] spBox = new EditText[20] ;
and putting this into a for loop
miBox[i] = (EditText)this.findViewById(R.id.miBox[i]);
spBox[i] = (EditText)this.findViewById(R.id.spBox[i]);
but Eclipse cannot resolve R.id.miBox[i]
How do I properly create an array of EditText in my xml so that
it is recognized?
Thanks
JD
int resID = getResources().getIdentifier("miBox" + i,
"id", getPackageName());
where i is your index
EditText editText = (EditText)findViewById(resId);
if you want to put it in an array, simply do this :
miBox[i] = (EditText)findViewById(resId);
the problem here is you have wrongly modified a few things.
the code should be like:
EditText[] miBox = new EditText[20] ;
EditText[] spBox = new EditText[20] ;
and putting this into a for loop
miBox[i] = (EditText)this.findViewById(R.id.miBox1);
spBox[i] = (EditText)this.findViewById(R.id.spBox1);
Here, the msitake is using miBox[i] since thats not the id you have used in your layout xml.
hope this helps.