Android working with custom array adapter

222 Views Asked by At

I am working on a custom array adapter. I have an expandable list view to which I am adding the list. I also have a search view in which users should be able to search any item. Below is my code for my custom adapter and my fragment

public class ThreeLevelListAdapter extends BaseExpandableListAdapter {

String[] parentHeaders;
List<String[]> secondLevel;
private Context context;
List<LinkedHashMap<String, String[]>> data;

/**
 * Constructor
 * @param context
 * @param parentHeader
 * @param secondLevel
 * @param data
 */
public ThreeLevelListAdapter(Context context, String[] parentHeader, List<String[]> secondLevel, List<LinkedHashMap<String, String[]>> data) {
    this.context = context;

    this.parentHeaders = parentHeader;

    this.secondLevel = secondLevel;

    this.data = data;
}

@Override
public int getGroupCount() {
    return parentHeaders.length;
}

@Override
public int getChildrenCount(int groupPosition) {


    // no idea why this code is working

    return 1;

}

@Override
public Object getGroup(int groupPosition) {

    return groupPosition;
}

@Override
public Object getChild(int group, int child) {


    return child;


}



@Override
public long getGroupId(int groupPosition) {
    return groupPosition;
}

@Override
public long getChildId(int groupPosition, int childPosition) {
    return childPosition;
}

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



@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {

    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    convertView = inflater.inflate(R.layout.row_first, null);
    TextView text = (TextView) convertView.findViewById(R.id.rowParentText);
    text.setText(this.parentHeaders[groupPosition]);

    return convertView;
}

@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {

    final SecondLevelExpandableListView secondLevelELV = new SecondLevelExpandableListView(context);

    String[] headers = secondLevel.get(groupPosition);


    List<String[]> childData = new ArrayList<>();
    HashMap<String, String[]> secondLevelData = data.get(groupPosition);

    for (String key : secondLevelData.keySet()) {


        childData.add(secondLevelData.get(key));

    }


    secondLevelELV.setAdapter(new SecondLevelAdapter(context, headers, childData));

    secondLevelELV.setGroupIndicator(null);


    secondLevelELV.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
        int previousGroup = -1;

        @Override
        public void onGroupExpand(int groupPosition) {
            if (groupPosition != previousGroup)
                secondLevelELV.collapseGroup(previousGroup);
            previousGroup = groupPosition;
        }
    });


    return secondLevelELV;
}

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

` Fragment

SearchView mSearchView;
static String TAG = "product search";
ExpandableListView suggestion_list; 
ThreeLevelListAdapter threeLevelListAdapterAdapter;
 String[] parent = new String[]{"A2A 100 MG TABS", "AQUA-VIT SACHET", "BRONCOPHYLINE SYRUP"};
String[] q1 = new String[]{"BAHRIA TOWN MARKET", "MAIN ROAD BAGH MONCHI LADHA"};
String[] q2 = new String[]{"DAROGHEWALA MAIN BAZAR"};
String[] q3 = new String[]{"ASKARI-10 HOUSING SOCITEY","CHUNGI DOGAJE"};
String[] des1 = new String[]{"M/S MEDSERVE PHARMACY"};
String[] des2 = new String[]{"M/S DANISH MEDICAL STORE"};
String[] des3 = new String[]{"FUTURE HEALTH PHARMACY","M/S ASAD PHARMACY","M/S GHAFOOR MEDICAL STORE"};
String[] des4 = new String[]{"M/S NOOR MEDICOSE"};
String[] des5 = new String[]{"M/S ABDUL GHAFAR MEDIACL STORE"};
ArrayList<String> parentlist = new ArrayList<String>(Arrays.asList(parent));
LinkedHashMap<String, String[]> thirdLevelq1 = new LinkedHashMap<>();
LinkedHashMap<String, String[]> thirdLevelq2 = new LinkedHashMap<>();
LinkedHashMap<String, String[]> thirdLevelq3 = new LinkedHashMap<>();
/**
 * Second level array list
 */
List<String[]> secondLevel = new ArrayList<>();
/**
 * Inner level data
 */
List<LinkedHashMap<String, String[]>> data = new ArrayList<>();

 secondLevel.add(q1);
    secondLevel.add(q2);
    secondLevel.add(q3);
    thirdLevelq1.put(q1[0], des1);
    thirdLevelq1.put(q1[1], des2);
    thirdLevelq2.put(q2[0], des3);
    thirdLevelq3.put(q3[0], des4);
    thirdLevelq3.put(q3[1], des5);

    data.add(thirdLevelq1);
    data.add(thirdLevelq2);
    data.add(thirdLevelq3);

threeLevelListAdapterAdapter = new ThreeLevelListAdapter(getActivity(), parent, secondLevel, data);
    suggestion_list.setAdapter(threeLevelListAdapterAdapter);

 mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String s) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String s) {
            if (TextUtils.isEmpty(s)) {
                // here I want to empty the threeLevelListAdapterAdapter

                suggestion_list.clearTextFilter();
            } else {
                // here I want to fill the threeLevelListAdapterAdapter 
            }
            return true;
        }
    });

Update 1

I have found the below code which implements the search with an expandable list view.

 public void filterData(String query){

 query = query.toLowerCase();
 Log.v("MyListAdapter", String.valueOf(continentList.size()));
 continentList.clear();

 if(query.isEmpty()){
   continentList.addAll(originalList);
 }
 else {

 for(Continent continent: originalList){
 
 ArrayList<Country> countryList = continent.getCountryList();
 ArrayList<Country> newList = new ArrayList<Country>();
 for(Country country: countryList){
 if(country.getCode().toLowerCase().contains(query) ||
   country.getName().toLowerCase().contains(query)){
  newList.add(country);
  }
 }
 if(newList.size() > 0){
  Continent nContinent = new Continent(continent.getName(),newList);
  continentList.add(nContinent);
 }
 }
 }

 Log.v("MyListAdapter", String.valueOf(continentList.size()));
 notifyDataSetChanged();

 }

How I can clear and fill my custom adapter during the search?

Any help would be highly appreciated

3

There are 3 best solutions below

0
On

First step, make the adapters to run on ArrayList instead of String[]. The following is a full sample.

MainActivity.java

public class MainActivity extends AppCompatActivity implements ThreeLevelListAdapter.ThreeLevelListViewListener {
SearchView mSearchView;
ExpandableListView suggestion_list;
ThreeLevelListAdapter threeLevelListAdapterAdapter;

String[] parent = new String[]{"A2A 100 MG TABS", "AQUA-VIT SACHET", "BRONCOPHYLINE SYRUP"};
String[] q1 = new String[]{"BAHRIA TOWN MARKET", "MAIN ROAD BAGH MONCHI LADHA"};
String[] q2 = new String[]{"DAROGHEWALA MAIN BAZAR"};
String[] q3 = new String[]{"ASKARI-10 HOUSING SOCITEY", "CHUNGI DOGAJE"};
String[] des1 = new String[]{"M/S MEDSERVE PHARMACY"};
String[] des2 = new String[]{"M/S DANISH MEDICAL STORE"};
String[] des3 = new String[]{"FUTURE HEALTH PHARMACY", "M/S ASAD PHARMACY", "M/S GHAFOOR MEDICAL STORE"};
String[] des4 = new String[]{"M/S NOOR MEDICOSE"};
String[] des5 = new String[]{"M/S ABDUL GHAFAR MEDIACL STORE"};

ArrayList<SampleData> originalList = new ArrayList<>();
ArrayList<SampleData> continentList = new ArrayList<>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main_page);
    suggestion_list = findViewById(R.id.expandable_listview);
    mSearchView = findViewById(R.id.search_view);

    ArrayList<SampleData> secondLevel = new ArrayList<>();

    ArrayList<String> data = new ArrayList<>(Arrays.asList(des1));
    SampleData sampleData = new SampleData(q1[0], data);
    secondLevel.add(sampleData);
    data = new ArrayList<>(Arrays.asList(des2));
    sampleData = new SampleData(q1[1], data);
    secondLevel.add(sampleData);
    originalList.add(new SampleData(parent[0], secondLevel));

    secondLevel = new ArrayList<>();
    data = new ArrayList<>(Arrays.asList(des3));
    sampleData = new SampleData(q2[0], data);
    secondLevel.add(sampleData);
    originalList.add(new SampleData(parent[1], secondLevel));

    secondLevel = new ArrayList<>();
    data = new ArrayList<>(Arrays.asList(des4));
    sampleData = new SampleData(q3[0], data);
    secondLevel.add(sampleData);
    data = new ArrayList<>(Arrays.asList(des5));
    sampleData = new SampleData(q3[1], data);
    secondLevel.add(sampleData);
    originalList.add(new SampleData(parent[2], secondLevel));

    continentList.addAll(originalList);
    threeLevelListAdapterAdapter = new ThreeLevelListAdapter(this, continentList, this);
    suggestion_list.setAdapter(threeLevelListAdapterAdapter);
    suggestion_list.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
        int previousGroup = -1;

        @Override
        public void onGroupExpand(int groupPosition) {
            if (groupPosition != previousGroup)
                suggestion_list.collapseGroup(previousGroup);
            previousGroup = groupPosition;
        }
    });
    mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String s) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String s) {
            // Second Step is to adopt your filter code here.
            return true;
        }
    });
}

@Override
public void onFinalItemClick(int plpos, int slpos, int tlpos, String plItem, String slItem, String tlItem) {
    Toast.makeText(this, plItem + "\n" + slItem + "\n" + tlItem, Toast.LENGTH_SHORT).show();
}
}

ThreeLevelListAdapter.java

public class ThreeLevelListAdapter extends BaseExpandableListAdapter {
Context context;
ArrayList<SampleData> overallData;
ThreeLevelListViewListener mThreeLevelListViewListener;
LayoutInflater inflater;

public ThreeLevelListAdapter(Context context, ArrayList<SampleData> overallData, ThreeLevelListViewListener listener) {
    this.context = context;
    this.overallData = overallData;
    inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    mThreeLevelListViewListener = listener;
}

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

@Override
public int getChildrenCount(int groupPosition) {
    return 1;
}

@Override
public String getGroup(int groupPosition) {
    return overallData.get(groupPosition).getCategory();
}

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

@Override
public long getGroupId(int groupPosition) {
    return groupPosition;
}

@Override
public long getChildId(int groupPosition, int childPosition) {
    return childPosition;
}

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

@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
    if (convertView == null) convertView = inflater.inflate(R.layout.row_first, null);
    TextView text = convertView.findViewById(R.id.rowParentText);
    text.setText(getGroup(groupPosition));
    return convertView;
}

@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
    final SecondLevelExpandableListView secondLevelELV = new SecondLevelExpandableListView(context);
    ArrayList<SampleData> childData = (ArrayList<SampleData>) getChild(groupPosition, childPosition);
    secondLevelELV.setAdapter(new SecondLevelAdapter(context, childData));
    secondLevelELV.setGroupIndicator(null);
    secondLevelELV.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
        int previousGroup = -1;
        @Override
        public void onGroupExpand(int groupPosition) {
            if (groupPosition != previousGroup)
                secondLevelELV.collapseGroup(previousGroup);
            previousGroup = groupPosition;
        }
    });

    secondLevelELV.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
        @Override
        public boolean onChildClick(ExpandableListView expandableListView, View view, int i, int i1, long l) {
            int ppos = (int)expandableListView.getTag();
            String plItem = getGroup(ppos);
            SecondLevelAdapter adapter = (SecondLevelAdapter)expandableListView.getExpandableListAdapter();
            String slItem = adapter.getGroup(i);
            String tlItem = (String)adapter.getChild(i, i1);
            mThreeLevelListViewListener.onFinalItemClick(ppos, i, i1, plItem, slItem, tlItem);
            return true;
        }
    });
    secondLevelELV.setTag(groupPosition);

    return secondLevelELV;
}

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

public interface ThreeLevelListViewListener{
    void onFinalItemClick(int plpos, int slpos, int tlpos, String plItem, String slItem, String tlItem);
}
}

SecondLevelAdapter.java

public class SecondLevelAdapter extends BaseExpandableListAdapter {
Context context;
ArrayList<SampleData> data;
LayoutInflater inflater;

public SecondLevelAdapter(Context context, ArrayList<SampleData> data) {
    this.context = context;
    this.data = data;
    inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public String getGroup(int groupPosition) {
    return data.get(groupPosition).getCategory();
}

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

@Override
public long getGroupId(int groupPosition) {
    return groupPosition;
}

@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
    if (convertView == null) convertView = inflater.inflate(R.layout.row_second, null);
    TextView text = convertView.findViewById(R.id.rowSecondText);
    text.setText(getGroup(groupPosition));
    return convertView;
}

@Override
public Object getChild(int groupPosition, int childPosition) {
    ArrayList<String> childList = (ArrayList<String>)(data.get(groupPosition).getItems());
    return childList.get(childPosition);
}

@Override
public long getChildId(int groupPosition, int childPosition) {
    return childPosition;
}

@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
    if (convertView == null) convertView = inflater.inflate(R.layout.row_third, null);
    TextView textView = convertView.findViewById(R.id.rowThirdText);
    textView.setText((String)getChild(groupPosition, childPosition));
    return convertView;
}

@Override
public int getChildrenCount(int groupPosition) {
    ArrayList<String> childList = (ArrayList<String>)(data.get(groupPosition).getItems());
    return childList.size();
}

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

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

SampleData.java

public class SampleData {
String Category;
Object items;

public SampleData(String category, Object items) {
    Category = category;
    this.items = items;
}

public String getCategory() {
    return Category;
}

public Object getItems() {
    return items;
}
}
0
On

I have implemented something similar in my project here: github.com/CMPUT301W21T21-H03/DivineInspiration

The way I did this fragment was to make two data array lists, the raw never changing data containing every thing, then another one for the display list. If you check the link, on line 92 is the filter and if the search text is length 0, reset the display list with the original data list and otherwise, I filter starting with the original and append it to a new list that will be the new display list at the end

0
On

All you have to do is to make a new list for your search and pass into your adapter. When the user is done with search pass the first list to your adapter.

    mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String s) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String s) {
            String text = s.getText().toString().toLowerCase(Locale.getDefault());
            ArrayList<Country> countryList = continent.getCountryList();
            List<Country> resultData = new ArrayList<>();
            for (Country country: countryList) {
                if (country.getCode().toLowerCase().contains(text) ||
                        country.getName().toLowerCase().contains(text) )) {
                    resultData.add(country);
                }
            }

            threeLevelListAdapterAdapter = new ThreeLevelListAdapter(getActivity(), parent, secondLevel, resultData);
            suggestion_list.setAdapter(threeLevelListAdapterAdapter);
            if (text.length() == 0) {
                threeLevelListAdapterAdapter = new ThreeLevelListAdapter(getActivity(), parent, secondLevel, data);
                suggestion_list.setAdapter(threeLevelListAdapterAdapter);
            }
            return true;
        }
        
});