Dynamically created TextViews in Java - NullPointerException - java

I try to add dinamically some TextViews in Java. I assume that when I want to use setText() method, I should earlier connect my Java's TextView object with XML's TextView - I use setId().
At the end, I got NullPointerException in the line where I use setId().
My code:
TextView[] tvQuestion = new TextView[numberOfQuestions];
TextView[] tvAnswer1 = new TextView[numberOfQuestions];
TextView[] tvAnswer2 = new TextView[numberOfQuestions];
TextView[] tvAnswer3 = new TextView[numberOfQuestions];
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
for (int i = 0; i < numberOfQuestions; i++) {
tvQuestion[i].setId(View.generateViewId()); // NullPointerException!
tvAnswer1[i].setId(View.generateViewId());
tvAnswer2[i].setId(View.generateViewId());
tvAnswer3[i].setId(View.generateViewId());
tvQuestion[i].setLayoutParams(params);
tvAnswer1[i].setLayoutParams(params);
tvAnswer2[i].setLayoutParams(params);
tvAnswer3[i].setLayoutParams(params);
tvQuestion[i].setText(question[i]);
tvAnswer1[i].setText(option1[i]);
tvAnswer2[i].setText(option2[i]);
tvAnswer3[i].setText(option3[i]);
layAll.addView(tvQuestion[i]);
layAll.addView(tvAnswer1[i]);
layAll.addView(tvAnswer2[i]);
layAll.addView(tvAnswer3[i]);
}
EDIT:
Solution: Philipp Jahoda's post.

You just created an Array for the TextViews. The TextViews inside the Array are null as long as they are not initialized.
So you need to call
tvQuestion[i] = new TextView(Context);
tvAnswer[i] = new TextView(Context);
// and so on ...
// and then later
tvQuestion[i].setId(View.generateViewId());
// and so on ...
before setting the ID and other stuff.

Related

How can I set a view's gravity and layout_gravity programmatically in Java instead of XML?

For my activity, we were tasked with creating the views entirely programmatically (not allowed to use XML).
I created what I want the layout to look like in XML.
but I'm having trouble getting my contentEditText and the gravities to correctly set the, up as I've done in the XML file.
This is what I have for my view.
public class NoteGridLayout extends GridLayout {
public NoteGridLayout(final Context context, EditText titleEditText, Spinner spinner, EditText contentEditText, Button backButton) {
super(context);
setColumnCount(2);
GridLayout.Spec colSpec, rowSpec;
colSpec = GridLayout.spec(0, 1, 1);
rowSpec = GridLayout.spec(0, 0, 0);
GridLayout.LayoutParams titleParams = new GridLayout.LayoutParams(rowSpec, colSpec);
colSpec = GridLayout.spec(1,1,1);
rowSpec = GridLayout.spec(0,0,0);
GridLayout.LayoutParams spinnerParams = new GridLayout.LayoutParams(rowSpec, colSpec);
colSpec = GridLayout.spec(0,2,1);
rowSpec = GridLayout.spec(1,1,1);
GridLayout.LayoutParams contentParams = new GridLayout.LayoutParams(rowSpec, colSpec);
colSpec = GridLayout.spec(0,2,1);
rowSpec = GridLayout.spec(2,1,0);
GridLayout.LayoutParams buttonParams = new GridLayout.LayoutParams(rowSpec, colSpec);
titleParams.width = 0;
titleParams.height = LayoutParams.WRAP_CONTENT;
spinnerParams.width = 0;
spinnerParams.height = LayoutParams.WRAP_CONTENT;
contentParams.width = 0;
contentParams.height = 0;
buttonParams.width = LayoutParams.MATCH_PARENT;
buttonParams.height = LayoutParams.WRAP_CONTENT;
contentParams.setGravity(Gravity.TOP);
titleEditText.setLayoutParams(titleParams);
spinner.setLayoutParams(spinnerParams);
contentEditText.setLayoutParams(contentParams);
backButton.setLayoutParams(buttonParams);
addView(titleEditText);
addView(spinner);
addView(contentEditText);
addView(backButton);
}
}
The two main problems I'm having are:
1. The titleEditText is not appearing to span an entire column, rather, the spinner is taking up the whole two columns.
2. The contentEditText gravity is not able to be set, placing the text at the top of the box.
What do I need to do to fix these two problems?
For layout_gravity following is a code snippet,
LinearLayout.LayoutParams params = new
LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
params.weight = 1.0f;
params.gravity = Gravity.CENTER;
yourView.setLayoutParams(params);
For Gravity use following line,
yourLayout.setGravity(Gravity.CENTER)

Android making CardViews programmatically

I am trying to create CardView type objects which will enable users to input their working hours for each day. I first did them in plain xml, which worked flawlessly, but not once I had to make some small changes and that meant modifying the code in 8 places.
I managed to understand how to create the cardviews programmatically ( I am using an enum type class in order to hold id's and names for the elements from the cardviews. The problem is, the result doesn't work as it should.
I can't manage to make the elements( CheckBox, TextView, SpinnerStart, SpinnerEnd) to be in the right place.
_checkBox should be aligned to the start of _relativeLayoutInCard, _TVDayLabel after it, then _spinnerEnd aligned to the end of the relatie layout and _spinnerStart at the beginning of spinnerEnd
The problem seems to be at the _layoutParamsOtherViews
private void createCards() {
/* get each day from enum and make the card
* with the necessary elements
*/
DaysOfWeek _previousDay = DaysOfWeek.MONDAY;
RelativeLayout _rootRelativeLayout = mActivity.findViewById(R.id.act_SWHours_RL_RootCV);
for (DaysOfWeek _day : DaysOfWeek.values()) {
Log.d("Stop", _day.geteDisplayName());
CardView _cardview = new CardView(mActivity, null, R.style.CardViewSWHours);
RelativeLayout.LayoutParams _layoutParamsCV = new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT
);
/* for Checkbox, Textviews and spinners inside CV */
RelativeLayout.LayoutParams _layoutParamsOtherViews = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT
);
RelativeLayout _relativeLayoutInCard = new RelativeLayout(mActivity, null, R.style.RelativeLayoutInCVSWHours);
_relativeLayoutInCard.setLayoutParams(_layoutParamsCV);
if(_day.geteDisplayName().equals("Monday") || _day.geteDisplayName().equals("All week days")) {
Log.d("Stop", "It gets here");
_layoutParamsCV.addRule(RelativeLayout.BELOW, R.id.act_SWHours_CB_DiffHours);
}
else {
_layoutParamsCV.addRule(RelativeLayout.BELOW, _previousDay.getCardViewId());
}
if(_day.geteDisplayName().equals("Saturday")) {
_layoutParamsCV.addRule(RelativeLayout.BELOW, DaysOfWeek.ALLDAYS.getCardViewId());
}
_layoutParamsCV.setMargins(64, 9, 64, 9);
_cardview.setRadius(32);
_cardview.setCardElevation(6);
_cardview.setId(_day.getCardViewId());
_cardview.setLayoutParams(_layoutParamsCV);
_rootRelativeLayout.addView(_cardview);
_cardview.addView(_relativeLayoutInCard);
CheckBox _checkBox = new CheckBox(mActivity);
_checkBox.setId(_day.geteCheckBoxID());
_checkBox.setText(R.string.act_SWHours_CB_FreeDay);
_relativeLayoutInCard.addView(_checkBox, _layoutParamsOtherViews);
_layoutParamsOtherViews.addRule(RelativeLayout.ALIGN_PARENT_START);
_checkBox.setLayoutParams(_layoutParamsOtherViews);
_layoutParamsOtherViews.removeRule(RelativeLayout.ALIGN_PARENT_START);
TextView _TVDayLabel = new TextView(mActivity);
_TVDayLabel.setText(_day.geteDisplayName());
_relativeLayoutInCard.addView(_TVDayLabel, _layoutParamsOtherViews);
_layoutParamsOtherViews.addRule(RelativeLayout.END_OF, _day.geteCheckBoxID());
_TVDayLabel.setLayoutParams(_layoutParamsOtherViews);
_layoutParamsOtherViews.removeRule(RelativeLayout.END_OF);
Spinner _spinnerEnd = new Spinner(mActivity);
_spinnerEnd.setId(_day.geteSpinnerEndID());
_relativeLayoutInCard.addView(_spinnerEnd, _layoutParamsOtherViews);
_layoutParamsOtherViews.addRule(RelativeLayout.ALIGN_PARENT_END);
_spinnerEnd.setLayoutParams(_layoutParamsOtherViews);
_layoutParamsOtherViews.removeRule(RelativeLayout.ALIGN_PARENT_END);
Spinner _spinnerStart = new Spinner(mActivity);
_spinnerStart.setId(_day.geteSpinnerStartID());
_relativeLayoutInCard.addView(_spinnerStart, _layoutParamsOtherViews);
_layoutParamsOtherViews.addRule(RelativeLayout.START_OF, _day.geteSpinnerEndID());
_spinnerStart.setLayoutParams(_layoutParamsOtherViews);
_previousDay = _day;
}
}
Apparently, the problem was that I used the same LayoutParams object at all views( even though I removed the rules before assigning it to the next one).
In order for this to work, just other LayoutParams objects for each view and that shall do the work.
/* for Checkbox, Textviews and spinners inside CV */
RelativeLayout.LayoutParams _layoutParamsCB = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT
);
RelativeLayout.LayoutParams _layoutParamsTV = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT
);
RelativeLayout.LayoutParams _layoutParamsSPS = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT
);
RelativeLayout.LayoutParams _layoutParamsSPE = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT
);
...
TextView _TVDayLabel = new TextView(mActivity);
_TVDayLabel.setText(_day.geteDisplayName());
_relativeLayoutInCard.addView(_TVDayLabel, _layoutParamsTV);
_layoutParamsTV.addRule(RelativeLayout.END_OF, _day.geteCheckBoxID());
_TVDayLabel.setLayoutParams(_layoutParamsTV);

How to edit TextView parameters programmatically?

I'm trying to make a Scheduling app, and in doing so have made a Schedule screen with TextViews and Views that represent the time slots that an activity can correspond to.
However I'm having a hard time getting a generated TextView (which will represent the activity on the Schedule) to line up correctly with the View associated with the Activity's start time.
For example in this case I make a TextView with text = "CSI2120", and attempt to line it up with line (which is a View) above the "13:00" TextView here. However I am missing something as the advice from these links as I can't get them to work.
Can I set “android:layout_below” at runtime, programmatically?
Android How to change layout_below to TextView programmatically (See Second Way in the Answer)
The TextView is in the default location on the top-right, not where I want it to be. What should be doing instead of what the links advise?
Here is my full method. timeSlots is an array of R.id.view[####] ints and Schedule is the Activity the method is in:
public void displayDailyActivities(int[] timeSlots){
String[] todaysActivities = {"CSI2120", "01", "14", "2017", "0300", "0400"};
// Make the associated TextView(s)
for(int i=0; i < todaysActivities.length; i=i+6){
int startTime = Integer.valueOf(todaysActivities[i+4]);
int startTimeHour = startTime / 100;
int startTimeMin = startTime % 100;
// Make the TextView and add it to the Schedule
// Code I got from links
TextView newActivity = new TextView(Schedule.this);
RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
LinearLayout.LayoutParams linearParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
// Make the activity, grabbing the corresponding timeslot (View) from the timeSlots array
newActivity.setText(todaysActivities[i]);
// In this case ( timeSlots[startTimeHour + 1] ) returns ( R.id.view0300 )
// which is the View (line) on the Schedule directly above to the "03:00" TextView
relativeParams.addRule(RelativeLayout.BELOW, timeSlots[startTimeHour + 1]);
newActivity.setLayoutParams(relativeParams);
linearParams.setMargins(0, startTimeMin-3, 0, 0);
newActivity.setLayoutParams(linearParams);
// Add to the screen
RelativeLayout schedule = (RelativeLayout) findViewById(R.id.scheduleView);
schedule.addView(newActivity);
// Make sure we're not going out of bounds
if(i + 6 > todaysActivities.length){
i = todaysActivities.length;
}
else{
}
}
}
EDIT: The code that I've found from other similar questions, specifically, that doesn't work for me are the lines:
TextView newActivity = new TextView(Schedule.this);
RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
LinearLayout.LayoutParams linearParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
...
relativeParams.addRule(RelativeLayout.BELOW, timeSlots[startTimeHour + 1]);
newActivity.setLayoutParams(relativeParams);
linearParams.setMargins(0, startTimeMin-3, 0, 0);
newActivity.setLayoutParams(linearParams);
you are overriding the relativeParams with the linearParams. set margins to relativeParms variable iteself and then setLayoutParams to newActivity like below:
relativeParams.addRule(RelativeLayout.BELOW, timeSlots[startTimeHour + 1]);
relativeParams.setMargins(0, startTimeMin-3, 0, 0);
newActivity.setLayoutParams(relativeParams);
// Add to the screen
RelativeLayout schedule = (RelativeLayout) findViewById(R.id.scheduleView);
schedule.addView(newActivity);
This can solve your problem
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.setMargins(10,10,10,10);
TextView textView = (TextView) findViewById(R.id.textView);
textView.setLayoutParams(params);

Java edittext to xml android

I am trying to do a app with multiple EditText and is wondering if there is any easy way to do that.
For instance to add matrix of EditText from your java code to your activity_main.xml or maby do a for loop which adds them at your specified location.
EditText[][] edittext = new EditText[10][10];
gridView = (GridView) findViewById(R.id.gridview);
for (int i=0;i<9;i++){
for (int j=0;j<9;j++){
gridView.addView(edittext[i][j], column X, row Y);
}
}
Here is a working example..
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout root = (LinearLayout) findViewById(R.id.master);
EditText t[][] = new EditText[10][10];
LinearLayout.LayoutParams dim = new LinearLayout.LayoutParams(LinearLayout.LayoutParams
.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
for (int i=0;i<9;i++){
for (int j=0;j<9;j++){
t[i][j]=new EditText(this);
t[i][j].setLayoutParams(dim);
t[i][j].setHint("Hello World , EditText[" + i + "]" + "[" + j + "]");
root.addView(t[i][j]);
}
}
}
There is no easier way to make a "form". Each EditText is a different xml component with different id, with its own attributes.
What you can do is an adapter with listview/recyclerview with EditText the holder.
You can do smth like that:
ArrayList<EditText> editTexts = new ArrayList<>();
LinearLayout ll = (LinearLayout) findViewById(R.id.container);
EditText oneOfEditText;
for (int i = 0; i < 100; i++){
oneOfEditText = new EditText(this);
oneOfEditText.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
));
oneOfEditText.setHint("MyHint");
oneOfEditText.setId(i);
ll.addView(oneOfEditText);
editTexts.add(oneOfEditText);
}
And then you can access these EditTexts like that:
for (EditText editText : editTexts){
Log.d("myLog", editText.getText().toString());
}
But the best practice for such things is to create them statically in xml, and then you can access them either via static ids, or like that:
for (int i =0; i < ll.getChildCount(); i++){
editTexts.add((EditText) ll.getChildAt(i));
}
I think the proper way implement each item is to use an adapter. In your case, you can use SimpleAdapter or create a custom adapter that extends BaseAdapter and set it using setAdapter(ListAdapter).
You can check the documentation for GridView here:
http://developer.android.com/guide/topics/ui/layout/gridview.html

Removing All Views gets rid of OnClickListener

I am adding some table rows to a tableLayout dynamically and adding an onClickListener to each row- but when I removeAllViews, for some reason it gets rid of the listener too....
Here is my code for adding the data:
private void addTickerToTable(String ticker, String last, String chg, String pchg, String time){
rowId++;
int theColor=Color.WHITE;
int rowColor=0;
float theSize=13f;
lp = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT);
row= new TableRow(this);
row.setPadding(0, 5, 0, 5);
if(rowOdd==0){row.setBackgroundColor(Color.parseColor("#343434"));rowColor=Color.parseColor("#343434");}
if(rowOdd==1){row.setBackgroundColor(Color.BLACK);rowOdd=-1;rowColor=Color.BLACK;}
rowOdd++;
row.setLayoutParams(lp);
tv0 = new TextView(this);
tv0.setTextColor(Color.parseColor("#3A54A7"));
tv0.setTextSize(theSize);
tv1 = new TextView(this);
tv1.setTextColor(theColor);
tv1.setTextSize(theSize);
tv2 = new TextView(this);
tv2.setTextSize(theSize);
tv3 = new TextView(this);
tv3.setTextSize(theSize);
tv0.setText(ticker);
tv0.setLayoutParams(params);
row.addView(tv0);
tv1.setText(last);
tv1.setLayoutParams(params);
row.addView(tv1);
tv2.setText(chg);
tv2.setLayoutParams(params);
row.addView(tv2);
tv3.setText(pchg);
tv3.setLayoutParams(params);
row.addView(tv3);
ll.addView(row,rowCount);
row.setId(rowId);
row.setOnClickListener(this);
row.setOnLongClickListener(this);
row.startAnimation(anim2);
rowCount++;
}
Then I have a separate method that simply resets the data-
ll.removeAllViews();
rowCount=0;
rowOdd=0;
rowId=0;
It runs perfect the first time- everything is clickable etc...but as soon as you refresh or run the reset code, all of a sudden the onClickListeners don't work...
Nevermind- looks like I wasn't resetting my clicked variable- Oops!

Categories

Resources