I'm using a spinner for selecting amounts to re-calculate quantities of recipe-ingredients.
I have a horizontal LinearLayout which I add a label(TextView) to to describe the spinner and then the spinner.
When I first load the activity, the label is positioned a bit higher than the spinner, when I select an item, it corrects its height.
How do I fix that?
Code of my spinner-loading method:
// Horizontal LinearLayout for displaying label + spinner
LinearLayout spinnerLayout = new LinearLayout(getApplicationContext());
spinnerLayout.setOrientation(LinearLayout.HORIZONTAL);
spinnerLayout.setLayoutParams( new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT));
// Textview for description
TextView lblAmount = new TextView(getApplicationContext());
lblAmount.setText("Quantity:");
lblAmount.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
lblAmount.setTextColor(Color.parseColor("#161618"));
spinnerLayout.addView(lblAmount);
// add spinner
ArrayList<Integer> spinnerArray = new ArrayList<Integer>();
for(int i = 1; i<= 10; i++) {
spinnerArray.add(i);
}
final Spinner spnIngredientQuantity = new Spinner(this);
ArrayAdapter<Integer> spinnerArrayAdapter = new ArrayAdapter<Integer>(this, android.R.layout.simple_spinner_dropdown_item, spinnerArray);
spnIngredientQuantity.setAdapter(spinnerArrayAdapter);
spnIngredientQuantity.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
spinnerLayout.addView(spnIngredientQuantity);
if(firstLoad) {
spnIngredientQuantity.setSelection(spinnerArrayAdapter.getPosition(recipe.getDefaultAmount()));
firstLoad = false;
}
spnIngredientQuantity.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
reloadIngredients((int) spnIngredientQuantity.getSelectedItem());
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
// Use default Quantity
}
});
scrollLayout.addView(spinnerLayout);
I think it might be the fact, that I add the spinnerLayout with height set to WRAP_CONTENT, so it's smaller when the TextView comes in. later, the spinner takes more space in height, but the textView doesn't get updatet.
Could that be the problem?
edit: attached screenshot
I don't know what actually caused the problem,but I fixed it with centering the textView horizontally:
spinnerLayout.setGravity(Gravity.CENTER_VERTICAL);
Related
In my app there is a Spinner for colors and a Button for the user to add additional spinners in different colors. An existing spinner is coupled with a delete button for removal upon creation. It looks like this -
I'm trying to accomplish the following:
The user clicks "ADD PAINTYPE"
A Spinner is created, given it is not already present in the List
If the user deletes the item, it is available to insert again.
I´m pretty new to Android App development, and this logic is difficult for me to work through. Any suggestions on how to approach this would be appreciated.
Edit: Blow down is the function, which called after user click the button "ADD PAINTYPE". The arrayAdapter of the newly created spinner is as same as the fisrt one(which in the left side of the "ADD PAINTYPE" button). Right now all Spinners are sharing the sam adapter. What I want to achieve is, When I choose a Option in one spinner, then dynamiclly the option will not be listed in other spinners.(e.g. The "ANFALLSTARTIGER" would not be listed in the second and the third spinners). Is this possible?
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
protected void addItem(Context context,View view) {
if(clickedTimes < 16) {
clickedTimes++;
final LinearLayout linearLayout = new LinearLayout(context);
Spinner spinner = new Spinner(context);
spinner.setPopupBackgroundResource(R.color.white);
spinner.setBackgroundColor(getResources().getColor(R.color.white));
final Button button = new Button(context);
final Button button_delete = new Button(context);
button_delete.setText("DELETE");
button_delete.setTextColor(getResources().getColor(R.color.white));
button_delete.setBackground(context.getDrawable(R.drawable.mybutton));
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
linearLayout.setWeightSum(6);
LinearLayout.LayoutParams params_0 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
linearLayout.setLayoutParams(params_0);
LinearLayout.LayoutParams params_1 = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 4.0f);
spinner.setLayoutParams(params_1);
params_1.setMargins(2, 2, 2, 2);
LinearLayout.LayoutParams params_2 = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f);
params_2.setMargins(2, 2, 2, 2);
button.setLayoutParams(params_2);
button_delete.setLayoutParams(params_2);
LinearLayout layout = (LinearLayout) view.findViewById(R.id.all_paintype);
layout.addView(linearLayout);
linearLayout.addView(spinner);
linearLayout.addView(button);
linearLayout.addView(button_delete);
button_delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
LinearLayout layoutAll = (LinearLayout) view.findViewById(R.id.all_paintype);
layoutAll.removeView(linearLayout);
spinners.remove(spinner);
clickedTimes--;
}
});
dropBoxButton(spinner, button, clickedTimes);
spinners.add(spinner);
}else {
Toast toast = Toast.makeText(getContext(),"Maximal Pain Type",Toast.LENGTH_SHORT);
toast.show();
}
}
protected void dropBoxButton(Spinner spinner, final Button button, int clickedTimes) {
arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(arrayAdapter);
spinner.setSelection(clickedTimes);
spinner.setVisibility(View.VISIBLE);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String string_1 = ((TextView) view).getText().toString();
setButtonColor(button, string_1);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
Finally found a workaround: I decided to just use a table with a single row and then set stretchAllColumns to true. This means it just mimics a horizontal layout with spread-out views.
I am trying to instantiate a horizontal linear layout at runtime and I would like the elements in the layout to spread out along the full width of the layout. I would also like everything to be center-vertical aligned. This is currently what I've got:
LinearLayout tertiaryLinearLayout = new LinearLayout(getActivity());
tertiaryLinearLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
tertiaryLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
tertiaryLinearLayout.setGravity(Gravity.FILL_HORIZONTAL);
This instantiates the layout but the elements in it don't correctly fill the full width of it. I am also not sure how I can get them to be center-vertical aligned without changing setGravity to
tertiaryLinearLayout.setGravity(Gravity.CENTER_VERTICAL);
This TextView is one of the five elements I add to the layout:
TextView dash = new TextView(getActivity());
dash.setText("-");
Two of the elements are ImageViews and the other three are TextViews. Here is how it looks currently:
https://i.stack.imgur.com/MGLyJ.jpg
EDIT:
The overall structure is a ScollView with a vertical LinearLayout. This LinearLayout holds lots of other vertical LinearLayouts, each with a horizontal LinearLayout. Hope that makes sense.
The parent view of tertiaryLinearLayout is here:
LinearLayout secondaryLinearLayout = new LinearLayout(getActivity());
secondaryLinearLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
secondaryLinearLayout.setOrientation(LinearLayout.VERTICAL);
...
secondaryLinearLayout.addView(tertiaryLinearLayout);
EDIT 2:
Here is my full code:
...
final LinearLayout linearLayout = root.findViewById(R.id.leagueLinearLayout);
List<Game> currentYearCategory = MainActivity.yearCategories.get(0);
for (int i = 0; i < currentYearCategory.size(); i++) {
TextView textView = new TextView(getActivity());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
textView.setLayoutParams(params);
textView.setText(currentYearCategory.get(i).date);
linearLayout.addView(textView);
}
seekBarChange(linearLayout, root, 0);
// Set up seek bar
SeekBar yearSeekBar = root.findViewById(R.id.yearSeekBar);
yearSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
seekBarChange(linearLayout, root, progress);
}
...
...
private void seekBarChange(LinearLayout linearLayout, View root, int progress){
TextView yearTextView = root.findViewById(R.id.yearTextView);
String newText = (1890 + progress * 10) + " - " + (1899 + progress * 10);
yearTextView.setText(newText);
final List<Game> currentYearCategory = MainActivity.yearCategories.get(progress);
linearLayout.removeAllViews();
for (int i = 0; i < currentYearCategory.size(); i++) {
// Create views
LinearLayout secondaryLinearLayout = new LinearLayout(getActivity());
secondaryLinearLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
secondaryLinearLayout.setOrientation(LinearLayout.VERTICAL);
View separatorView = new View(getActivity());
separatorView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 50));
TextView date = new TextView(getActivity());
date.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
date.setText(currentYearCategory.get(i).date);
LinearLayout tertiaryLinearLayout = new LinearLayout(getActivity());
tertiaryLinearLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
tertiaryLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
tertiaryLinearLayout.setGravity(Gravity.CENTER_VERTICAL);
ImageView homeImage = new ImageView(getActivity());
homeImage.setLayoutParams(new ViewGroup.LayoutParams(150, 150));
if (currentYearCategory.get(i).celticIsHome){
homeImage.setBackgroundResource(R.drawable.celtic_logo);
} else {
homeImage.setBackgroundResource(R.drawable.rangers_logo);
}
TextView homeScore = new TextView(getActivity());
homeScore.setText(currentYearCategory.get(i).fullTimeScore.substring(0, 1));
TextView dash = new TextView(getActivity());
dash.setText("-");
TextView awayScore = new TextView(getActivity());
awayScore.setText(currentYearCategory.get(i).fullTimeScore.substring(2));
ImageView awayImage = new ImageView(getActivity());
awayImage.setLayoutParams(new ViewGroup.LayoutParams(150, 150));
if (currentYearCategory.get(i).celticIsHome){
awayImage.setBackgroundResource(R.drawable.rangers_logo);
} else {
awayImage.setBackgroundResource(R.drawable.celtic_logo);
}
// Add views
tertiaryLinearLayout.addView(homeImage);
tertiaryLinearLayout.addView(homeScore);
tertiaryLinearLayout.addView(dash);
tertiaryLinearLayout.addView(awayScore);
tertiaryLinearLayout.addView(awayImage);
secondaryLinearLayout.addView(separatorView);
secondaryLinearLayout.addView(date);
secondaryLinearLayout.addView(tertiaryLinearLayout);
final int gameNum = i;
secondaryLinearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openGameActivity(currentYearCategory, gameNum);
}
});
linearLayout.addView(secondaryLinearLayout);
}
}
Any help would be greatly appreciated, thanks!
I guess that the PARENT view that the tertiaryLinearLayout will be added to is wrap_content for the layout_width. Try to make its width match_parent. You should have a look on this tutorial at 2:52s
In my main.xml I have a LinearLayout:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/linearMain"
>
</LinearLayout>
Then, inside my Main.java I am retrieving values from the DB (name and price of an item). Then, I dynamically created my form using the below code:
Cursor cursor = mydb.getAllJuice();
lm = (LinearLayout) findViewById(R.id.linearMain);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ActionBar.LayoutParams.WRAP_CONTENT, ActionBar.LayoutParams.WRAP_CONTENT);
while (cursor.moveToNext()) {
int cid = cursor.getInt(0);
String id = Integer.toString(cid);
String name = cursor.getString(1);
String price = cursor.getString(2);
// Create LinearLayout
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.HORIZONTAL);
// Create TextView
TextView product = new TextView(this);
product.setText(name+" ");
ll.addView(product);
// Create TextView
TextView pricetxt = new TextView(this);
pricetxt.setText(" "+price);
ll.addView(pricetxt);
// Create TextView
TextView currency = new TextView(this);
currency.setText(" LL ");
ll.addView(currency);
// Create TextView
TextView qtylabel = new TextView(this);
qtylabel.setText("QTY ");
ll.addView(qtylabel);
EditText qty = new EditText(this);
qty.setMinLines(1);
qty.setMaxLines(3);
ll.addView(qty);
lm.addView(ll);
}
// Create LinearLayout
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.HORIZONTAL);
final Button btn = new Button(this);
// Give button an ID
int j = 122;
btn.setId(j+1);
btn.setText("Add To Cart");
// set the layoutParams on the button
btn.setLayoutParams(params);
//Add button to LinearLayout
ll.addView(btn);
//Add button to LinearLayout defined in XML
lm.addView(ll);
The user will be able to enter the number of items and consequently onClick of the button a TextView will be manipulated.
To fill this textview I will need to loop on all the items that were created to check the price and check how the number that the user entered. I tried using the below code, however I am not able to access the specific item that I want as I have in each row 2 TextView and 1 editText:
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// code will be here
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
total = 0 ;
View v1 = null;
for(int i=0; i<lm.getChildCount(); i++) {
v1 = lm.getChildAt(i);
}
}
});
How can I access the different element in the v1?
You can use tag parameter of your Views (TextView, EditText etc.): setTag(Object) . Tags are essentially an extra piece of information that can be associated with a view. They are most often used as a convenience to store data related to views in the views themselves rather than by putting them in a separate structure. Check Android documentation for more details.
P.S. Instead to use your approach, you can use RecyclerView (or older ListView) with ViewHolder. This already mentioned in comments.
Answer to your question:
The problem is that your "product", "pricetxt", "btn" variables are local variables and gets garbage collected after your current loop iteration is over.
Well you can implement view holder pattern in your project.
Create a class named ViewHolder
class ViewHolder{
LinearLayout ll;
TextView product;
TextView pricetxt ;
TextView currency ;
TextView qtylabel ;
EditText qty ;}
public ViewHolder(LinearLayout ll TextView product TextView pricetxt TextView currency TextView qtylabel EditText qty)
{
this.l1= l1;
this.product=product;
this.pricetxt=pricetxt;
this.currency = currency;
this.qtylabel = qtylevel;
this.qty = qty;
}
This class can hold all your data by passing all these parameters (qty, pricetxt, etc).
Now you have to maintain a List for this ViewHolder Object at the top. You can do this as-
List myList<ViewHolder> = new ArrayList<ViewHolder>();
At the end of every iteration, create and add the ViewHolder object;
You can do this as follows
ViewHolder currentView = new ViewHolder(l1.product,pricetxt,currency,qtylabel,qty);
myList.add(currentView);
myList.add(currentView);
You can access any ViewHolder object maintained inside the list at position "index" as
myList.get(index);
Or the EditText "qty" as
myList.get(index).qty;
In this way you can access your created EditTexts and TextView even after the loop iteration is over.
My Suggestion:- No one does it in this way. As suggested some guys over here you should you android implement recommended RecyclerView which is much more efficient than the current implementation. In cases you can even you ListView.
I am working on a project in which I need to dynamically add TextView and Spinner as well. I was able to add these two things dynamically from my program.
Now when I was trying to select some items in the Spinner, it was not selecting those items.
Does I need to do anything to make that item selected in Spinner?
for (Map.Entry<String, String> entry : mapColumns.entrySet()) {
spinnerArray = new ArrayList<String>();
final TextView rowTextView = new TextView(cont);
final Spinner spinner = new Spinner(cont);
rowTextView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
spinner.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
for(String s: entry.getValue().split(",")) {
System.out.println(s);
s = s.replaceAll("[^a-zA-Z0-9]+","");
spinnerArray.add(s);
}
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(cont, android.R.layout.simple_spinner_dropdown_item, spinnerArray);
rowTextView.setText(entry.getKey());
rowTextView.setTypeface(null, Typeface.BOLD);
spinner.setAdapter(spinnerArrayAdapter);
layout.addView(rowTextView);
layout.addView(spinner);
}
Here mapColumns will hev Key-Value pair. So in the Spinner all the items are getting shown from the Value of that map.
Problem Statement:-
Now I need to make sure if anybody is selecting any items in the Spinner, it should get selected and visible to naked eye.
How can I do that based on my code. Thanks for the help.
Below is the image-
Try use this code :
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(con,
android.R.layout.simple_spinner_item, spinnerArray);
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
Add an OnItemSelectedListener to your spinner:
spinner.setAdapter(spinnerArrayAdapter);
// add the listener
spinner.setOnItemSelectedListener(this);
Then, implement the listener in your activity:
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
// An item was selected. You can retrieve the selected item using
// parent.getItemAtPosition(pos)
}
public void onNothingSelected(AdapterView<?> parent) {
// Another interface callback
}
I have a problem on displaying th JSON Result in my tableView wherein instead of clearing the tablerows before inserting the fetched data, it just concatinates the new data from the old ones and I can't figure out why. Here's my code:
First I have a JSON Parser which gets all of the information based on the selected city and dates and I think there is no need to show that part but I just add the data into List Array then do this part.
public void showinfo(){
// Get the TableLayout
TableLayout tl = (TableLayout) findViewById(R.id.maintable);
tl.removeAllViews();
Log.v(KahelTag, "eventsCleared");
// Go through each item in the array
for (int current = 0; current < infoID.size(); current++)
{
TableRow tr = new TableRow(this);
tr.setId(100+current);
tr.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
//CREATE TEXT VIEW FOR INFO1
final TextView info1 = new TextView(this);
clubName.setId(200+current);
clubName.setText(info1.get(current));
clubName.setTextColor(Color.WHITE);
clubName.setTextSize(12);
clubName.setTypeface(null, Typeface.BOLD);
clubName.setTag(infoID.get(current));
clubName.setGravity(Gravity.CENTER_VERTICAL);
clubName.setLayoutParams(new LayoutParams(
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 65, getResources().getDisplayMetrics()),
LayoutParams.WRAP_CONTENT));
tr.addView(info1);
//CREATE TEXT VIEW FOR info2
TextView info2 = new TextView(this);
eventName.setId(current);
eventName.setText(info2.get(current));
eventName.setGravity(Gravity.CENTER_VERTICAL);
eventName.setTextSize(12);
eventName.setTextColor(Color.WHITE);
eventName.setLayoutParams(new LayoutParams(
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 120, getResources().getDisplayMetrics()),
LayoutParams.WRAP_CONTENT));
tr.addView(info2);
//CREATE TEXT VIEW FOR INFO3
TextView info3 = new TextView(this);
eventDate.setId(current);
eventDate.setText(info3.get(current));
eventDate.setGravity(Gravity.CENTER_VERTICAL);
eventDate.setTextSize(12);
eventDate.setTextColor(Color.WHITE);
eventDate.setLayoutParams(new LayoutParams(
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80, getResources().getDisplayMetrics()),
LayoutParams.WRAP_CONTENT));
tr.addView(info3);
// Add the TableRow to the TableLayout
tl.addView(tr, new TableLayout.LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
}
}
Now I show that info after setting the content view with showinfo();
And now for the spinner part. It just call again the JSON codes to change parameters then Display the info out in the table again. But It doesn't work as I wanted since as I said above it just concatinates the data. By the way, I have two parameters that is passed for my JSON text. Here's the code for the spinner:
Spinner spinParam1 = (Spinner) findViewById(R.id.spinner1);
Spinner spinParam2 = (Spinner) findViewById(R.id.spinner2);
spinParam1.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
Object specify_param1 = parentView.getItemAtPosition(position);
if(specify_param1.toString() != "All"){
getEvents(specify_param1.toString(),null);
showinfo();
Log.v(KahelTag, "showinfo");
}
else
{
getEvents(null,null);
showinfo();
Log.v(KahelTag, "elseshowinfo");
}
}
public void onNothingSelected(AdapterView<?> parentView) {
getEvents(null,null);
showinfo();
Log.v(KahelTag, "nothingshowinfo");
}
});
spinParam2.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
Object specify_param2 = parentView.getItemAtPosition(position);
if(specify_param2.toString() != "Any"){
getEvents(specify_param2.toString(),null);
showinfo();
Log.v(KahelTag, "showinfo");
}
else
{
getEvents(null,null);
showinfo();
Log.v(KahelTag, "elseshowinfo");
}
}
public void onNothingSelected(AdapterView<?> parentView) {
getEvents(null,null);
showinfo();
Log.v(KahelTag, "nothingshowinfo");
}
});
Any revisions that I need to make for this to work the way I wanted? Thanks!
If you do it this way i'd do
tl = new TableLayout();
But why don't you use listview with a custom adapter instead, it sounds a lot more like what you need. Then you dont need to create x100 tablerows etc.
Haven't noticed it but the main cause of the problem is the JSON String array where I store all of the data which is why it concatenates the data from the previous output. Solved the problem by clearing out the arrays first before parsing JSON string. :)