Referring to programmatically created UI elements in Android - android

I was wondering how to refer to an View if I create it programmatically.
I have to create new passenger Views with "Add Passenger" and respectively "Remove Passenger" buttons to my app. The promts are kept LinearLayouts called "#+id/passenger" which have two EditTexts called "#+id/passenger_name" and "#+id/passenger_weight". Those are then kept in a yet another parent LinearLayout called passenger_layout that can hold all the passenger LinearLayouts in a bunch
Adding new passengers is easy, but I have no idea how to refer to the newly created elements. I guess they get a identifier of some sort automatically? I'd prefer them to be "passenger_name%" and "passenger_weight%", where % is an index _passengerCount.
addPassenger.Click += delegate {
//Add to index
++passengerCount;
//Prep new passenger layout
var newLayout = new LinearLayout(Activity);
//Set LayoutParameters from the existing passenger LayoutParameters
newLayout.LayoutParameters = newPassenger.LayoutParameters;
//Prep the new EditTexts
var name = new EditText(Activity);
var weight = new EditText(Activity);
//Set the EditTexts' LayoutParameters from existing LayoutParameters
name.LayoutParameters = new ViewGroup.LayoutParams(passengerName.LayoutParameters);
weight.LayoutParameters = new ViewGroup.LayoutParams(passengerWeight.LayoutParameters);
//These cleary don't work :<
// name.Id = Resources.GetIdentifier( "passenger_name" + passengerCount, "id", Activity.PackageName);
// weight.Id = "passenger_weight" + passengerCount;
//Add EditTexts to the new passenger layout and then and then add the new passenger to the parent LinearLayout
newLayout.AddView(name);
newLayout.AddView(weight);
passengerLayout.AddView(newLayout);
Log.Debug(GetType().FullName, "Add clicked");
};
That is my click delegate to create a new passenger, but again even if I create them like this I don't know how I can find them later if I have to for example remove them or get the name or weight data.
How do I refer to programmatically created UI elements?

When you create a view, try giving it some ID, and holding that ID as a static reference somewhere.
Then, you could simply call the containing view's findViewById(MY_VIEWS_ID) and get the view.
Of course, alternatively, you could always hold a reference to the view you created somewhere in your code when you create it. If you're afraid of memory leaks, you could use WeakReference.
Hope this helps.

You could maintain a static variable within the Activity that will contain the UI element after it gets initialized.
Something like:
// Definition
private static TextView textViewToSave = null;
textViewToSave = // create the TextView programatically.
// Do stuff with the saved TextView
textViewToSave.setText("O Hai world!");

Related

Custom ListView adapters with dynamic textView creation within the listview adapter

My requirement goes like the following:
Create a custom listview which has a title and subtitle (static contents from xml), followed by a linear layout which contains textviews, that will be created on runtime/dynamic. The number of textviews to be created on runtime may vary between 1-10. Beneath the linear layout, there could be one image or a textview (but only one).
Edit: Also these dynamic textview may or may not contain compound drawables on runtime.
I have tried the custom adapter extending the baseadapter and could achieve the title and subtitle along with image and textview. But I am unable to create dynamic textviews and add them to the listview's current list item.
Please find a sample reference in the image, the red bordered line represents the dynamic textviews to be created.
Code Below:
for(int i =0; i< jsonDetails.size(); i++) {
mh.textview1 = new TextView(context);
if(null != jsonDetails.get(i+"")) {
mh.linearLayout.addView(mh.textview1);
mh.textview1.setLayoutParams(mh.textViewLP);
mh.textview1.setGravity(Gravity.CENTER_VERTICAL);
mh.textview1.setText("Test" + i);
}
}
I would advise against trying to add/remove some arbitrary number of textviews dynamically like this. The approach I would take would be to combine the text elements into one element and always have just one TextView in the layout of your list item.
StringBuilder builder = new StringBuilder();
for (int i =0; i< jsonDetails.size(); i++) {
if (null != jsonDetails.get(Integer.toString(i)) {
builder.append("APPEND TEXT HERE");
}
}
mh.textView.setText(builder.toString());
Ended up with creating a new stringbuilder object with ," " quote. And appended each string to the text view. Finally I got the output working as required when used with linear layout n stuffs. Thanks for ur help :)

Android: give textfield 'id' in java

I was wondering how to give a TextField an 'id' in java. So I am pretty much wanting to know how to give the TextField android:id="#id/NAMEHERE" but do it in java. Here is the code so far:
TextView taskname = new TextView(this);
taskname.setText("Task " + tasknumber);
tasklayout.addView(taskname);
What do I need to add to give it an id?
If your question is to how to set id into activity, then understand purpose of id.
Id is specially required when you want to fetch view reference into activity class, where view has been declared into xml file. But in Activity, if you are creating any view, by
TextView taskname = new TextView(this);
here, you already have view reference, but if you still want to set id, then you can use method
taskname.setId(10002);
Try this
static final int TEXT_ID = 80001;
TextView taskname = new TextView(this);
taskname.setId(TEXT_ID);
and later in your code you can refer to this textview by
TextView t = (TextView)findViewById(TEXT_ID);
or
TextView t = taskname;

How to identify associated widget when list item is clicked?

I have been able to create a ListActivity that displays a header and a footer, and sandwiched between these a custom layout that contains on each row three checkboxes and a Contact name (reading from the Contacts database). I use a SimpleCursorAdapter to display this info. My problem has been getting the OnListItemClicked()* to fire. I click in the ListView (on the checkboxes AND on the name of the Contact) and my breakpoint is never reached. So: What must I do to get that to fire. I AM setting it, like so:
lv.SetOnListItemClicked(etc);
I think it is; I'm not at my dev machine right now
But even if I am able to get the click event to fire, how will I be able to identify the associated checkboxes? They are named ckbx1, ckbx2, and ckbx3 (or so) in the layout file, but there will be (Contacts.Count) of them, so how can I positively identify which ones have been clicked?
My other option is to dynamically create the widgets in the Activity's OnCreate().
My pseudocode for this is the following, and I'm open to suggestions/feedback on whether this makes or is [not] the best way to go about it:
OnCreate() {
Cursor c = getContacts();
for (i = 0, i == c.Count, i++) {
int id = getContactID(i);
CheckBox ckbx1 = new CheckBox();
ckbx1.Tag = id;
ckbx1.OnClick = Checkbox1Click();
CheckBox ckbx2 = new CheckBox();
ckbx2.Tag = id;
ckbx2.OnClick = Checkbox2Click();
CheckBox ckbx3 = new CheckBox();
ckbx3.Tag = id;
ckbx3.OnClick = Checkbox3Click();
TextView tv = new TextView();
tv.Text = getContactName(i);
}
Checkbox1Click() {
int ContactID = (CheckBox)object.Tag;
switch (ContactID)
case 1:
WriteToDB(1, Option1);
case 2:
WriteToDB(2, Option1);
...
}
This (especially the CheckboxClick event handler) is obviously very rough, but I think you can get the drift of where I'm going with this - saving the "checked" state of the Checkboxes to a SQLite DB so that I know Contact1 wants email (or twitter feed, or whatever the other two checkboxes indicate).
So is my previous method salvageable, or should I go down this new path (or veer off a little from that?)
Usually i uses View.setTag to identify a view instance. For example,
checkBox.setTag("listItem1");

Re-using a radiobutton in Android

Th question: Can I re-use RadioButton objects over and over again in an child activity?
I have a parent activity and a child activity. In the child activity, I have a large number of radio button displayed in a UI. In order to provide databinding from the parent down to the child, I have created a class (below) which contains a collection of RadioButtons. To populate the child activity, I pass a reference to this class down to the child which then groups the radioButtons into RadioGroups and displays them. I do this because the checked status of each button is now automatically available in the parent class, without the need to transfer any data through bundles.
public class GeneralAttribute{
Activity mThis;
public class Gender { // Mutually exclusive members
String categoryDesc = "Gender of user";
RadioButton isUnspecified = initRadioButton("Unspecified", true);
RadioButton isMale = initRadioButton("Male" , false);
RadioButton isFemale = initRadioButton("Female" , false);
} ;
<....more subclasses....>
RadioButton initRadioButton(String str, Boolean b) { // Factory
float cLayoutWeight = 0.5f;
RadioButton rb = new RadioButton(mThis);
rb.setText (str);
rb.setChecked(b);
rb.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, cLayoutWeight));
return rb;
}
GeneralAttribute(Activity localThis){ // Constructor
mThis = localThis;
gender = new Gender();
handedness = new Handedness();
location = new Location();
}
}
In the parent activity i have:
public class Parent(...)
public GeneralAttribute mGeneralAttribute; // Member class of RadioButtons
public static SPIGestureLoggerActivity TopLevelActivity;// Reference to the parent activity
public void onCreate(Bundle savedInstanceState) {
TopLevelActivity = this; // Assign this to the reference
mGeneralAttribute = new GeneralAttribute(this); // Initialize the class of RBs
startActivity(child); // Start the child
In the child activity i have this:
radiogroup = new RadioGroup(this);
radiogroup.setOrientation(RadioGroup.VERTICAL);
radiogroup.addView(Parent.TopLevelActivity.mGeneralAttribute.gender.isUnspecified);
radiogroup.addView(Parent.TopLevelActivity.mGeneralAttribute.gender.isMale);
radiogroup.addView(Parent.TopLevelActivity.mGeneralAttribute.gender.isFemale);
Parent.TopLevelActivity.mGeneralAttribute.gender.isUnspecified.setChecked(true);
mLinearLayout.addView(radiogroup);
This works fine....the first time the child activity is displayed. The second time it is displayed I get an exception.
In summary, here is the chain of events:
create the class of RadioButtons,
pass them to the child,
add them to a new RadioGroup
collect user choices
finish the child acitivty (which should destroy the RadioGroups)
use the data in the parent,
start the child activity again,
attempt to add the RadioButtons to new RadioGroups...
...Exception.
I can avoid this problem, if I null the class and reconstruct it. However, I would like to re-show the choices made from the first viewing with the second viewing.
Ideas:
Are the radioButtons saving pointers to the non-existant RadioGroups from the first viewing?
Is there a way to re-assign the view parent on each radio button in the class?
P.S. You may ask why I'm not using XML. For one, I will have 100+ of these radio buttons and I think it will be too painful to manage through XML. For another, I just like working programmatically on these things.
make sure you remove all the radiobuttons from the all radiogroups. Basically your right the radiobuttons are saving pointers to the non-existant raidogroups and no there isn't isn't a way to reassigned without calling removeAllViews on all the radiogroups. The best place to do that will be the onDestroy if your sure thats being called.

Repeat view in a single activity

I have a activity which shows a button, a text and a list. I would like to repeat that pattern depending on data (SQLite). If I have 5 unique categories, show 5 buttons, 5 text and 5 lists. How do I do that ? How can I repeat the pattern ?
You can just add a new button text and list to the same LinearLayout. So..
addStuffz(){
LinearLayout main = (LinearLayout)findViewById(R.id.main_linearLayout);
LinearLayout newLayout = new LinearLayout(context);
/**
* Do Init here
*/
Button anotherButton = new Button(context);
/**
* Do Init here
*/
TextView anotherText = new TextView(context);
/**
* Do Init here
*/
ListView anotherList = new ListView(context);
/**
* Do Init here
*/
newLayout.addView(anotherButton);
newLayout.addView(anotherText);
newLayout.addView(anotherList);
mainLayout.addView(newLayout);
}
The standard design pattern is to use a ListActivity(or a standard activity with a listView)
and create a CursorAdapter to create views and databind values from your recordset cursor to the view.
Then call setAdapter() on your ListActvity.
VIDEO
The use of list adapters is dicussed in the Google IO 2009 video on UI improvements
in android you cannot "repeat a view" in a same actiivty (a child cannot have more than 1 parent ) but u can always do a workaround. u can write a mehod as getview() which returns u a parent view conatining ur buttons, texts etc. and u add this to the top layer viewgroup;
while(somelogic)
urparentview.addview(getview());
setcontentview(urparentview)
ur getviewmethod may be like this
view getview()
{
button b = new button(this);
edittext ed = new edittext(this);
//set orientations etc...
LinearLayout ll = new LineaLayout(this);
ll.addview(b);
ll.addView(ed);
return ll;
}

Categories

Resources