ListView inside RecyclerView - android

I am using recyclerViewAdapter to fill recycler view.
Inside each recyclerItem must be list with items, and I decided to make it listView.
so inside onBindViewHolder of recyclerView i create new cursor, make new query (with help of contentResolver) and than i need to fill my listView with this data.
here is some my code:
Cursor.moveToFirst();
int size = Cursor.getCount();
if (size > 0){
for (int i = 0; i<size; i++){
Cursor.moveToPosition(i);
setCurrentItem();
}
}
private void setCurrentItem(){
View View = LayoutInflater.from(mContext).inflate(R.layout.list_item_test, null);
mLogo = (ImageView)cardView.findViewById(R.id.iv_Item_logo);
mName = (TextView)cardView.findViewById(R.id.tv_cardItem_Name);
mNumber = (TextView)cardView.findViewById(R.id.tv_cardItem_Number);
mBlocked = (TextView)cardView.findViewById(R.id.tv_Item_blocked);
mDate = (TextView)cardView.findViewById(R.id.tv_Item_Date);
String Name = Cursor.getString(AccountsFragment.NAME);
String Numb = Cursor.getString(AccountsFragment.NUMBER);
Numb = USB_Converter.Numbers(Numb);
String Date = Cursor.getString(AccountsFragment.DATE);
Date = USB_Converter.friendlyDate(Date);
int Status = Cursor.getInt(AccountsFragment.STATUS);
if (Status == UserAccountsEntry.STATUS_ID_ACTIVE){
mBlocked.setVisibility(View.VISIBLE);
} else {
mBlocked.setVisibility(View.GONE);
}
mName.setText(Name);
mNumber.setText(Numb);
mDate.setText(Date);
mHolder.mListView.addFooterView(cardView);
}
this works without any errors, but it's does not show listView...
any idea how to fix this?
EDIT
listView.xml:
<ListView
android:id="#+id/lv_accountList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:dividerHeight="1dp"
/>

You don't show the content of list_item_test.xml, but you'll probably need to give the inner ListView an absolute height in dp (or give it's parent an absolute height and then use match_parent on the ListView).
You can't use wrap_content for a ListView (it will shrink to 0 height), and you can't use match_parent if the parent doesn't have an independently derived or explicitly declared height.

Related

recyclerview child count is smaller than arrayList size in activity class

IN my Activity class i get child of Recyclerview like:
final int itemsCount = recly_list_lab.getChildCount();
but it gave me 7 item count but i have 10 item then how to get 10 items in Main Activity
this my code for getting child item for recyclerView:
final int itemsCount = recly_list_lab.getChildCount();
Log.e("itemsCount::",itemsCount+"");
if (itemsCount != 0) {
try {
for (int i = 0; i <itemsCount; i++) {
final View viewtestcategoryname = recly_list_lab.getChildAt(i);
AutoCompleteTextView autoctv_testcategory = (AutoCompleteTextView) viewtestcategoryname.findViewById(R.id.autoctv_testcategory);
String TestCategoryName = autoctv_testcategory.getText().toString();
Log.e("TestCategoryname:",TestCategoryName);
AutofitRecyclerView grid_labreferal_checkboxes_test = (AutofitRecyclerView) viewtestcategoryname.findViewById(R.id.grid_labreferal_checkboxes_test);
final int itemcheckTestCount = grid_labreferal_checkboxes_test.getChildCount();
Log.e("itemcheckTestCount:",itemcheckTestCount+"");
RecyclerView recly_testsubcategory = (RecyclerView) viewtestcategoryname.findViewById(R.id.recly_testsubcategory);
final int itemSubCategoryName = recly_testsubcategory.getChildCount();
Log.e("itemSubCategoryName:",itemSubCategoryName+"");
for (int test_check = 0; test_check < itemcheckTestCount; test_check++) {
final View viewTestCheck = grid_labreferal_checkboxes_test.getChildAt(test_check);
CheckBox grid_labreferal_checkbox = (CheckBox) viewTestCheck.findViewById(R.id.grid_labreferal_checkbox);
TextView txt_item_id = (TextView) viewTestCheck.findViewById(R.id.txt_item_id);
if (grid_labreferal_checkbox.isChecked()) {
Log.e("%sgrid_lcheckbox", grid_labreferal_checkbox.getText().toString());
if (txt_item_id != null && txt_item_id.getText().toString().trim().length() != 0) {
}
}
}
for (int subcatname = 0; subcatname< itemSubCategoryName; subcatname++){
final View SubCategory = recly_testsubcategory.getChildAt(subcatname);
AutoCompleteTextView autoctv_testsubcategory = (AutoCompleteTextView) SubCategory.findViewById(R.id.autoctv_testsubcategory);
Log.e("subcategoryname::",autoctv_testsubcategory.getText().toString());
AutofitRecyclerView grid_labreferal_checkboxes_subtest= (AutofitRecyclerView) SubCategory.findViewById(R.id.grid_labreferal_checkboxes_subtest);
final int itemcheckSubtestCount = grid_labreferal_checkboxes_subtest.getChildCount();
Log.e("itemcheckTestCount:",itemcheckSubtestCount+"");
for (int test_check = 0; test_check < itemcheckSubtestCount; test_check++) {
// jsonObjectMulti = new JSONObject();
final View viewTestCheck = grid_labreferal_checkboxes_subtest.getChildAt(test_check);
CheckBox grid_labreferal_checkbox = (CheckBox) viewTestCheck.findViewById(R.id.grid_labreferal_checkbox);
TextView txt_item_id = (TextView) viewTestCheck.findViewById(R.id.txt_item_id);
if (grid_labreferal_checkbox.isChecked()) {
Log.e("%sgrid_subtestcheckbox", grid_labreferal_checkbox.getText().toString());
if (txt_item_id != null && txt_item_id.getText().toString().trim().length() != 0) {
//testUpload.put(txt_item_id.getText().toString().trim(), grid_labreferal_checkbox.getText().toString().trim());
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
views inside the recyler view may be less than the total number of item inside the view as views will get recycled and reused to display multiple items.
You can use adapter.getItemCount() method to know how many view item will be displayed inside recyler view.
Not all adapter items are attached to the parent. The getChildCount() method returns the number of views displayed. If you want to get the item count of the adapter, you have to query the adapter for it.
final int itemsCount = recly_list_lab.getAdapter().getItemCount();
But considering your code, you're just miss-using the RecyclerView. You're not supposed to access child views of the recycler directly. Everything you need to do with it should go through the adapter and the view holders!
RecyclerView doesn't hold views for all list items in memory, it only has for example - 7 in your case. When you scroll, it reuses those 7 views for displaying different items. The purpose of this is improving the rendering performance.

Getting values of EditTexts from multiple Layouts in Android not working?

Not asked a question in a while so it's been long overdue!
I am creating an app where job items can be created onClick, with each new row containing a Description(EditText), a Price(EditText) and a button to delete the current row, but I am having trouble when getting the values from the EditText fields when there is more than one row - it just returns the values of the newest row.
Aside from the 'Job List Container', the views are created dynamically so pardon the lack of XML, but the structure of what I am trying to achieve is as follows, where clicking the Add button adds a row (this can be multiple rows) and clicking the submit button takes all of the Description and Price values and processes them (adds the prices and adds the job to the DB):
...and this is the code I've written for it called from the addNewJobRow onClick listener (all together for simplicity):
private void addJobItem() {
//Create a new row container
final LinearLayout jobRowContainer = new LinearLayout(this);
//Create a new EditText for the Description
final EditText description = new EditText(this);
description.setHint("Description...");
description.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
1.0f
));
//Create an EditText for the Price
final EditText price = new EditText(this);
price.setHint("00.00");
//Create a new button to delete the row
Button delete = new Button(this);
delete.setBackgroundColor(Color.RED);
delete.setText("X");
//Add Description, Price and Delete to the row container
jobRowContainer.addView(description);
jobRowContainer.addView(price);
jobRowContainer.addView(delete);
//Add the Row Container to the Jobs List Container
ll_jobListContainer.addView(jobRowContainer);
//Get the values of the Description and Price, for each row
btn_JobSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for (int i = 0; i < ll_jobListContainer.getChildCount(); i++) {
for(int j = 0; j < jobRowContainer.getChildCount(); j++) {
if (jobRowContainer.getChildAt(i) instanceof EditText){
String descriptionString = description.getText().toString();
String priceString = price.getText().toString();
System.out.println("z! " + descriptionString + " # " + priceString);
}
}
}
}
});
}
I have tried a couple of iterations of this with and without the nested FOR loops and with and without the use of instanceof, but all it does is print out the newest row.
So, if I have multiple job rows, how can I get all of the values as required?
Thanks for your time and all that nice stuff xxx
The basic problem is that you're using only the last instance of description and price instead of each rows instance. (This may be what Dmitry is saying as well). To fix it, you need to get the input for each row. Here's one way.
Set an ID for description & price. (You can't just use '1' or '2', it needs to be a resource type ID so it is guaranteed to be unique). I made a dummy layout file of a row & assigned IDs in that to the 2 EditTexts. There may be a better way to do it. So anyway, add these 2 lines in your declarations
descripton.setId(R.id.description); and price.setId(R.id.price);
Now this is your onClick()
public void onClick(View v) {
for (int i = 0; i < ll_jobListContainer.getChildCount(); i++) {
LinearLayout currentRow = (LinearLayout)ll_jobListContainer.getChildAt(i);
EditText editText = (EditText)currentRow.findViewById(R.id.description);
String descriptionString = editText.getText().toString();
editText = (EditText)currentRow.findViewById(R.id.price);
String priceString = editText.getText().toString();
Log.d(TAG, "z! " + descriptionString + " # " + priceString);
}
}
EDIT: I didn't want to change this answer since it had already been accepted so I've put a more concise solution in another answer.
Of cause, your last setOnClickListener takes strings
String descriptionString = description.getText().toString();
String priceString = price.getText().toString();
Where description and price - is fields in the function (last edittexts).
The good way to do that is to use RecyclerView/ListView, in "onTextChangeListner" of ViewHolder save new text to model of this object and print all text from your models, not directly from views.
I normally try to answer only question that was asked rather than change code that's not necessary. However, in this case, since I had created a dummy layout just to get Resource IDs, I wonder if that layout file could be put to use. I had started to change my answer but original one was accepted before I could make the changes. I've put a different version of the solution here. I didn't want to modify an answer that had already been accepted.
private void addJobItem() {
//Create a new row container
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout jobRowContainer = (LinearLayout)inflater.inflate(R.layout.row_layout, null);
//Add the Row Container to the Jobs List Container
ll_jobListContainer.addView(jobRowContainer);
//Get the values of the Description and Price, for each row
btn_JobSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for (int i = 0; i < ll_jobListContainer.getChildCount(); i++) {
LinearLayout currentRow = (LinearLayout)ll_jobListContainer.getChildAt(i);
EditText editText = (EditText)currentRow.findViewById(R.id.description);
String descriptionString = editText.getText().toString();
editText = (EditText)currentRow.findViewById(R.id.price);
String priceString = editText.getText().toString();
Log.d(TAG, "z! " + descriptionString + " # " + priceString);
}
}
});
}
row_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/single_row">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Description..."
android:id="#+id/description"
/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="00.00"
android:id="#+id/price"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/holo_red_dark"
android:text="X"
android:id="#+id/clear_button"
/>
</LinearLayout>

Filter TextViews based on ID

I am trying to verify TextView of an app which shows the price of the products listed when a category is searched.
I am using Robotium for automation.
The hierarchy when i get the current view (solo.getCurrentViews(ListView.class)) is something like:
ListView
--> (0)FrameLayout
--> (1)RelativeLayout
--> (0)ImageView
--> (1)RelativeLayout
-->(0)ImageView
-->(1)TextView //id - name
-->(2)TextView //id - price
-->(3)TextView //id - other
--> (2)RelativeLayout
--> (0)ImageView
--> (1)RelativeLayout
-->(0)ImageView
-->(1)TextView //id - name
-->(2)TextView //id - price
-->(3)TextView //id - other
--> (3)RelativeLayout
--> (0)ImageView
--> (1)RelativeLayout
-->(0)ImageView
-->(1)TextView //id - name
-->(2)TextView //id - price
-->(3)TextView //id - other
--> (4)RelativeLayout
--> (0)ImageView
--> (1)RelativeLayout
-->(0)ImageView
-->(1)TextView //id - name
-->(2)TextView //id - price
-->(3)TextView //id - other
--> (5)RelativeLayout
--> (0)ImageView
--> (1)RelativeLayout
-->(0)ImageView
-->(1)TextView //id - name
-->(2)TextView //id - price
-->(3)TextView //id - other
I could figure out two ways of getting the price:
Traverse through children of list view and get to the price via index. Like below code
int index = 1;
ListView view = null;
List<ListView> productList = solo.getCurrentViews(ListView.class);
view = productList.get(0);
for (int i = 1; i < view.getChildCount(); i++) {
RelativeLayout relativeLayoutDetails = (RelativeLayout) view.getChildAt(index++); // get the first RelativeLayout
RelativeLayout productDetails = (RelativeLayout) relativeLayoutDetails.getChildAt(2); //get the inner child RelativeLayout
TextView productName = (TextView) productDetails.getChildAt(0);
System.out.println("********" + productDetails.getChildCount());
TextView price = (TextView) productDetails.getChildAt(2);
System.out.println(productName.getText().toString() + "---"+ price.getText().toString());
}
The problem with this code is TextView price = (TextView) hotelDetails.getChildAt(2); doesn't give me price but gives me other TextView (Don't know why). Also this works only for current views. I am not able to scroll down the complete list and get details for each and every product.
Second is, getting all the TextViews for current views and filter them based on the price id. Something like below:
ListView l = (ListView) solo.getView(android.R.id.list);
int viewShown = l.getChildCount();
int total = l.getCount();
int i;
int index=1;
if (hotelsShown != 0) {
for (i = 0; i < total / viewShown; i++) {
List<TextView> textViews = solo.getCurrentViews(TextView.class, l); //get all the text views
//filter for price
for(TextView priceView: textViews){
if(priceView.id equals "price-id")
//get this TextView.
}
solo.scrollDown();
solo.sleep(500);
}
The problem I am facing with this approach is i don't know how do i filter those views based on the ID. Also, while scrolling, this skips one or two products from current views and am not able to fix that.
If someone could suggest something on this, that would be great.
I will refer to one of my earlier answers which you can use to get you a view at the index of a list here.
Once you have this you can combine the function with a new one that get all the child elements of a view:
private List<View> getAllChildren(View v) {
if (!(v instanceof ViewGroup)) {
ArrayList<View> viewArrayList = new ArrayList<View>();
viewArrayList.add(v);
return viewArrayList;
}
ArrayList<View> result = new ArrayList<View>();
ViewGroup viewGroup = (ViewGroup) v;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
View child = viewGroup.getChildAt(i);
ArrayList<View> viewArrayList = new ArrayList<View>();
viewArrayList.add(v);
viewArrayList.addAll(getAllChildren(child));
result.addAll(viewArrayList);
}
return result;
}
and then finally the last one is to filter a list of views by id
public View(List<View> views, int idToMatch) {
for (View view : views) {
if (view.getId() == idToMatch) {
return view;
}
}
return null;
}
You can probably figure out hwo to combine these all into one function that will do what you want nicely. (Hint an R.id.price is an integer so just pass that into the last functon once you have th elist of children at the index you wanted to get)

TextView is ListView is not shown correctly

I have an app that take strings from database and put it in ListView.
this is the code for getting my String from database:
public void setLogView(String date){
ArrayAdapter<TextView> adapter = new ArrayAdapter<TextView>(this, android.R.layout.simple_list_item_1);
listView.setAdapter(adapter);
DataBaseMain dataBase = new DataBaseMain(this);
dataBase.open();
String[][] all = dataBase.dayLog(date);
dataBase.close();
if(all == null)
return;
String temporay = "";
for(int j = 0; j < all[0].length; j++){
temporay = "";
for (int i = 0; i < all.length; i++){
TextView text = new TextView(this);
temporay = temporay + " " + all[i][j];
text.setText(temporay);
adapter.add((TextView)text);
}
}
}
Its seems that i get new TextView in my ListView but the text is messed up.
I checked my temporay string and is fine.
Is somewhere in putting him in the ListView.
No error in logcat or exceptions.
here is what i got in my app ListView insted of my wanted text.(i wanted to put picutrue but i dont have enough repetion:
There, it becomes clear from the image you provided
Try, this..
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
listView.setAdapter(adapter);
Your adapter to appending textView object instead of String you are providing.
then add temporay instead of textView inside you loop..like
adapter.add(temporay);
This, will certainly solve your issue.
Change your adapter to ArrayAdapter<String>, and add temporay instead of the whole listview.
Or else, you can extend the ArrayAdapter in and override the getView()
Assuming that, you are trying to display the text in custom listview using separate layout.xml which contains only textview in it.
Check my example given below, this is how i did to achieve this:
First of all fetch the data you are want to display and store it in an ArrayList. Here, al_rec_id, al_rec_name are arraylists of the type Integer and String, respectively.
cursor = database.query("records_data", new String[]{"rec_id", "rec_name"}, "cat_id=?", new String[]{cat_id+""}, null, null, null);
if(cursor.getCount() == 0)
Toast.makeText(getBaseContext(), "No records found.", Toast.LENGTH_SHORT).show();
else
{
while(cursor.moveToNext())
{
al_rec_id.add(cursor.getInt(0));
al_rec_name.add(cursor.getString(1));
}
cursor.close();
}
After that, bind this arraylist with ArrayAdapter and then set this adapter to listview as below. Here, array_adapter_all_records is an ArrayAdapter of the type String
array_adapter_all_records = new ArrayAdapter<String>(this, R.layout.single_row_home, R.id.textViewSingleRowHome, al_rec_name);
listview_all_records.setAdapter(array_adapter_all_records);
This is my single_row_home.xml code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="15dp"
android:background="#ffffff" >
<TextView
android:id="#+id/textViewSingleRowHome"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
style="#style/listview_only_textview"
android:text="TextView" />
</RelativeLayout>
Thats it. And you're done...!!!
Create a class custom adapter which will extend your ArrayList Adapter in that You can either inflate a different xml which contains your textview or you can create a dynamic textview as you are doing it now in your getView method in custom Adapter. If You need an example let me know.

android TextView arrays

I am making a word game in which each a user has multiple guesses, each one made up of multiple TextViews. So far my code reads:
TextView[] guess1 = new TextView[numTextViews];
guess1[0] = (TextView) findViewById(R.id.Guess1_1);
guess1[1] = (TextView) findViewById(R.id.Guess1_2);
guess1[2] = (TextView) findViewById(R.id.Guess1_3);
guess1[3] = (TextView) findViewById(R.id.Guess1_4);
guess1[4] = (TextView) findViewById(R.id.Guess1_5);
with the xml looking like:
<TextView
android:id="#+id/Guess1_1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center"
android:text="#string/guessChar" />...
which repeats with android:id= changing.
I am going to be repeating myself if I type out TextView[] guess2 and all its elements.
What is a better way to go about this?
Would it be better to create all the TextViews programmatically as they are so similar?
This is how you can iterate through your views without the use of ids in repetitive code:
LinearLayout ll = (LinearLayout) findViewById(R.id.layout_containing_textviews);
for (int i = 0; i < ll.getChildCount(); i++) {
if (ll.getChildAt(i).getClass() == TextView.class) {
guess1[i] = (TextView)ll.getChildAt(i);
}
}
Make sure to tweak this in case you have non-TextView views since the i index will not be consecutive in that case. You can use another counter just for the TextViews.
Now if your layout has only TextViews, you don't even need an array. You can use that layout as a container/array the way it's used in the snipped above.
Do you know what is the amount of guesses for each text view?
I would suggest you to use reflection
Class clazz = R.id.class; // get the R class
Field f = clazz.getField("Guess1_" + "1");
int id = f.getInt(null); // pass in null, since field is a static field.
TextView currcell = (TextView) findViewById(id);
in this case it will bring the Guess1_1
for you case:
for (int i =0; i < numTextViews; i++)
{
Class clazz = R.id.class;
Field f = clazz.getField("Guess1_" + Integer.toString(i+1));
int id = f.getInt(null);
guess[i] = (TextView)findViewById(id);
}
but this only bring you the first array of Guess1 you need to convert it to generic code..
so some problems can be occur.. so read it with the xml as you have right now would be the easiest way..
Edit:
If the all textView have the same attributes you can also create it programmatically
LinearLayout view = new LinearLayout(this); // create new linear layout
view.setOrientation(LinearLayout.HORIZONTAL); // optional.. so the
// view will be horizontaly
view.setLayoutParams(new LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT)); // set the layout
// height and width
for (int i = 0; i < numOf ; i ++)
{
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
guess[i] = new TextView();
guess[i].setLayoutParams(lp);
guess[i].setID(i+1);
}
You could either create the textViews programmatically (and use inflate if you wish to use some xml too), or you could use the getIdentifier method , for example:
private static final String ID_FORMAT="Guess1_%d";
...
for(int i=0;i<10;++i)
{
String id=String.format(FORMAT,i);
TextView tv = (TextView) findViewById(getResources().getIdentifier(id, "id", getPackageName()));
//...
}
same goes if you wish to do a loop within a loop.
If the layout has a lot of views, I would suggest using an adapterView (listView,gridView,...) instead, and avoid creation of so many views (either programmatically or by xml).

Categories

Resources