I have many buttons in my activity (only a subset of which are visible at a time). I currently have something ugly like this:
buttonID[0] = R.id.buttonr1b1;
buttonID[1] = R.id.buttonr1b2;
buttonID[2] = R.id.buttonr1b3;
buttonID[3] = R.id.buttonr1b4;
...
buttonID[35] = R.id.buttonr1b36;
for (int i = 0; i < 36; i++) {
button[i] = (Button) findViewById(buttonID[i]);
}
Is there a more elegant way to reference all of R.id.buttonXXX ? It just looks so wrong and ugly.
Thank you.
Your instincts are correct. It's ugly and in general if you find yourself wanting to do this you should rethink your design.
If your buttons are uniform to the point where you want to loop over them to do something like this, they're probably uniform enough to generate programmatically in the first place (and you can store references as you create them) or use some form of AdapterView. What data needs to be associated with each button? Can you associate it directly using setTag/getTag? Do you need to use IDs here at all?
I'm not sure if this is more elegant or less elegant, because you will lose compile-time checking of your IDs. However, you can construct the IDs by name:
final static String PREFIX = "buttonr1b";
...
Resources res = getResources();
for (int i = 0; i < 36; i++) {
int resID = res.getIdentifier(PREFIX + i , "id", getPackageName());
button[i] = (Button) findViewById(resID);
}
Note: make sure "getPackageName()" would return the appropriate package for your R class, otherwise specify it explicitly.
Related
I have several layout elements which I want to process as an array, for example:
for (int j=0; j< N; j++)
((TextView)findViewById(R.id.groupStart+j)).setText(getRowText(j));
The problem is that Android doesn't understand ID definition like
android:id="#+id/groupStart+1"
Perhaps I can't find right syntax. I can assure certain IDs for element if I add them in a layout grammatically, but I want to define them in resource. I can't also edit R.java because it is automatically generated. Any recommendations?
Use this :
for(int i=0; i<5; i++){
int resID = getResources().getIdentifier("groupStart"+i, "id", getPackageName());
view = findViewById(resID);
}
Where ids are:
android:id="#+id/groupStart1"
android:id="#+id/groupStart2"
.
.
.
I have a couple of EditTexts arranged on rows and columns.Those EditTexts contain product name,quantity and price and a TextView that shows the total in real time(calculates it each time you write on one of the EditTexts)
I've setup a a button on each row that when clicked sets visibility of the row(3EditTexts for product name,price and quantity) to GONE.
My problem is that after i set the visibility to GONE,though there are no more EditTexts it still calculates their values from before being GONE.
My question now is,what happens when the EditTexts are set to visibility.GONE ?
My app calculates in real time,so when something happens to an EditText,he calculates again..but it's like the values are still there...Isn't this supposed to be the difference between invisible and gone ?
I'll show you the way i calculate(it is called even after you press the X button to erase the EditTexts,not only when you change values inside EditTexts)
public void calculeaza() {
totaltest = 0;
prod = new String[allprod.size()];
pret = new String[allpret.size()];
cant = new String[allcant.size()];
for (int m = 0; m < allprod.size(); m++) {
prod[m] = allprod.get(m).getText().toString();
if (prod[m].matches("")) {
prod[m] = " - ";
}
}
for (int j = 0; j < allcant.size(); j++) {
cant[j] = allcant.get(j).getText().toString();
if (cant[j].matches("")) {
cant[j] = Float.toString(0);
}
}
for (int k = 0; k < allpret.size(); k++) {
pret[k] = allpret.get(k).getText().toString();
if (pret[k].matches("")) {
pret[k] = Float.toString(0);
}
}
for (int l = 0; l < allpret.size(); l++) {
Float temp = Float.parseFloat(cant[l]) * Float.parseFloat(pret[l]);
totaltest = totaltest + temp;
TextView totalf = (TextView) findViewById(R.id.total);
totalf.setText(String.format("Total: %.2f", totaltest));
}
}
Lines Straight from Android dev site..
View.GONE This view is invisible, and it doesn't take any space for layout purposes.
View.INVISIBLE This view is invisible, but it still takes up space for layout purposes.
i.e it retains EditText object even after Gone..
You can reinitialise edittext if you dont want it to retain its value...or setText = ""
Above quoted is the only difference...
Hope this helps...
I'm not really seeing in the code you posted anything I can use to answer this question, but there does appear to be some confusion as to what setVisibility does:
INVISIBLE elements are not seen on the page, but they still take up space (there's a hole where they would be)
GONE elements have no visible effect on the screen, from the user's perspective they aren't there. However they are still part of the view.
If you want to remove the object from the view, then you need to call removeView() on its parent.
It may still take up memory after it has been removed from the view, in case your code has kept references to it in any variables.
It may still take up memory after there are no further references to it, at least until the garbage collector gets around to it.
I'm hoping the rather generalized statements above help clarify the situation.
I have a layout the contains 4 TextViews with ids: "Name1", "Name2", "Name3", "Name4"
I would like to iterate on them with a for loop,
is there any way to do this?
something like
for(int i = 1; i <= 4; i++)
{
findViewById(R.id."Name" + i)
}
I know that this code is far from being real, but any help?
Thank you!
Ron
No, you cannot do it like that because R.id.xyz is referencing a static int of a static class. It's not a string that can be concatenated like that. Also, your code ignores the return value of findViewById so it does nothing (though I realize you mentioned the code is far being real, but still an actual use case might help clarify what you're trying to do). R.id."Name" means nothing and will give you a compiler error.
To loop through you can do something like this:
int[] ids = {R.id.foo, R.id.bar};
then
for(int i = 0; i<ids.length; i++) {
View v = findViewById(ids[i]);
}
Sure you can do that sort of. You cannot access an member of R.id using a string literal you must type out the variable name.
R.id."Test" is no good but R.id.Test is fine.
If you examine the type of R.id.XYZ you will find that it is simply an integer. There is no reason why you cannot perform basic arithmetic on id values.
However it doesn't really make sense to do so. When you build your APK the compiler automatically creates a static class called R that contains references to the various resources and assets contained in your APK, such as layouts, drawables, sounds, etc..
Just because you know that the integer value for R.id.button1 is X there is no guarantee that the integer value for R.id.button2 will be X+1, in fact it could be anything.
If you want to create a list of TextViews to iterate over consider adding them to a List and then iterating over the list. Like so:
ArrayList<TextView> list = new ArrayList<TextView>();
list.add( (TextView) findViewById(R.id.textView1) );
list.add( (TextView) findViewById(R.id.textView2) );
list.add( (TextView) findViewById(R.id.textView3) );
list.add( (TextView) findViewById(R.id.textView4) );
int size = list.getSize();
for (int i=0; i< size; i++)
{
TextView tv = list.get(i);
// Do something with tv like set its label to i
tv.setText(Integer.toString(i));
}
I want to work dynamically therefore I want to bind text views dynamically I think an example would explain me the best
assuming I want to bind 7 image views i can do it like this :
Country = (EditText)findViewById(R.id.CountryEditText);
City = (EditText)findViewById(R.id.CityEditText);
LivinigCreture = (EditText)findViewById(R.id.LivingCretureE);
Nature =(EditText)findViewById(R.id.NatureEditText);
Inanimate = (EditText)findViewById(R.id.InanimateEditText);
KnowenPersonality = (EditText)findViewById(R.id.KnowenPersonalityEditText);
Occupation = (EditText)findViewById(R.id.OccupationEditText);
but lets change 7 with NUMOFFILEDS as a final where i want to do the previous ?
myImages = new ImageView [7];
for (int i = 0; i<7;i++,????)
myImages[i] = (ImageView)findViewById(R.id.initialImageView01);
notice : in my R file the R.id.initialImageView01 - R.id.initialImageView07 are not generate in a cont gap between them therefore I don't know how to make this architecture possible .
and if there's a way can someone show me an example how to work dynmiclly (like using jsp on android combined way or something ?)
id its possiable to do so constant times is it possible to build an the same xml constant num of times like jsp does
thank u pep:)
You can store the IDs themselves in an array at the beginning of your Activity; that way you'll only need to write them once and you can index them afterwards.
Something like:
int[] initialImageViewIds = {
R.id.CountryEditText,
R.id.CityEditText,
R.id.LivingCretureE,
R.id.NatureEditText,
R.id.InanimateEditText,
R.id.KnowenPersonalityEditText,
R.id.OccupationEditText
};
Then you can access them with:
myImages = new ImageView [7];
for (int i = 0; i<7;i++) {
myImages[i] = (ImageView)findViewById(initialImageViewIds[i]);
}
If that's not enough and you really want to get the IDs dynamically, I suppose you can use reflection on the R.id class, possibly with something like R.id.getClass().getFields() and iterate on the fields to check if their names interest you. Check reference for the Class class, too.
I need a help with setting a random image using setImageResource method.
In the drawable folder, I have a jpeg file named photo0.jpg, photo1.jpg...photo99.jpg.
And the following code works:
int p = R.drawable.photo1;
image.setImageResource(p);
The above will display photo1.jpg but I want to show a random image.
I tried the following but it doesn't work.
String a = "R.drawable.photo";
int n = (int) (Math.random()*100)
String b = Integer.toString(n);
String c = a+b;
int p = Integer.parseInt(c);//checkpoint
image.setImageResource(p);
It seems like the string "R.drawable.photoXX" isn't being changed to integer at the checkpoint.
Could someone please teach me a right code?
Thank you in advance.
Strings are pretty much evil when it comes to work like this due to the overhead costs. Since Android already provides you with integer id's I would recommend storing all of them to an int array and then using a random number for the index.
The code would look something like this:
int imageArr[] = new int[NUM_IMAGES];
imageArr[1] = R.drawable.photo;
//(load your array here with the resource ids)
int n = (int)Math.random()*NUM_IMAGES;
image.setImage(imageArr[n]);
Here we have a pretty straight forward implementation and bypass all the creation and destruction that occurs with the string concats.
maybe the error is here
int n = (int) (Math.random()*100)
put % not * Like this
int n = (int) (Math.random()%100)
to get all numbers under 100