Basically, I've been trying to place a bunch of EditText and TextViews programmatically, all within a RelativeLayout (I have to do it programmatically because the amount of stuff is variable depending on how many "employees" the user has entered). Now, I only need ten pieces of data per "employee", so I decided to keep track of the data using id's in base 10 (ie Employee 1 gets id 0-9, Employee 2 gets id 10-19, etc.). However, every time I use LayoutParams.addRule(int,int) function and manually input my own id, it fails to pick it up. If I use the addRule(int,int) function using "R," it works. The only reason I can come up with that would explain addRule's failure to respond to the manually inputed id values is if my math (for the id-values) is wrong, but if you look at my code, the math is pretty self-explanatory. Please tell me what I'm doing wrong because this is maddening.
Here's what I have so far:
for(int i=0;i<u.getTemp().size();i++){
int index=10*i;
RelativeLayout.LayoutParams layoutParams=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
if(i==0)
layoutParams.addRule(RelativeLayout.BELOW,R.id.start_date);
else
layoutParams.addRule(RelativeLayout.BELOW,index-1);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
TextView empName=new TextView(rl.getContext());
empName.setTextSize(26);
empName.setText(u.getTemp().get(i).getName());
empName.setId(index++);
empName.setLayoutParams(layoutParams);
rl.addView(empName);
TextView empNum=new TextView(rl.getContext());
empNum.setText("Employee Number: " + u.getTemp().get(i).getNum());
empNum.setId(index++);
RelativeLayout.LayoutParams empNumLayout=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
empNumLayout.addRule(RelativeLayout.BELOW,empNum.getId()-1);
empNumLayout.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
empNum.setLayoutParams(empNumLayout);
rl.addView(empNum);
EditText regHours=new EditText(rl.getContext());
regHours.setHint("Regular Hours");
regHours.setId(index++);
RelativeLayout.LayoutParams regHoursLayout=new RelativeLayout.LayoutParams(300,RelativeLayout.LayoutParams.WRAP_CONTENT);
regHoursLayout.addRule(RelativeLayout.BELOW,regHours.getId()-1);
regHoursLayout.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
regHours.setLayoutParams(regHoursLayout);
rl.addView(regHours);
}
*Notes: rl is the relativeLayout I placed in the xml file.
I recently lost the reputation to comment :) so I am posting it as an answer. You can try using Linear Layout instead of Relative Layout. If you require any further assistance let me know. I'll help you out. :)
The error was that ids have to be positive. The first TextView had an id of 0 which explains why the addRule didn't respond.
Related
I am trying to interact with dynamically generated buttons. I want to update text and background color for those player clicked and for those who is near by horizontal or vertical axis at the moment of a click.
What I've tried. I've found an id property of a button in XML which led me to idea that I can make a text key to refer to a programmatically generated button. But when I've tried to assign an id - IDE was expecting a number (Int), not a string. Since buttons form a square array - I decided to encode each button via 4 digit number where first 2 digits stand for a row number and other two stand for a column number. Though when I tried to use findViewById IDE told me that it was expecting a special id data type, not a number.
That's how it looks for now:
for (i in 1..size) {
for (j in 1..size){
val button = Button(this)
button.id = i*100 + j
constraintLayout.addView(button)
}
}
What idea or method could I look at?
If you created it dynamically you can save it in a variable (or an array) for later use.
val myButtons = ArrayList<Button>()
for (i in 1..size) {
for (j in 1..size){
val button = Button(this)
myButtons.add(button)
constraintLayout.addView(button)
}
}
if you have a layout with dynamically created views and you know their order you can get them with getChildAt(index).
Alternatively you can assign ids saved in xml like this.
Please don't be so strict, I never did this before.
I have database with some hobbies and their id.
What I need is dynamically create some quantity of TextView for every hobby. With this no problem :)
But then i need to set onClickListener on each of this textView, and if one of them was clicked - get id for this hobby from database.
Any ideas please!
maybe setTag(id) with id of hobby and inside OnClickListener obtain this tag by (int) v.getTag()
Here is my code :
rl=(RelativeLayout)findViewById(R.id.ScoreLayout);
rtb=new RatingBar(this);
rl.addView(rtb);
rtb.setNumStars(5);
rtb_params=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
rtb_params.addRule(RelativeLayout.CENTER_HORIZONTAL);
rtb_params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
rtb.setLayoutParams(rtb_params);
txt1=new TextView(this);
rl.addView(txt1);
txt1.setSingleLine();
txt1.setTextSize(TypedValue.COMPLEX_UNIT_PX,15);
txt1.setText("Best Score: ");
txt1_params=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
txt1_params.addRule(RelativeLayout.ALIGN_TOP, rtb.getId());
txt1_params.addRule(RelativeLayout.CENTER_HORIZONTAL);
txt1.setLayoutParams(txt1_params);
txt2=new TextView(this);
rl.addView(txt2);
txt2.setSingleLine();
txt2.setTextSize(TypedValue.COMPLEX_UNIT_PX,30);
txt2.setText(String.valueOf(DataBase.HighScore));
txt2_params=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
txt2_params.addRule(RelativeLayout.ALIGN_TOP, txt1.getId());
txt2_params.addRule(RelativeLayout.CENTER_HORIZONTAL);
txt2.setLayoutParams(txt1_params);
txt3=new TextView(this);
rl.addView(txt3);
txt3.setSingleLine();
txt3.setTextSize(TypedValue.COMPLEX_UNIT_PX,15);
txt2.setText("Current Score: ");
txt3_params=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
txt3_params.addRule(RelativeLayout.ALIGN_TOP, txt2.getId());
txt3_params.addRule(RelativeLayout.CENTER_HORIZONTAL);
txt3.setLayoutParams(txt1_params);
txt4=new TextView(this);
rl.addView(txt4);
txt4.setSingleLine();
txt4.setTextSize(TypedValue.COMPLEX_UNIT_PX,30);
txt4.setText(String.valueOf(DataBase.score));
txt4_params=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
txt4_params.addRule(RelativeLayout.ALIGN_TOP, txt3.getId());
txt4_params.addRule(RelativeLayout.CENTER_HORIZONTAL);
txt4.setLayoutParams(txt1_params);
btn1=new Button(this);
rl.addView(btn1);
btn1_params=new RelativeLayout.LayoutParams(150,40);
btn1_params.addRule(RelativeLayout.CENTER_HORIZONTAL);
btn1_params.topMargin=DataBase.Layout_Height-80-80;//first 80 for the advertisment Bar and second for the two 40-height-buttons
btn1.setLayoutParams(btn1_params);
btn2=new Button(this);
rl.addView(btn2);
btn2_params=new RelativeLayout.LayoutParams(150,40);
btn2_params.addRule(RelativeLayout.CENTER_HORIZONTAL);
btn2_params.addRule(RelativeLayout.ALIGN_TOP, btn1.getId());
btn2.setLayoutParams(btn2_params);
and while these views should be centered horizontally and tactical they appear like that :
http://postimg.org/image/peqhzw0uh/
I want each view to be under another view and all views should be horizontally in the center ! RatingBar(rtb) should be in the top and under that should be
txt1-->txt2-->txt3-->txt4-->btn1-->btn2
I have spent to much time quering this issue and i cant find the answer why this is happening
thank you for your help :)
You need to setId() some identifiers to your views so that the ALIGN_TOP, view.getId() rules actually do something.
Though ALIGN_TOP only aligns the top of the view, making the views draw on top of each other. Use LAYOUT_BELOW rule or a LinearLayout instead.
For a view id, any integer > 0 will do. Just make sure the id's are distinct so the RelativeLayout can find the correct views you're referring to.
For Android Studio's "Expected resource of type Id" error, use #IdRes annotation to annotate your integers as resource identifiers. For example,
#android.support.annotation.IdRes int id = 1;
view.setId(id); // no error
id++; // next id
view2.setId(id); // and so on
... though in this case a LinearLayout would avoid the need of generating ids in the first place.
Since you are using RelativeLayout use txt1_params.addRule(RelativeLayout.BELOW, rtb.getId()); This should do the trick..
Sample Code for txt1 below rtb
txt1_params=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
txt1_params.addRule(RelativeLayout.BELOW, rtb.getId());
txt1_params.addRule(RelativeLayout.CENTER_HORIZONTAL);
txt1.setLayoutParams(txt1_params);
You can use the same code for rest of the views.
Assign id via code (programmatically)
Manually set ids using someView.setId(int);
The int must be positive, but is otherwise arbitrary- it can be whatever you want (keep reading if this is frightful.)
For example, if creating and numbering several views representing items, you could use their item number.
My app is using api 7. I don't know where to start with this challenge.
I have SQLite DB with some numbers stored between 1-99. Now I would like to make number picker for this range which would also remove numbers that are already in DB.
Create a list off the numbers 0-99, then do a query on your database. For every row in the results from the database, check if the list contains is (something like list.contains(number). If it is there, remove it (list.remove(item)) then proceed to the next row
You'll probably have to make your own widget. This will be somewhat involved, and since you are an Android beginner you might better spend your time coming up with a different input method.
In case you do decide to write your own widget, I would recommend extending LinearLayout, then inside of the constructor, doing something like this psuedocode:
setOrientation(VERTICAL);
addView ImageButton arrowUpButton;
addView EditText numberEditText;
addView ImageButton arrowDownButton;
arrowUpButton.setOnClickListener {
int num = myListOfInts.get(currentIndex++);
numberEditText.setText(num);
}
//vice versa for arrowDownButton
you'd also have to create a setter for the myListOfInts.
Good luck!
I have a for loop that each time prints out a row with a TextView within. I want this TextView to be clickable, and when clicked it is supposed to start another activity and send an ID with the Intent. But it's this that I can't manage to work. All links shows up nicely in a table and the textviews are clickable, but all links sends me to the next activity with the same ID, the ID of the last link.
Here is a simplified version of the content of the for loop:
TextView title = new TextView(this);
title.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
title.setText(titleLine);
title.setClickable(true);
title.setId(rows);
rows++;
title.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent myIntent = new Intent(a.this, b.class);
myIntent.putExtra("id", idLine);
a.this.startActivity(myIntent);
}
});
contRight.addView(title);
I suppose the problem is that all textViews looks the same, so the last setOnClickListener works on all links. However, I have added an ID to each title, with this code: title.setId(rows);, so they are all supposed to be unique.
Anybody who can give some help? :) Thanks!
Shouldn't idLine be v.getId()? It's good for this value to be as "fresh" as possible so that you aren't reading an old value: in this case, the value of the last row which had probably been lurking in idLine. Hence, getting the value from the view directly is the safest method.
Also, the "tag" might be a better place to store information than the id. You can access the tag, and indeed store any number of arguments as tags on any view, without changing the id:
title.setTag(rows);
and then later:
intent.putExtra((Integer) v.getTag());
To store multiple objects (with keys) you can use:
title.setTag("rowid", rows);
and then retrieve it using:
intent.putExtra((Integer) v.getTag("rowid"));
and then you could add additional keys if you requirements changed.
In any case, the intention of the tag is to store information for later retrieval, whereas the id is meant to serve as an identifier for finding views in a hierarchy.