How to create the the same fragment several times into a Layout? - android

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!!!

Related

Dynamic Dialog Containing Linear Layouts

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.

Generate a XML layout file dynamically

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.

ListView getChildAt giving NullPointer for not visible elements (Android)

When I select one of the items from the listview that is not visible when the activity is created it throws an exception becuase those that are not visible are null. As you see, I already know why the problem gives the exception and I would thank the one that gives me the tip for solving it. Here's the code.
public void myFunction(View view) {
int i, i2 = 0;
// get the row the clicked button is in
ListView lerroa = (ListView) view.getParent();
i = lerroa.getPositionForView(view);
System.out.println(i + 1);
LinearLayout ll = (LinearLayout) lerroa.getChildAt(i);
TextView pedido = (TextView) ll.getChildAt(0);
}
Any easier way of taking the textview at the item that has been clicked on?
I've solved the problem.
In order to show also the items of the list view that were not visible, those that caused the NullPointers, I've replaced the line of code which crashed the app. Here it is:
Replace:
LinearLayout ll = (LinearLayout) lerroa.getChildAt(i);
For this one:
LinearLayout ll = (LinearLayout) lerroa.getChildAt(i -lerroa.getFirstVisiblePosition()).findViewById(R.id.LinearLayout3);
getVisiblePosition allows us playing with the first item shown at the LinearLayout and so avoids any NullPointer.
I know this is a bit shoddy and that is not the best way to code what I want to achieve. In spite of this, I've seen so many times the same error on the internet but without any correct answare. I wish this would be usefull for others.
Have a nice code!

Referring to programmatically created UI elements in 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!");

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.

Categories

Resources