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.
Related
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.
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?
I am populating new data in my RecyclerView adapter all at once, so there are no insert or remove one item actions.
So simply, i have an old list and when some Event occurs i get the new list and i can assign the new list to the old.
Problems are i cannot make properly the animation for each item in the old list
when item has new position in the new list (should notifyItemMoved from old position to new)
when there is a new item in the new list (should notifyItemInserted with that position in the new list)
when the old item is not present in the new list (should notifyItemRemoved with that position)
Here is something i have now, which i thought will work for first case - item move to new position:
if(currentAdapterData!= null){
for(int i = 0; i < currentAdapterData.size(); i++){
for(int j = 0; j < newData.size(); j++){
if(currentAdapterData.get(i).getSomeIdentifier().equals(newData.get(j).getSomeIdentifier())){
Log.v("same item", "currentAdapterData index :" + i + " ," + currentAdapterData.get(i).getSomeIdentifier() + " == newData index: " + j + " ," + newData.get(j).getSomeIdentifier());
if(i != j){
notifyItemMoved(i, j);
}
}
}
}
}
currentAdapterData = newData;
However it does not work as expected, and there is difference between logs(which are correct) and the list appearing on the phone(with wrong items positions, some duplicates, buggy etc.)
So how can i make it work? With notifyItemMoved, notifyItemInserted and notifyItemRemoved?
I don't want to just use NofifyDataSetChanged, because it refresh the entire list instead of just updating the items with animations that have changed.
It looks like that your new data is also a form of list, not a single item. I think this could be a good candidate for using DiffUtil in the support library.
Here is also a nice tutorial for it.
It will allow you to calculate the difference in the new data and only update needed fields. It will also offload the work asynchronously.
You just need to implement a DiffUtil.Callback to indicate if your items are the same or the contents are the same.
You update your recyclerView like that:
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);
diffResult.dispatchUpdatesTo(yourAdapter);
Simply use DiffUtil like
final MyDiffCallback diffCallback = new MyDiffCallback(prevList, newList);
final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);
Create a Callback by extending MyDiffCallback and override methods and do as needed.
public class MyDiffCallback extends DiffUtil.Callback
// override methods
Well for this ,I feel this would be the easiest.Just follow it ->
Replace this
if(currentAdapterData!= null){
for(int i = 0; i < currentAdapterData.size(); i++){
for(int j = 0; j < newData.size(); j++){
if(currentAdapterData.get(i).getSomeIdentifier().equals(newData.get(j).getSomeIdentifier())){
Log.v("same item", "currentAdapterData index :" + i + " ," + currentAdapterData.get(i).getSomeIdentifier() + " == newData index: " + j + " ," + newData.get(j).getSomeIdentifier());
if(i != j){
notifyItemMoved(i, j);
}
}
}
}
}
currentAdapterData = newData;
with
if(currentAdapterData!= null){
for(int i = 0; i < currentAdapterData.size(); i++){
for(int j = 0; j < newData.size(); j++){
if(currentAdapterData.get(i).getSomeIdentifier().equals(newData.get(j).getSomeIdentifier())){
Log.v("same item", "currentAdapterData index :" + i + " ," + currentAdapterData.get(i).getSomeIdentifier() + " == newData index: " + j + " ," + newData.get(j).getSomeIdentifier());
if(i != j){
notifyDataSetChanged();
new CountDownTimer(250, 250) {
#Override
public void onTick(long millisUntilFinished) {
Log.d("millisUntilFinished", "" + millisUntilFinished);
}
#Override
public void onFinish() {
notifyItemMoved(i, j);
}
}.start();
}
}
}
}
}
this will update the values and after 250 millisecond(1/4th a second),the value with be moved with animation.
I have a layout that is built dynamically from a database. There are several sections, One of the pieces is a series of radio groups with custom text on each radio button that is read from the database.
My code is properly inflating the layout, adding the correct number of radio buttons and adding the correct text to them.
What I can't figure out is how to get the value of the checked radio button when it is a child of a table row. I am not using an on item selected because I need to wait until the user is sure all the answers are filled in before getting the results. So I have a separate button with an onClick that is going to read the data and store it in the database.
Here is the area in my main XML file
Here is the individual row XML
<RadioGroup
android:id="#+id/radioGroup1"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</RadioGroup>
</TableRow>
Here is where I am trying to read the values of the selected radio button
table = (TableLayout) findViewById(R.id.TableLayout03);
for( int ii = 0; ii < nRecs3; ii++ ){
TableRow row1= (TableRow)table.getChildAt(ii);
Log.i("radio button " , " index of row is " + String.valueOf(row1));
View child = table.getChildAt(ii);
int idx = row1.indexOfChild(child);
Log.i("radio button " , " index of child is " + String.valueOf(idx));
RadioGroup radio = (RadioGroup)child;
Log.i("radio button " , " checked button is " + String.valueOf(radio.getCheckedRadioButtonId()));
}
but it's crashing before it gets to the first log statement. I've tried all sorts of variations on getting the value of the child of the child row but nothing is working.
I got it to work. For future reference in case anyone else has this issue you have to have the radiogroup be the child and then work within that to get the buttons.
Here is how I described the table in my main XML file
<ScrollView
android:id="#+id/scroll03"
android:layout_width="fill_parent"
android:layout_height="175dp">
<TableLayout
android:id="#+id/TableLayout03"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</TableLayout>
</ScrollView>
Then I have this as the XML file for the row entry:
<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="#+id/radioGroup1_lbl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:typeface="monospace" />
<RadioGroup
android:id="#+id/radioGroup1"
android:layout_width="wrap_content"
android:layout_height="175dp">
</RadioGroup>
</TableRow>
Here is the subset of code that creates the table rows and radio groups from the database
// Set up the user traits
cmd = String.format("select evaluation_trait_table.trait_name, evaluation_trait_table.id_traitid, " +
"custom_evaluation_name_table.custom_eval_number " +
"from evaluation_trait_table inner join last_eval_table on " +
" evaluation_trait_table.id_traitid = last_eval_table.id_traitid" +
" inner join custom_evaluation_name_table on evaluation_trait_table.id_traitid = " +
" custom_evaluation_name_table.id_traitid where evaluation_trait_table.trait_type = 3 ") ;
crsr = dbh.exec( cmd );
cursor = ( Cursor ) crsr;
startManagingCursor(cursor);
nRecs3 = cursor.getCount(); // number of user defined traits to use
dbh.moveToFirstRecord();
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()){
user_evaluation_traits.add(cursor.getString(0));
user_trait_numbers.add(cursor.getInt(1));
user_trait_number_items.add(cursor.getInt(2));
}
inflater = getLayoutInflater();
TableLayout table = (TableLayout) findViewById(R.id.TableLayout03);
for( int ii = 0; ii < nRecs3; ii++ ){
TableRow row = (TableRow)inflater.inflate(R.layout.eval_custom_item, table, false);
tempLabel = user_evaluation_traits.get(ii);
// Set the text for the radiogroup label
((TextView)row.findViewById(R.id.radioGroup1_lbl)).setText(tempLabel);
// Get the text for the buttons
tempText = String.valueOf(user_trait_numbers.get(ii));
cmd = String.format("select custom_evaluation_traits_table.custom_evaluation_item " +
" from custom_evaluation_traits_table " +
" where custom_evaluation_traits_table.id_traitid = '%s' "+
" order by custom_evaluation_traits_table.custom_evaluation_order ASC ", tempText);
crsr = dbh.exec( cmd );
cursor = ( Cursor ) crsr;
startManagingCursor(cursor);
nRecs4 = cursor.getCount();
dbh.moveToFirstRecord();
ArrayList buttons = new ArrayList();
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()){
buttons.add (cursor.getString(0));
}
radioBtnText = (String[]) buttons.toArray(new String [buttons.size()]);
// Build the radio buttons here
radioGroup = ((RadioGroup) row.findViewById(R.id.radioGroup1));
addRadioButtons(user_trait_number_items.get(ii), radioBtnText);
table.addView(row);
}
Here is the method that creates the radiogroup
private void addRadioButtons(int numButtons, String[] radioBtnText) {
int i;
for(i = 0; i < numButtons; i++){
//instantiate...
RadioButton radioBtn = new RadioButton(this);
//set the values that you would otherwise hardcode in the xml...
radioBtn.setLayoutParams
(new LayoutParams
(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
//label the button...
radioBtn.setText(radioBtnText[i]);
Log.i("addradiobuttons", radioBtnText[i]);
radioBtn.setId(i);
//add it to the group.
radioGroup.addView(radioBtn, i);
}
}
And finally the subset of code where I actually read the radio buttons and get ready to update my database
table = (TableLayout) findViewById(R.id.TableLayout03);
if (nRecs3 != 0) {
for( int ii = 0; ii < nRecs3; ii++ ){
TableRow row1= (TableRow)table.getChildAt(ii);
tempTrait = user_trait_numbers.get (ii);
RadioGroup rg=(RadioGroup)findViewById(R.id.radioGroup1);
try {
tempRadioBtn = rg.getCheckedRadioButtonId();
cmd = String.format("select custom_evaluation_traits_table.id_custom_traitid " +
" from custom_evaluation_traits_table " +
" where custom_evaluation_traits_table.id_traitid = %s "+
" and custom_evaluation_traits_table.custom_evaluation_order = %s ", tempTrait, tempRadioBtn+1);
crsr = dbh.exec( cmd );
cursor = ( Cursor ) crsr;
startManagingCursor(cursor);
dbh.moveToFirstRecord();
tempRadioBtn = cursor.getInt(0);
} catch (Exception ex) {
tempRadioBtn = 0;
}
user_scores.add(tempRadioBtn);
}
for( int ii = nRecs3; ii < 5; ii++ ){
user_scores.add(0);
}
}else {
for( int ii = 0; ii < 5; ii++ ){
user_scores.add(0);
}
}
// Fill the user score variables from the user_scores array
trait16_data = user_scores.get(0);
trait17_data = user_scores.get(1);
trait18_data = user_scores.get(2);
trait19_data = user_scores.get(3);
trait20_data = user_scores.get(4);
From there I build my query to do the actual update for this sheep record in the sheep_evaluation_table.
maybe its too late but you can just add setoncheckedlistener. this log id and state. after this you use setter and getter.
hope this will help
private void inflateRadioButton() {
ArrayList arrayList = json_helper_class.getChoice_group_multiple();
for (int i = 0; i < arrayList.size(); i++) {
LinearLayout row = new LinearLayout(Diagnose_Test_Activity.this);
row.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
final RadioButton radioButton = new RadioButton(Diagnose_Test_Activity.this);
String a = String.valueOf(arrayList.get(i));
radioButton.setText(a);
radioButton.setId(i);
radioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
String a = String.valueOf(radioButton.getId());
Log.d(TAG, "onCheckedChanged: "+a+b);
//setter here
}
});
row.addView(radioButton);
ll_group_multiple_container.addView(row);
}
}
hi i have problem in displaying a value into my TextView..
For example i will input 1,2,3,4 then i like to display the output in this manner in my TextView..How can i do that? please help me, thank you in advance
1 appeared 1 times
2 appeared 1 times
3 appeared 1 times
4 appeared 1 times
here's my code:
String []values = ( sum.getText().toString().split(","));
double[] convertedValues = new double[values.length];
Arrays.sort(convertedValues);
int i=0;
int c=0;
while(i<values.length-1){
while(values[i]==values[i+1]){
c++;
i++;
}
table.setText(values[i] + " appeared " + c + " times");
c=1;
i++;
if(i==values.length-1)
table.setText(values[i] + " appeared " + c + " times");
Make your textView to support multipleLines and after that create in code a StringBuffer and append to it the results, something like
resultString.append(result).append(" appeared").append(c).append(" times\n");
after that you set text for textView like:
textView.setText(resultString.toString());
Here is the idea :
// this is test string, you can read it from your textView
String []values = ( "2, 1, 3, 5, 1, 2".toString().split(","));
int [] intValues = new int[values.length];
// convert string values to int
for (int i = 0; i < values.length; ++i) {
intValues[i] = Integer.parseInt(values[i].trim());
}
// sort integer array
Arrays.sort(intValues);
StringBuilder output = new StringBuilder();
// iterate and count occurrences
int count = 1;
// you don't need internal loop, one loop is enough
for (int i = 0; i < intValues.length; ++i) {
if (i == intValues.length - 1 || intValues[i] != intValues[i + 1]) {
// we found end of "equal" sequence
output.append(intValues[i] + " appeared " + count + " times\n");
count = 1; // reset count
} else {
count++; // continue till we count all equal values
}
}
System.out.println(output.toString()); // prints what you extected
table.setText(output.toString()); // display output