0

Good day!

I'm a newbie at android/java programming and I'm trying to create, kinda like, a history function to my app. I'm using an expandableListView with a gridView (or listView; I don't really know what else to use aside from these two) inside to show said history. All the data comes from sqLite database which has 3 tables named Requests, Properties & ReqLine all linked together.

The format I'm trying to create is something like this (Sorry, cant post images yet):


HEADER: TextView ----- data from db 1st table


CHILD: TextView ----- data from 2nd
GRID:
1)item from DB 3rd table
2)item from DB 3rd table


I was able to populate the header and child portions but I'm having trouble with the child gridView repeating data on every child. I know it's with the way I'm passing the ArrayList to the GridView Adapter but I don't the correct way of doing it or how to implement it.

I tried a bunch of ways including adding another arraylist to my header class model but I don't know how I should get the childcount for it in my adapter.

I've seen lots on posts here in SO but none of them seems to have the solution to my problem. Can anyone help me with this? Thanks in advance! Suggestions on revisions are welcome as well.

Here's my code for the history fragment:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.history_tab_layout, container, false);

    openHelper = new DatabaseHelper(getActivity());
    myDb = openHelper.getReadableDatabase();
    TextView _number = (TextView) rootView.findViewById(R.id.lblNumber);
    TextView _date = (TextView) rootView.findViewById(R.id.lblHistoryDate);
    TextView _transtype = (TextView) rootView.findViewById(R.id.lblHistoryTransType);
    TextView _amount = (TextView) rootView.findViewById(R.id.lblHistoryAmount);

    Cursor mCursor = null;
    Cursor dataCursor = null;
    Cursor itemCursor = null;
    String Query = "SELECT * FROM Requests";
    mCursor = myDb.rawQuery(Query, null);
    transHistory = new ArrayList<HistoryHeader>();
    gridHistory = new ArrayList<GridItems>();
    int count = 1;
    if(mCursor.getCount()!=0) {
        while (mCursor.moveToNext()) {
            String reqDate = mCursor.getString(mCursor.getColumnIndex("RequestDate"));
            String reqTransType = mCursor.getString(mCursor.getColumnIndex("TransType"));
            String reqTotalAmt = mCursor.getString(mCursor.getColumnIndex("AmtTotal"));
            String reqPCode = mCursor.getString(mCursor.getColumnIndex("Property"));
            String BaseId = mCursor.getString(0);
            HistoryHeader history = new HistoryHeader(count, reqDate, reqTransType, reqTotalAmt);

            String Query2 = "SELECT * FROM Projects WHERE PrjCode = '"+ mCursor.getString(3) +"'";
            dataCursor = myDb.rawQuery(Query2, null);
            if (dataCursor.getCount()!=0){
                while (dataCursor.moveToNext()){
                    String reqPName = dataCursor.getString(dataCursor.getColumnIndex("PrjName"));
                    history.setItemList(createItems(reqPCode, reqPName, 1));
                }
            }

            String Query3 = "SELECT * FROM ReqLine WHERE Base_Id = "+ BaseId;
            itemCursor = myDb.rawQuery(Query3, null);
            if (itemCursor.getCount()!=0) {
                while (itemCursor.moveToNext()) {
                    String reqPurpose = itemCursor.getString(itemCursor.getColumnIndex("Purpose"));
                    String reqAmount = itemCursor.getString(itemCursor.getColumnIndex("AmtLine"));
                    Integer reqNum = itemCursor.getInt(itemCursor.getColumnIndex("Linenum"));
                    GridItems test = new GridItems(reqNum, reqPurpose, reqAmount);
                    gridHistory.add(test);
                }
            }

            transHistory.add(history);
            count++;
        }
    }

    final ExpandableListView _Content = (ExpandableListView) rootView.findViewById(R.id.historyList);
    _Content.setIndicatorBounds(5,5);
    HistoryAdapter exAdpt = new HistoryAdapter(getActivity(), transHistory, gridHistory);
    _Content.setIndicatorBounds(0,20);
    _Content.setAdapter(exAdpt);

    return rootView;
}

private List<HistoryDetail> createItems(String _strPropertyCode, String _strPropertyName, int num) {
    List<HistoryDetail> result = new ArrayList<HistoryDetail>();
    for (int i=0; i < num; i++) {
        HistoryDetail item = new HistoryDetail(i, _strPropertyCode, _strPropertyName);
        result.add(item);
    }
    return result;
}

And the Code for my HistoryAdapter.java

public class HistoryAdapter extends BaseExpandableListAdapter {
private Context context;
private List<HistoryHeader> _listDataHeader;
private ArrayList<GridItems> _listGridItems;

public HistoryAdapter(Context context, List<HistoryHeader> _listDataHeader, ArrayList<GridItems> _listGridItems) {
    this.context = context;
    this._listDataHeader = _listDataHeader;
    this._listGridItems = _listGridItems;
}

@Override
public int getGroupCount() {
    return _listDataHeader.size();
}

@Override
public int getChildrenCount(int groupPosition) {
    /*Integer size = _listDataHeader.get(groupPosition).getItemList().size();
    return size;*/
    return 1;
}

@Override
public Object getGroup(int groupPosition) {
    return _listDataHeader.get(groupPosition);
}

@Override
public Object getChild(int groupPosition, int childPosition) {
    return _listDataHeader.get(groupPosition).getItemList().get(childPosition);
}

@Override
public long getGroupId(int groupPosition) {
    return _listDataHeader.get(groupPosition).hashCode();
}

@Override
public long getChildId(int groupPosition, int childPosition) {
    return _listDataHeader.get(groupPosition).getItemList().get(childPosition).hashCode();
}

@Override
public boolean hasStableIds() {
    return true;
}

@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup viewGroup) {
    View v = convertView;
    if (v == null) {
        LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.history_list_group, null);
    }
    TextView groupNum = (TextView) v.findViewById(R.id.historyNumber);
    TextView groupDate = (TextView) v.findViewById(R.id.historyDate);
    TextView groupTransType = (TextView) v.findViewById(R.id.historyTransType);
    TextView groupAmount = (TextView) v.findViewById(R.id.historyTotalAmt);

    HistoryHeader header = _listDataHeader.get(groupPosition);

    groupNum.setText(String.valueOf(header.getId()));
    groupDate.setText(header.getDate());
    groupTransType.setText(header.getTransType());
    groupAmount.setText(header.getTotalAmt());

    return v;
}

@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup viewGroup) {
    View v = convertView;
    if (v == null) {
        LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.history_list_child, null);
    }
    TextView itemPropCode = (TextView) v.findViewById(R.id.historyPropertyCode);
    TextView itemPropName = (TextView) v.findViewById(R.id.historyPropertyName);
    GridView itemGrid = (GridView) v.findViewById(R.id.historyItemList);
    ItemGridAdapter adapter = new ItemGridAdapter(context,_listGridItems);
    itemGrid.setAdapter(adapter);

    HistoryDetail detail = _listDataHeader.get(groupPosition).getItemList().get(childPosition);

    itemPropCode.setText(detail.getPropertyCode());
    itemPropName.setText(detail.getPropertyName());

    return v;
}

@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
    return true;
}

Then the ItemGridAdapter.java

public class ItemGridAdapter extends BaseAdapter {
Context context;
ArrayList<GridItems> itemList;

public ItemGridAdapter(Context context, ArrayList<GridItems> itemList) {
    this.context = context;
    this.itemList = itemList;
}

@Override
public int getCount() {
    // TODO Auto-generated method stub
    return itemList.size();
}

@Override
public Object getItem(int position) {
    // TODO Auto-generated method stub
    return position;
}

@Override
public long getItemId(int position) {
    // TODO Auto-generated method stub
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    if (convertView == null) {
        LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.history_grid_layout, null);
    }

    TextView _rowPurpose = (TextView) convertView.findViewById(R.id.rowPurpose);
    TextView _rowAmount = (TextView) convertView.findViewById(R.id.rowAmount);

    GridItems gridItems = itemList.get(position);
    _rowPurpose.setText(gridItems.getPurpose());
    _rowAmount.setText(gridItems.getAmount());

    return convertView;
}

@Override
public boolean areAllItemsEnabled() {
    return false;
}

@Override
public boolean isEnabled(int position) {
    // Return true for clickable, false for not
    return false;
}

Model Classes

public class HistoryHeader implements Serializable {
private long id;
private String _strDate;
private String _strTransType;
private String _strTotalAmt;

private List<HistoryDetail> itemDetails = new ArrayList<HistoryDetail>();
private List<GridItems> itemGrid = new ArrayList<>();

public HistoryHeader(long id, String _strDate, String _strTransType, String _strTotalAmt) {
    this.id = id;
    this._strDate = _strDate;
    this._strTransType = _strTransType;
    this._strTotalAmt = _strTotalAmt;
}

public long getId() {
    return id;
}

public void setId(long id) {
    this.id = id;
}

public String getDate() {
    return _strDate;
}

public void setDate(String _strDate) {
    this._strDate = _strDate;
}

public String getTransType() {
    return _strTransType;
}

public void setTransType(String _strTransType) {
    this._strTransType = _strTransType;
}

public String getTotalAmt() {
    return _strTotalAmt;
}

public void setTotalAmt(String _strTotalAmt) {
    this._strTotalAmt = _strTotalAmt;
}

public List<HistoryDetail> getItemList() {
    return itemDetails;
}

public void setItemList(List<HistoryDetail> itemDetails) {
    this.itemDetails = itemDetails;
}

public List<GridItems> getItemGrid(){ return itemGrid; }

public void setItemGrid(List<GridItems> itemGrid) { this.itemGrid = itemGrid; }


public class GridItems {
private long id;
private String _strPurpose, _strAmount;

public GridItems(long id, String _strPurpose, String _strAmount) {
    this.id = id;
    this._strPurpose = _strPurpose;
    this._strAmount = _strAmount;
}

public long getId() {
    return id;
}
public void setId(long id) {
    this.id = id;
}
public String getPurpose() {
    return _strPurpose;
}
public void setPurpose(String _strPurpose) {
    this._strPurpose = _strPurpose;
}
public String getAmount() {
    return _strAmount;
}
public void setAmount(String _strAmount) {
    this._strAmount = _strAmount;
}
GianhTran
  • 2,890
  • 2
  • 15
  • 34
jpBlue
  • 3
  • 3

1 Answers1

0

Try this:

Cursor mCursor = null;
Cursor dataCursor = null;
Cursor itemCursor = null;
String Query = "SELECT * FROM Requests";
mCursor = myDb.rawQuery(Query, null);
transHistory = new ArrayList<HistoryHeader>();
//allGridHistory = new ArrayList<ArrayList<GridItems>>(); // Changed2
//gridHistory = new ArrayList<GridItems>();
int count = 1;
if(mCursor.getCount()!=0) {
    while (mCursor.moveToNext()) {
        String reqDate = mCursor.getString(mCursor.getColumnIndex("RequestDate"));
        String reqTransType = mCursor.getString(mCursor.getColumnIndex("TransType"));
        String reqTotalAmt = mCursor.getString(mCursor.getColumnIndex("AmtTotal"));
        String reqPCode = mCursor.getString(mCursor.getColumnIndex("Property"));
        String BaseId = mCursor.getString(0);
        HistoryHeader history = new HistoryHeader(count, reqDate, reqTransType, reqTotalAmt);

        String Query2 = "SELECT * FROM Projects WHERE PrjCode = '"+ mCursor.getString(3) +"'";
        dataCursor = myDb.rawQuery(Query2, null);
        if (dataCursor.getCount()!=0){
            while (dataCursor.moveToNext()){
                String reqPName = dataCursor.getString(dataCursor.getColumnIndex("PrjName"));
                history.setItemList(createItems(reqPCode, reqPName, 1));
            }
        }

        String Query3 = "SELECT * FROM ReqLine WHERE Base_Id = "+ BaseId;
        itemCursor = myDb.rawQuery(Query3, null);
        if (itemCursor.getCount()!=0) {
            gridHistory = new ArrayList<GridItems>(); // Added
            while (itemCursor.moveToNext()) {
                String reqPurpose = itemCursor.getString(itemCursor.getColumnIndex("Purpose"));
                String reqAmount = itemCursor.getString(itemCursor.getColumnIndex("AmtLine"));
                Integer reqNum = itemCursor.getInt(itemCursor.getColumnIndex("Linenum"));
                GridItems test = new GridItems(reqNum, reqPurpose, reqAmount);
                gridHistory.add(test);
            }
            history.setItemGrid(gridHistory); // Changed2
        }

        transHistory.add(history);
        count++;
    }
}

final ExpandableListView _Content = (ExpandableListView) rootView.findViewById(R.id.historyList);
_Content.setIndicatorBounds(5,5);
HistoryAdapter exAdpt = new HistoryAdapter(getActivity(), transHistory); // Changed2

The adapter:

public class HistoryAdapter extends BaseExpandableListAdapter {
private Context context;
private List<HistoryHeader> _listDataHeader;
//private ArrayList<GridItems> _listGridItems;

public HistoryAdapter(Context context, List<HistoryHeader> _listDataHeader) {
    this.context = context;
    this._listDataHeader = _listDataHeader;
    //this._listGridItems = _listGridItems;
}

@Override
public int getGroupCount() {
    return _listDataHeader.size();
}

@Override
public int getChildrenCount(int groupPosition) {
/*Integer size = _listDataHeader.get(groupPosition).getItemList().size();
return size;*/
    return 1;
}

@Override
public HistoryHeader getGroup(int groupPosition) {
    return _listDataHeader.get(groupPosition);
}

@Override
public Object getChild(int groupPosition, int childPosition) {
    return _listDataHeader.get(groupPosition).getItemList().get(childPosition);
}

@Override
public long getGroupId(int groupPosition) {
    return _listDataHeader.get(groupPosition).hashCode();
}

@Override
public long getChildId(int groupPosition, int childPosition) {
    return _listDataHeader.get(groupPosition).getItemList().get(childPosition).hashCode();
}

@Override
public boolean hasStableIds() {
    return true;
}

@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup viewGroup) {
    View v = convertView;
    if (v == null) {
        LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.history_list_group, null);
    }
    TextView groupNum = (TextView) v.findViewById(R.id.historyNumber);
    TextView groupDate = (TextView) v.findViewById(R.id.historyDate);
    TextView groupTransType = (TextView) v.findViewById(R.id.historyTransType);
    TextView groupAmount = (TextView) v.findViewById(R.id.historyTotalAmt);

    HistoryHeader header = _listDataHeader.get(groupPosition);

    groupNum.setText(String.valueOf(header.getId()));
    groupDate.setText(header.getDate());
    groupTransType.setText(header.getTransType());
    groupAmount.setText(header.getTotalAmt());

    return v;
}

@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup viewGroup) {
    View v = convertView;

    // As for using grid view, there is only one child, no suitable view for reuse/recycle.
    //if (v == null) {
        LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.history_list_child, null);
    //}

    TextView itemPropCode = (TextView) v.findViewById(R.id.historyPropertyCode);
    TextView itemPropName = (TextView) v.findViewById(R.id.historyPropertyName);
    GridView itemGrid = (GridView) v.findViewById(R.id.historyItemList);

    // Get the child list of this group/header.
    List<GridItems> history_list_child = getGroup(groupPosition).getItemGrid();

    // As for using grid view, onChildClickListener cannot be used. You may need to pass the group/header object
    // to grid view adapter and do onClick inside getView. First try your original way to display data correctly.
    ItemGridAdapter adapter = new ItemGridAdapter(context, history_list_child);
    itemGrid.setAdapter(adapter);

    HistoryDetail detail = _listDataHeader.get(groupPosition).getItemList().get(childPosition);
    itemPropCode.setText(detail.getPropertyCode());
    itemPropName.setText(detail.getPropertyName());

    return v;
}

@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
    return true;
}
}

Hope that helps!

i_A_mok
  • 2,536
  • 2
  • 9
  • 13
  • Thanks for the reply @I_A_Mok! I've tried adding the lines you suggested and change the HistoryAdapter accordingly but I'm not exactly sure how to change the ItemGridAdapter.java to match the added lines. I'm getting _incompatible types_ error on the line where it says `GridItems gridItems = itemList.get(position);`. Can you please instruct me on how I should set the text for the gridview after adding these lines? Thanks again! – jpBlue Aug 17 '18 at 07:24
  • I just noticed that you can have the grid list inside your header class, therefore I changed the code a little bit (the 3 lines commented with **Changed2**) and also added the adapter code. You may also take a look of my answers here: https://stackoverflow.com/questions/49914836/checkbox-for-gridview-inside-listview-in-android/49934675#49934675 , https://stackoverflow.com/questions/50288713/expandablelistview-with-viewpager-combination-as-its-child/50383160#50383160 – i_A_mok Aug 18 '18 at 08:34
  • Hey I_A_Mok, thanks again for helping me with this. I've tried the changes you provided but, I can't seem to get this line to work: `List history_list_child = getGroup(groupPosition).getItemGrid();`. It's giving me a **cannot resolved method getItemGrid()** error. I tried modifying it but I can't seem to figure out how to get the child list for the group using `List` or `ArrayList`. I looked at the links you provided as well but both seem to be using the HashMap method and is a little different to how my code is structured so I'm a bit lost. Can you please tell me what I'm missing? – jpBlue Aug 19 '18 at 14:36
  • By the way, no worries about the `onChildClickListener` for the gridview. I actually want to disable it in my app since the whole purpose of the grid is just to show the values. That's why I added the last 2 boolean codes in my ItemGridAdapter. Thanks again! – jpBlue Aug 19 '18 at 14:41
  • Please note that in my adapter, **getGroup** return HistoryHeader instead of object. I forgot to mark it as Changed. – i_A_mok Aug 19 '18 at 16:00
  • Wow! This is awesome! It's finally working the way I want it too. Thanks so much! you're a life saver! Wish I could give this a +10 but even my +1 wont show up since I don't have enough rep. But really, you saved me alot of headaches trying to solve this issue. XD Hope this help others doing similar projects as well. – jpBlue Aug 20 '18 at 00:26