3 级 ExpandableListView 重复菜单

3-level ExpandableListView duplicates menu

我正在尝试制作 3 级 ExpandableListView。 第一级菜单工作正常。 当我在第二层有 2 个或更多项目时,就会出现问题。 这些项目乘以第二级的项目数。 例如,

Alberta

->Edmonton

->Calgary

->Edmonton

->Calgary

但是,我只添加了一个埃德蒙顿和一个卡尔加里。

如果我有埃德蒙顿、卡尔加里、波士顿,它总共会有 9 个项目。

(只有一项可以正常工作)。

import android.app.Activity;
import android.content.Context;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.SearchView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity
{
ExpandableListView explvlist;
ParentLevel plAdapter;
Content content = new Content();
SearchView sv;

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    //Remove title bar
    this.requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.activity_main);

    initCountryExpandableListView();
    initSearchView();
}

private void initCountryExpandableListView()
{
    explvlist = (ExpandableListView)findViewById(R.id.ParentLevel);
    plAdapter = new ParentLevel(this);
    explvlist.setAdapter(plAdapter);

    // Listview Group click listener
    explvlist.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {

        @Override
        public boolean onGroupClick(ExpandableListView parent, View v,
                                    int groupPosition, long id) {
            Toast.makeText(getApplicationContext(),
            "Group Clicked " + content.getCountryName(groupPosition),
            Toast.LENGTH_SHORT).show();
            return false;
        }
    });
}

private void initSearchView()
{
    sv = (SearchView)findViewById(R.id.searchView);

    sv.setOnQueryTextListener(new SearchView.OnQueryTextListener( ) {
        @Override
        public boolean onQueryTextChange( String newText ) {
            if(newText.trim().length() == 0)
            {
                content.cancelSearch();
                if(plAdapter!=null)
                    plAdapter.notifyDataSetChanged();
            }
            return true;
        }

        @Override
        public boolean onQueryTextSubmit(String query) {
            content.search(query);
            if(plAdapter!=null)
                plAdapter.notifyDataSetChanged();
            Toast.makeText(getApplicationContext(),
                    "Searching: " + query,
                    Toast.LENGTH_SHORT).show();
            return true;
        }
    });

    sv.setOnCloseListener(new SearchView.OnCloseListener() {
        @Override
        public boolean onClose() {
            content.cancelSearch();
            if(plAdapter!=null)
                plAdapter.notifyDataSetChanged();
            return true;
        }
    });
}

public class ParentLevel extends BaseExpandableListAdapter
{
    private Context _context;
    SecondLevelAdapter slAdapter;

    public ParentLevel(Context context)
    {
        this._context = context;
    }

    @Override
    public Object getChild(int groupPosition, int childPosititon)
    {
        return content.getProvinceName(groupPosition, childPosititon);
    }

    @Override
    public long getChildId(int groupPosition, int childPosition)
    {
        return (long)( groupPosition*1024+childPosition );  // Max 1024 children per group
    }

    @Override
    public View getChildView(int groupPosition, int childPosition,
                             boolean isLastChild, View convertView, ViewGroup parent)
    {
        final int countryPosition = groupPosition;
        CustExpListview SecondLevelexplv = new CustExpListview(MainActivity.this);
        slAdapter = new SecondLevelAdapter(_context, countryPosition);
        SecondLevelexplv.setAdapter(slAdapter);
        // Listview Group click listener
        SecondLevelexplv.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {

            @Override
            public boolean onGroupClick(ExpandableListView parent, View v,
                                        int subGroupPosition, long id) {
                Toast.makeText(getApplicationContext(),
                        "SubGroup Clicked " + content.getProvinceName(countryPosition, subGroupPosition),
                        Toast.LENGTH_SHORT).show();
                return false;
            }
        });

        // Listview on child click listener
        SecondLevelexplv.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {

            @Override
            public boolean onChildClick(ExpandableListView parent, View v,
                                        int subGroupPosition, int childPosition, long id) {
                // TODO Auto-generated method stub
                Toast.makeText(
                        getApplicationContext(),
                        "Child Clicked " + content.getCityName(countryPosition, subGroupPosition, childPosition), Toast.LENGTH_SHORT)
                        .show();
                return false;
            }
        });

        return SecondLevelexplv;
    }

    @Override
    public int getChildrenCount(int groupPosition)
    {
        return content.getProvinceSize(groupPosition);
    }

    @Override
    public Object getGroup(int groupPosition)
    {
        return content.getCountryName(groupPosition);
    }

    @Override
    public int getGroupCount()
    {
        return content.getCountrySize();
    }

    @Override
    public long getGroupId(int groupPosition)
    {
        return (long)( groupPosition*1024 );  // To be consistent with getChildId;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded,
                             View convertView, ViewGroup parent)
    {
        String headerTitle = content.getCountryName(groupPosition);
        if (convertView == null) {
            LayoutInflater infalInflater = (LayoutInflater) this._context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = infalInflater.inflate(R.layout.list_group, null);
        }

        TextView lblListHeader = (TextView) convertView
                .findViewById(R.id.lblListHeader);
        lblListHeader.setTypeface(null, Typeface.BOLD);
        lblListHeader.setText(headerTitle);

        return convertView;
    }

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

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

    @Override
    public void notifyDataSetChanged()
    {
        if(slAdapter!=null)
            slAdapter.notifyDataSetChanged();
        super.notifyDataSetChanged();
    }
}

public class CustExpListview extends ExpandableListView
{

    public CustExpListview(Context context)
    {
        super(context);
    }

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // the value (2000) should not be fixed and be calculated
        // as follows: cell_height x root_items_count x root_items_children_count
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(2000, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

public class SecondLevelAdapter extends BaseExpandableListAdapter
{

    private Context _context;
    private int _groupPosition;

    public SecondLevelAdapter(Context context, int groupPosition)
    {
        this._context = context;
        this._groupPosition = groupPosition;
    }

    @Override
    public Object getChild(int subGroupPosition, int childPosition)
    {
        return content.getCity(subGroupPosition, childPosition);
    }

    @Override
    public long getChildId(int subGroupPosition, int childPosition)
    {
        return (long)( subGroupPosition*1024+childPosition );  // Max 1024 children per group
    }

    @Override
    public View getChildView(int subGroupPosition, int childPosition,
                             boolean isLastChild, View convertView, ViewGroup parent)
    {
        String headerTitle = content.getCityName(_groupPosition, subGroupPosition, childPosition);
        if (convertView == null) {
            LayoutInflater infalInflater = (LayoutInflater) this._context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = infalInflater.inflate(R.layout.list_child, null);
        }

        TextView lblListChild = (TextView) convertView.findViewById(R.id.lblListChild);
        lblListChild.setText(headerTitle);

        return convertView;
    }

    @Override
    public int getChildrenCount(int subGroupPosition)
    {
        return content.getCitySize(_groupPosition, subGroupPosition);
    }

    @Override
    public Object getGroup(int subGroupPosition)
    {
        return content.getProvinceName(_groupPosition, subGroupPosition);
    }

    @Override
    public int getGroupCount()
    {
        return content.getProvinceSize(_groupPosition);
    }

    @Override
    public long getGroupId(int groupPosition)
    {
        return (long)( groupPosition*1024 );  // To be consistent with getChildId;
    }

    @Override
    public View getGroupView(int subGroupPosition, boolean isExpanded,
                             View convertView, ViewGroup parent)
    {
        String headerTitle = content.getProvinceName(_groupPosition, subGroupPosition);
        if (convertView == null) {
            LayoutInflater infalInflater = (LayoutInflater) this._context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = infalInflater.inflate(R.layout.list_subgroup, null);
        }

        TextView lblSubListHeader = (TextView) convertView.findViewById(R.id.lblSubListHeader);
//            lblSubListHeader.setTypeface(null, Typeface.BOLD);
        lblSubListHeader.setText(headerTitle);

        return convertView;
    }

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

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

}
}

Content.java

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

public class Content {

private LinkedHashMap<String, LinkedHashMap<String, List<String>>> data = new LinkedHashMap<>();
private LinkedHashMap<String, LinkedHashMap<String, List<String>>> searchedData = new LinkedHashMap<>();
private boolean isSearch = false;

public Content()
{
    LinkedHashMap<String, List<String>> alberta = new LinkedHashMap<>();
    List<String> edmonton = new ArrayList<>();
    edmonton.add("Snowboarding in Edmonton");
    edmonton.add("Parkland and environment");
    alberta.put("Edmonton", edmonton);

    List<String> calgary = new ArrayList<>();
    calgary.add("First settlement");
    calgary.add("Oil boom");
    alberta.put("Calgary", calgary);
    data.put("Alberta", alberta);

    LinkedHashMap<String, List<String>> bc = new LinkedHashMap<>();
    List<String> whistler = new ArrayList<>();
    whistler.add("Snowboarding in whistler");
    whistler.add("Food an culture of whistler by Dr.Kowuasky");
    bc.put("Whistler", whistler);

    List<String> whiteRock = new ArrayList<>();
    whiteRock.add("Poker Group");
    whiteRock.add("Pool Club");
    bc.put("White Rock", whiteRock);

    List<String> burnaby = new ArrayList<>();
    burnaby.add("Google programming contest");
    burnaby.add("Facebook Hackathon");
    bc.put("Burnaby", burnaby);
    data.put("British Columbia", bc);

    LinkedHashMap<String, List<String>> manitoba = new LinkedHashMap<>();
    data.put("Manitoba", manitoba);

    LinkedHashMap<String, List<String>> newBrunswick = new LinkedHashMap<>();
    data.put("New Brunswick", newBrunswick);

    LinkedHashMap<String, List<String>> newfoundland = new LinkedHashMap<>();
    data.put("Newfoundland", newfoundland);

    LinkedHashMap<String, List<String>> novaScotia = new LinkedHashMap<>();
    data.put("Nova Scotia", novaScotia);

    LinkedHashMap<String, List<String>> ontario = new LinkedHashMap<>();
    data.put("Ontario", ontario);

    LinkedHashMap<String, List<String>> pei = new LinkedHashMap<>();
    data.put("Prince Edward Island", pei);

    LinkedHashMap<String, List<String>> quebec = new LinkedHashMap<>();
    data.put("Quebec", quebec);
}

private LinkedHashMap<String, LinkedHashMap<String, List<String>>> getData()
{
    if(isSearch)
    {
        return searchedData;
    }
    else
    {
        return data;
    }
}

public void search(String input)
{
    isSearch = true;
    searchedData.clear();

    for(String country : data.keySet())
    {
        if(country.toLowerCase().contains(input.toLowerCase()))
        {
            //Add this country
            addCountry(country);
        }
        for(String province : data.get(country).keySet())
        {
            if(province.toLowerCase().contains(input.toLowerCase()))
            {
                //Add this province
                addProvince(country, province);
            }
            for(String city : data.get(country).get(province))
            {
                if(city.toLowerCase().contains(input.toLowerCase()))
                {
                    //Add this city
                    addCity(country, province, city);
                }
            }
        }
    }
}

private void addCountry(String country)
{
    if(!searchedData.containsKey(country))
    {
        searchedData.put(country, new LinkedHashMap<String, List<String>>());
    }
}

private void addProvince(String country, String province)
{
    addCountry(country);
    if(!searchedData.get(country).containsKey(province))
    {
        searchedData.get(country).put(province, new ArrayList<String>());
    }
}

private void addCity(String country, String province, String city)
{
    addProvince(country, province);
    if(!searchedData.get(country).get(province).contains(city))
    {
        searchedData.get(country).get(province).add(city);
    }
}

public void cancelSearch()
{
    isSearch = false;
}

public int getCountrySize()
{
    return getData().size();
}

public String getCountryName(int countryIndex)
{
    List<String> l = new ArrayList<>(getData().keySet());
    return l.get(countryIndex);
}

public LinkedHashMap<String, List<String>> getProvince(int countryIndex)
{
    List<LinkedHashMap<String, List<String>>> l = new ArrayList<>(getData().values());
    return l.get(countryIndex);
}

public int getProvinceSize(int countryIndex)
{
    return getProvince(countryIndex).size();
}

public String getProvinceName(int countryIndex, int provinceIndex)
{
    LinkedHashMap<String, List<String>> p = getProvince(countryIndex);
    List<String> l = new ArrayList<>(p.keySet());
    return l.get(provinceIndex);
}

public List<String> getCity(int countryIndex, int provinceIndex)
{
    LinkedHashMap<String, List<String>> p = getProvince(countryIndex);
    List<List<String>> l = new ArrayList<>(p.values());
    return l.get(provinceIndex);
}

public int getCitySize(int countryIndex, int provinceIndex)
{
    return getCity(countryIndex, provinceIndex).size();
}

public String getCityName(int countryIndex, int provinceIndex, int cityIndex)
{
    List<String> c = getCity(countryIndex, provinceIndex);
    return c.get(cityIndex);
}
}

将第二个 expandablelistadapter getGroupCount 设为 return 1