In my current spring project, one of my activities should be a form where the user can insert a new entity. the code for the activity is like this:
public class FormNewItemActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.form_new_item_view);
Intent intent = getIntent();
Dao<?> dao = intent.getStringExtra(HelloActivity.EXTRA_MESSAGE);
}
}
the layout file should have a list of EditText fields and a unique Button in the end for trigger the saving of the data in a SQLite database.
I wonder if it's possible, giving a list of string with the name of the fields of the entity class, generate a xml layout file dynamically with one EditText for each field.
Anyone knows if this is really possible and how can be done?
You cannot dynamically create and load an XML layout file. However, what you can do is dynamically create the layout programatically which will have the same effect. This method works by creating and adding views at runtime to a layout that serves as a container - such as an empty LinearLayout. In your example you would make R.layout.form_new_item_view contain an empty LinearLayout
<LinearLayout
android:id="#+id/container_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
You would then find your container layout in onCreate
LinearLayout container = (LinearLayout) findViewById(R.id.container_layout);
And then create and add TextView or EditText as you needed from a list of field names
for(String title: listOfTitles){
TextView field = new TextView(this);
field.setText(title);
container.addView(field);
}
To customize the layout further you can set LayoutParams for each view added to control margins and other parameters.
Related
I have a fragment to register customer addresses (called "address") that contains a "+" button.
I want to create another fragment below this containing the same content so that the customer can add as many addresses as he wants to.
I know it's possible to create components one by one programatically. But, this fragmet is a bit complex and I dont want to create it dynamically.
Is that possible to insert the same fragment several times inside a layout of the fragment itself?
I got it!
#Override
public void onClick(View v) {
LinearLayout newlayout = new LinearLayout(getContext());
newlayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
newlayout.setId(ConfigFragment.generateViewId());
LinearLayout parentlayout = (LinearLayout) view.findViewById(R.id.regpet_frame_main);
parentlayout.addView(newlayout);
ConfigFragment.openFragment(new RegPetFragment(), newlayout.getId(), getChildFragmentManager(), getString(R.string.title_reg_pet));
}
Surely new questions will come!!!
I am trying to make a dialog that consists of a LinearLayout which contains a number of other LinearLayouts that are effectively Buttons that each bring you to a website. Instead of statically making each LinearLayout Button in the layout xml file, I have a JSON feed that has a possibly changing number of buttons to display in the dialog. I found a question that looks similar...
... but I'm not sure how to dynamically add LinearLayouts to a Dialog. The data for each of the LinearLayout buttons gets parsed into an ArrayList of items, each representing a Button in the Dialog.
Normally you should use a RelativeLayout for this:
To notice, where your last created button is and to set the next one to the next position costs not so much performance as creating new layouts. You should try to call addView(); as less as possible, because each time the view must be rendered again.
But if it's necessary to add LinearLayouts, here is a sample code:
LinearLayout linearLayout = new LinearLayout(context);
linearLayout.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
linearLayout.setOrientation(LinearLayout.VERTICAL);
viewGroup.addView(linearLayout);
Use a ListView or RecyclerView and control it with an adapter.
For the dialog you can use a DialogFragment. Override the onCreateDialog method and return an AlertDialog inside. The AlertDialog.Builder has the setView method that you can use to inflate your list or recycler. Then just keep a reference to the adapter in your dialog fragment and use it to load your layout-buttons dynamically.
For example:
public class WebsitePickerDialogFragment extends DialogFragment {
Adapter adapter = new YourRecyclerViewAdapter();
#NonNull
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final RecyclerView contentView = LayoutInflater.from(getContext()).inflate(...
contentView.setAdapter(adapter);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(contentView);
return builder.create();
}
}
If you don't want scrolling behavior, you can still use this pattern with any adapter view, like the https://github.com/frankiesardo/LinearListView lib that uses LinearLayout like a ListView.
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 :)
I've made a TableRow class and added my own methods to it. In the TableRow is a EditText where i want to retreive values from. I thought about using the getChildAt() for finding the right EditText in the right TableRow. But because i made my own TableRow class i can't use the getChildAt() wich is in the original TableRow class or parents of it.
So how can i get the EditText values from the tablerows? Create my own getChildAt method?(if so, how?) or is there a different way?
Example-
EditText editEmail, editPass;
String name = "", pass = "";
editEmail=(EditText)findViewById(R.id.editEmail);
editPass=(EditText)findViewById(R.id.editPass);
name = editEmail.getText().toString();
pass = editPass.getText().toString();
you can try this. the values now in string variable and you can use these variables wherever you want.
Whenever you create dynamic view you can assign an id to that view as
final int ID=1001;
EditText et=new EditText(this);
et.setId(ID);
and get the view using
findviewbyid(ID) ;
If you are using xml
android:id="#+id/ed1"
In Activity
EditText et=(EditText)findViewById(R.id.ed1);
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!");