Android LinearLayout.removeViewAt (int i) throws exceptions? - android

I have the following code:
for (int i = 0; i < linearLayout.getChildCount() - 5; i++) //IN this code, please assume the child count is 10;
{
View v = linearLayout.getChildAt(i);
Standard.Loge("REMOVING: " + i + " " + (v == null));
linearLayout.removeViewAt(i);
}
This outputs the following:
REMOVING: 0 false
REMOVING: 1 false
REMOVING: 2 true
the app crashes, even though the views at index 2 - 4 have not been removed, throwing this error:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.unFocus(android.view.View)' on a null object reference
at android.view.ViewGroup.removeViewInternal(ViewGroup.java:4937)
at android.view.ViewGroup.removeViewAt(ViewGroup.java:4899)
at (((The last line in the for loop above)))
It would appear that the views are null, even though getChildCount registers that the views exist, and my guess is that this is causing removeChildAt to crash. I am adding the views dynamically in java so I am not able to use findViewByID. I am really at a loss here. How can I fix this crash so I can remove these views?

I think you actually just want to remove element 0. When you remove one of the elements, they all shift back. So element 1 becomes 0 and 2 becomes 1, etc.
This code should work:
for (int i = 0; i < linearLayout.getChildCount() - 5; i++) //IN this code, please assume the child count is 10;
{
View v = linearLayout.getChildAt(0);
Standard.Loge("REMOVING: " + 0 + " " + (v == null));
linearLayout.removeViewAt(0);
}

Related

Deleting child view from first position and adding it to last position

I have a custom view called TinderStackLayout.
At a certain part of the code I am deleting a child view of it and re-adding it back at the last position possible -
private void handleViewAfterAnimation(View view, boolean shouldSkipView) {
Log.d("card view - ", "inside handleViewAfterAnimation");
isCardAnimating = false;
TinderStackLayout tinderStackLayout = (TinderStackLayout) view.getParent();
if (tinderStackLayout == null)
return;
tinderStackLayout.removeView(view);
if (shouldSkipView)
tinderStackLayout.addCard((TinderCardView) view, tinderStackLayout.getChildCount() - 1);
//this part is for debugging purpose
for (int i = 0; i < tinderStackLayout.getChildCount(); i++) {
View childAt = tinderStackLayout.getChildAt(i);
if (childAt instanceof TinderCardView)
Log.d("card view - ", "child cards after deletion - " + (((TinderCardView) childAt).usernameTextView.getText()));
}
}
here is my addCard() method -
public void addCard(TinderCardView tinderCardView, int addToPosition) {
View topCard = getChildAt(0);
if (topCard != null && topCard.equals(tinderCardView)) {
return;
}
topCardOnStack = tinderCardView;
ViewGroup.LayoutParams layoutParams;
layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
addView(tinderCardView, addToPosition, layoutParams);
// tinderCardView.animate()
// .x(0)
// .setInterpolator(new AnticipateOvershootInterpolator());
}
What I don't understand is what I get in the UI -
I have 3 cards.
I press the button, one card is being animated away, the second one is being shown. I press the button again, the second one animates away. I press the last one and the button does not work anymore. What I want to achieve is the first card appearing now behind the last one.
Here is what I get when logging the values out -
seems correct, it was before clicking 3 2 1 and now 2 3 1. The next one should be 1 2 3, but this is what I get for the next one -
goes back to 3 2 1 instead of 1 2 3. I can't figure out why. ?
Edit:
found the reason why this is happening, I am giving a view which should always be the top card on the stack but I am actually not giving the top card because I am always adding a new card. Here is the method -
public void handleButtonPressed(int buttonTag) {
Log.d("card view - ", "inside handleButtonPressed");
TinderStackLayout tinderStackLayout = ((TinderStackLayout) this.getParent());
TinderCardView topCard = (TinderCardView) tinderStackLayout.getChildAt(tinderStackLayout.getChildCount() - 1);
if (isCardAnimating) {
return;
}
switch (buttonTag) {
case DELETE_BUTTON_PRESSED:
isCardAnimating = true;
deleteCard(topCard);
break;
case PASS_BUTTON_PRESSED:
Log.d("card view - ", "inside pass button pressed");
isCardAnimating = true;
passCard(topCard);
Log.d("card view - ", "top card Value before pass - " + topCard.displayNameTextView.getText());
Log.d("card view - ", "child count - " + tinderStackLayout.getChildCount());
for (int i = 0; i < tinderStackLayout.getChildCount(); i++) {
View childAt = tinderStackLayout.getChildAt(i);
if (childAt instanceof TinderCardView)
Log.d("card view - ", "child cards before deletion - " + (((TinderCardView) childAt).usernameTextView.getText()));
}
break;
case APPROVE_BUTTON_PRESSED:
showLawyerContactDetailsFragment(topCard);
break;
}
}
I am trying to do TinderCardView topCard = (TinderCardView) tinderStackLayout.getChildAt(tinderStackLayout.getChildCount() - 1) in order to get the top card in my stack, which would be correct if I delete the cards and not re-add them to my stack but that is not the case when re-adding them. What should be the solution for always getting the top card when I am adding new views all the time?
If you want to shuffle cards, then you don't need to delete and re-add them. You simply need a data structure, which will do it for you. For your use case you can use Circular Array.
private CircularArray cardArray; //declaration
Now when you are adding your views, add it to your card array also.
cardArray.addLast(tinderCardView);
addView(tinderCardView); // add to your layout.
Then use this code to check.
int shuffleCount = 3;
for (int i = 1; i <= shuffleCount; i++)
shuffleTopCard(i);
Finally shuffleTopCard() method.
private void shuffleTopCard(int shuffleID) {
Log.d(TAG, "shuffleTopCard: cards before shuffle");
for (int i = 0; i < cardCount; i++)
Log.d(TAG, "shuffleTopCard: " + ((TinderCardView) cardArray.get(i)).getTag());
TinderCardView cardView = (TinderCardView) cardArray.popLast();
Log.e(TAG, "shuffleTopCard: top cardID = " + cardView.getTag());
cardArray.addFirst(cardView);
Log.d(TAG, "shuffleTopCard: cards after shuffling " + shuffleID + " time");
for (int i = 0; i < cardArray.size(); i++)
Log.d(TAG, "shuffleTopCard: " + ((TinderCardView) cardArray.get(i)).getTag());
Log.e(TAG, "shuffleTopCard: after shuffle top card = " + ((TinderCardView) cardArray.getLast()).getTag());
}
Use of CircularArray will free you from head-ache of maintaining card position manually and also separates your CustomViewGroup and card shuffling logic thereby resulting in loosely-coupled code.

Keep getting "IndexOutOfBoundsException: Index: 0, Size: 0" when trying to check array entry

I am offering products in the menuItemArrayList and as the user places products of their choice in the shopping cart, they will be added to the selectionItemArrayList. Here is my code that checks to see if the product already exists in the shopping cart. If so then only the quantity gets updated.
I have twiddling around with the code but I keep getting this error
IndexOutOfBoundsException: Index: 0, Size: 0
The code is just an extract from an onClickListener from the recyclerview's onBindHolder:
int position = getAdapterPosition();
for (int j = 0; j <= selectionItemArrayList.size(); j++) {
if (menuItemArrayList.get(position).getMenuItemName().equals(selectionItemArrayList.get(j).selectionName)) { // Loop through selection array to see if item exists in array
selectionItemArrayList.get(j).selectionQuantity += 1; // if it does exist then only update the quantity by 1
} else {
// Get the item name, price and add 1 to the quantity
String menuItemName = menuItemArrayList.get(position).getMenuItemName();
String menuItemPrice = menuItemArrayList.get(position).getMenuItemPrice();
SelectionItem selectionItems = new SelectionItem(menuItemName, menuItemPrice, 1);
selectionItemArrayList.add(selectionItems);
}
}
Any idea what I am doing wrong? The exception is thrown on the line where I compare the product name in the main array with the one in the cart array.
This is your loop:
for (int j = 0; j <= selectionItemArrayList.size(); j++)
When iterating over a list, you almost always want to use <, and not <=. This is because lists indices start from 0. So a list of size 2 has items at 0 and 1.
When you use <= on a list with zero elements, it will still try to access the element at index 0 (because 0 is <= 0). But your list is empty; it has no element at index 0. So you crash.
Try this instead:
for (int j = 0; j < selectionItemArrayList.size(); j++)

unable to retrieve values from two different arraylist

i am having two different arraylist of diffrent size,my problem is that i have to retrieve values from both the list and show that on to a textview,when i am using two loops it is first completing the inner loop and than executing outer loop and the vales are getting printed two times and if using break to break the inner loop it is completely ignoring inner loop after 1st loop.
ArrayList<LocationDto>location = new ArrayList<>();
education<EducationDto> = new ArrayList<>();
if (education.size() != 0) {
for (int j = 0; j < education.size(); j++) {
for (int k = 0; k < location.size(); k++) {
if (!education.get(j).getSpecializationTitle().equalsIgnoreCase("") && !location.get(k).getLocationName().equalsIgnoreCase("")) {
tvEducation.append(education.get(j).getEducationTitle() + "(" + education.get(j).getSpecializationTitle() + ")" + " Located at " + location.get(k).getLocationName());
} else if (education.get(j).getSpecializationTitle().equalsIgnoreCase("") && !location.get(k).getLocationName().equalsIgnoreCase("")) {
tvEducation.append(education.get(j).getEducationTitle() + " Located at " + location.get(j).getLocationName());
} else if (!education.get(j).getSpecializationTitle().equalsIgnoreCase("") && location.get(k).getLocationName().equalsIgnoreCase("")) {
tvEducation.append(education.get(j).getEducationTitle() + "(" + education.get(j).getSpecializationTitle() + ")");
} else {
tvEducation.append(education.get(j).getEducationTitle());
}
if (j != education.size() - 1) {
tvEducation.append(" , ");
}
break;
}
}
} else {
tvEducation.setText("Not Specified");
tvEducation.setTextColor(getResources().getColor(R.color.color_three));
}
what should i do now?
The break statement terminates a loop regardless of whether it has completed or not, so your problem is that you've put a break directly inside your inner for loop without some sort of condition. Therefore the first time the loop runs it will reach the break which is why it's terminating on the first iteration!
You probably mean to put the break inside the last if statement?

FlexboxLayout count lines

I need to add views programmatically to FlexboxLayout and for each view added check if it created a new row or not.
How can I get Row count?
Tried:
for (int i = 0; i < 100; i++) {
flexboxlayout.add(createView(this.getContext(), i));
//log
Log.e("position: " + i + " ; row count -> " + flexboxlayout.getFlexLines().size());
}
getFlexLines method does not always return the expected Line count.

ArrayList Skip Data when Show?

UPDATE SOLVED :
i don't know what happened, my Array is work normally when i add this code :
EditText editText= new EditText(this);
editText.setId(456 + i);
mSurveyView.addView(editText);
I don't know how to title this question. Because i am confused, but i will explain my problem with code
So, I have ArrayList data, ex : 1 2 3 4 5 , but when i try to show/debug just get 3 data like 1 3 5. I think, the ArrayList skip my data?
This is my code :
if (dataSurvey.listFieldSurvey.size() > 0) {
for (int i = 0; i < dataSurvey.listFieldSurvey.size(); i++) {
FieldSurvey xx = dataSurvey.listFieldSurvey.get(i);
String type = xx.metaSurvey.name;
Log.d("Tag", "type text " + dataSurvey.listFieldSurvey.size());
labelCaption = new TextView(getActivity());
labelCaption.setId(456 + i);
labelCaption.setText(xx.name + ". " + xx.caption);
labelCaption.setTypeface(Typeface.DEFAULT_BOLD);
mSurveyView.addView(labelCaption);
}
}
I tried Log.d "Tag", i have data size 5, but just show 3 data when i tried to show

Categories

Resources