ExpandableListView with ViewPager combination as i

2020-02-01 19:04发布

UPDATE - Added experimentation result

Is it possible to implement an ExpandableListView to have a viewpager child?

I tried to put viewpager as a child in ExpandableListView but it is not showing :( I also tried to add it under ScrollView but same result so I think it is a problem being under a scrollable view? But when I removed ScrollView it showed up. What can I do so they can go together?


This is what I am aiming for to do

Original Pic

And this is what happen when I tried to implement on my own code.
P.S. This is just a sampler and not yet finished. I have 3 children and my layout displayed thrice also with each item inside

enter image description here

2条回答
爱情/是我丢掉的垃圾
2楼-- · 2020-02-01 19:35

I made a sample in Java. Hope that helps!

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

            <Button
                android:id="@+id/btnClearChecks"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="Clear Checks" />

            <Button
                android:id="@+id/btnPutOrder"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="Put Order" />
    </LinearLayout>

    <ExpandableListView
        android:id="@+id/expandedListView"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </ExpandableListView>
</LinearLayout>

expanded_list_group.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants" >

<CheckBox
    android:id="@+id/cb_group"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="40dp"
    android:layout_gravity="center_vertical" />

<TextView
    android:id="@+id/tv_group"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Text"
    android:textSize="30sp" />
</LinearLayout>

list_child_pager.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="60dp">

<android.support.v4.view.ViewPager
    android:id="@+id/layout_child"
    android:layout_width="match_parent"
    android:layout_height="200dp" />
</LinearLayout>

list_pager_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnCount="@integer/pager_col_count"
android:rowCount="@integer/pager_row_count">

</GridLayout>

integers.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="pager_col_count">3</integer>
<integer name="pager_row_count">3</integer>
</resources>

ChildItemSample.java

public class ChildItemSample {
private boolean checked = false;
private String name;
private int qty;

public int getQty() {
    return qty;
}

public void setQty(int qty) {
    this.qty = qty;
}

public boolean isChecked() {
    return checked;
}

public void setChecked(boolean checked) {
    this.checked = checked;
}

public String getName() {
    return name;
}

public ChildItemSample(String name, int qty){
    this.name = name;
    this.qty = qty;
}
}

MainActivity.java:

public class MainActivity extends AppCompatActivity {
Button clearChecks, putOrder;
ExpandableListView expandableListView;
ExpandableListPagerAdapter expandableListAdapter;
int lastExpandedPosition = -1;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    expandableListView = findViewById(R.id.expandedListView);
    clearChecks = findViewById(R.id.btnClearChecks);
    putOrder = findViewById(R.id.btnPutOrder);

    List<String> listTitle = genGroupList();
    expandableListAdapter = new ExpandableListPagerAdapter(this, getSupportFragmentManager(), listTitle, genChildList(listTitle));
    expandableListView.setAdapter(expandableListAdapter);

    expandableListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
        @Override
        public void onGroupExpand(int groupPosition) {
            if(lastExpandedPosition != -1 && (lastExpandedPosition != groupPosition)){
                expandableListView.collapseGroup(lastExpandedPosition);
            }
            lastExpandedPosition = groupPosition;
        }
    });
    clearChecks.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            expandableListAdapter.clearChecks();
        }
    });
    putOrder.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            ArrayList<String> putOrder = expandableListAdapter.getOrderList();
            StringBuilder msg = new StringBuilder();
            for(int i=0; i<putOrder.size(); i++){
                msg.append(putOrder.get(i));
                msg.append("\n");
            }
            Toast.makeText(getBaseContext(), msg, Toast.LENGTH_LONG).show();
        }
    });
}

private ArrayList<String> genGroupList(){
    ArrayList<String> listGroup = new ArrayList<>();
    for(int i=1; i<10; i++){
        listGroup.add("Group: " + i);
    }
    return listGroup;
}

private Map<String, List<ChildItemSample>> genChildList(List<String> header){
    Map<String, List<ChildItemSample>> listChild = new HashMap<>();
    for(int i=0; i<header.size(); i++){
        List<ChildItemSample> testDataList = new ArrayList<>();
        int a = (int)(Math.random()*28);
        for(int j=0; j<a; j++){
            ChildItemSample testItem = new ChildItemSample("Child " + (j + 1), 0);
            testDataList.add(testItem);
        }
        listChild.put(header.get(i), testDataList);
    }
    return listChild;
}
}

ExpandableListPagerAdapter.java:

public class ExpandableListPagerAdapter extends BaseExpandableListAdapter {
private int child_items_per_page;

private Context context;
private FragmentManager fm;
private List<String> listGroup;
private Map<String, List<ChildItemSample>> listChild;
private static int checkedBoxesCount;
private boolean[] checkedGroup;

ExpandableListPagerAdapter(Context context, FragmentManager manager, List<String> listGroup, Map<String,
        List<ChildItemSample>> listChild) {
    this.context = context;
    fm = manager;
    this.listGroup = listGroup;
    this.listChild = listChild;
    checkedBoxesCount = 0;
    checkedGroup = new boolean[listGroup.size()];
    child_items_per_page = context.getResources().getInteger(R.integer.pager_col_count) *
            context.getResources().getInteger(R.integer.pager_row_count);
}

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

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

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

@Override
public ChildItemSample getChild(int groupPosition, int childPosition) {
    return listChild.get(listGroup.get(groupPosition)).get(childPosition);
}

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

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

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

@Override
public View getGroupView(int groupPosition, boolean b, View view, ViewGroup viewGroup) {
    String itemGroup = getGroup(groupPosition);
    GroupViewHolder groupViewHolder;
    if(view == null){
        LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.expanded_list_group, null);
        groupViewHolder = new GroupViewHolder();
        groupViewHolder.tvGroup = view.findViewById(R.id.tv_group);
        groupViewHolder.cbGroup = view.findViewById(R.id.cb_group);
        groupViewHolder.cbGroup.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int pos = (int)view.getTag();
                checkedGroup[pos] = !checkedGroup[pos];
                for(ChildItemSample item : listChild.get(listGroup.get(pos))){
                    item.setChecked(checkedGroup[pos]);
                }
                notifyDataSetChanged();
            }
        });
        view.setTag(groupViewHolder);
    }else {
        groupViewHolder = (GroupViewHolder)view.getTag();
    }
    groupViewHolder.tvGroup.setText(String.format("%s (%d)", itemGroup, listChild.get(listGroup.get(groupPosition)).size()));
    if(checkedGroup[groupPosition]) groupViewHolder.cbGroup.setChecked(true);
    else groupViewHolder.cbGroup.setChecked(false);
    groupViewHolder.cbGroup.setTag(groupPosition);
    return view;
}

@Override
public View getChildView(final int groupPosition, int childPosition, boolean b, View view, ViewGroup viewGroup) {
    LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View rowView = inflater.inflate(R.layout.list_child_pager, null);
    ViewPager childLayout = rowView.findViewById(R.id.layout_child);

    List<ChildItemSample> childItemSampleList = listChild.get(listGroup.get(groupPosition));
    ChildPagerAdapter adapter = new ChildPagerAdapter(fm, childItemSampleList, child_items_per_page);
    childLayout.setAdapter(adapter);
    return rowView;
}

public class ChildPagerAdapter extends FragmentStatePagerAdapter {
    private List<ChildItemSample> pagerItemList;
    private int items_per_page;

    ChildPagerAdapter(FragmentManager fm, List<ChildItemSample> pagerItemList, int items_per_page) {
        super(fm);
        this.pagerItemList = pagerItemList;
        this.items_per_page = items_per_page;
    }

    @Override
    public Fragment getItem(int position) {
        return ChildFragment.newInstance(position, pagerItemList, items_per_page);
    }

    @Override
    public int getCount() {
        int remainedItemCount = pagerItemList.size()%child_items_per_page;
        if(remainedItemCount == 0)
            return (pagerItemList.size()/child_items_per_page);
        else
            return (pagerItemList.size()/child_items_per_page + 1);
    }
}

public static class ChildFragment extends Fragment {
    private static final String SECTION_NUMBER = "section_number";
    private static final String ITEMS_PER_PAGE = "items/page";
    private static List<ChildItemSample> itemList;

    public ChildFragment() {}

    public static ChildFragment newInstance(int sectionNumber, List<ChildItemSample> pagerItemList,
                                            int itemPerPage) {
        ChildFragment fragment = new ChildFragment();
        Bundle args = new Bundle();
        args.putInt(SECTION_NUMBER, sectionNumber);
        args.putInt(ITEMS_PER_PAGE, itemPerPage);
        fragment.setArguments(args);
        itemList = pagerItemList;
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        int child_items_per_page = getArguments().getInt(ITEMS_PER_PAGE);
        int start_item = getArguments().getInt(SECTION_NUMBER)*child_items_per_page;
        int itemCount = itemList.size() - getArguments().getInt(SECTION_NUMBER)*child_items_per_page;
        if(itemCount > child_items_per_page) itemCount = child_items_per_page;
        itemCount += getArguments().getInt(SECTION_NUMBER)*child_items_per_page;

        GridLayout pageView = (GridLayout)inflater.inflate(R.layout.list_pager_item, container, false);
        for(int i=start_item; i<itemCount; i++){
            ChildItemSample expandedListText = itemList.get(i);
            CheckBox cbChild = new CheckBox(getContext());
            GridLayout.LayoutParams params = new GridLayout.LayoutParams();
            params.width = (int)(80 * getContext().getResources().getDisplayMetrics().density);
            cbChild.setLayoutParams(params);
            cbChild.setChecked(expandedListText.isChecked());
            cbChild.setText(expandedListText.getName());
            cbChild.setTag(i);
            pageView.addView(cbChild);

            cbChild.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    CheckBox cb = (CheckBox) view;
                    int pos = (int) view.getTag();
                    ChildItemSample selectedItem = itemList.get(pos);
                    selectedItem.setChecked(cb.isChecked());
                    if(cb.isChecked()){
                        checkedBoxesCount++;
                        Toast.makeText(getContext(),"Checked value is: " +
                                        itemList.get(pos).getName(),
                                Toast.LENGTH_SHORT).show();
                    }else {
                        checkedBoxesCount--;
                        if(checkedBoxesCount == 0){
                            Toast.makeText(getContext(),"nothing checked",Toast.LENGTH_SHORT).show();
                        }else {
                            Toast.makeText(getContext(),"unchecked",Toast.LENGTH_SHORT).show();
                        }
                    }
                }
            });
        }
        return pageView;
    }
}

public void clearChecks() {
    for(int i=0; i<checkedGroup.length; i++) checkedGroup[i] = false;
    for(List<ChildItemSample> value : listChild.values()) {
        for (ChildItemSample sample : value) {
            sample.setChecked(false);
        }
    }
    checkedBoxesCount = 0;
    notifyDataSetChanged();
}

public ArrayList<String> getOrderList(){
    ArrayList<String> overallOrder = new ArrayList<>();
    for(int i=0; i<getGroupCount(); i++){
        //for(int j=0; j<getChildrenCount(i); j++){
        for(int j=0; j<listChild.get(getGroup(i)).size(); j++){
            if(getChild(i,j).isChecked()){
                String newOrder = getGroup(i) + ">" + getChild(i, j).getName();
                overallOrder.add(newOrder);
            }
        }
    }
    return overallOrder;
}

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

private class GroupViewHolder {
    CheckBox cbGroup;
    TextView tvGroup;
}
}

Another sample adapter that has ViewPager child (Without fragment)

public class ExpandableListPagerAdapter2 extends BaseExpandableListAdapter {
private Context context;
private List<String> listGroup;
private Map<String, List<ChildItemSample>> listChild;
private int checkedBoxesCount;
private boolean[] checkedGroup;
private int child_items_per_page;

ExpandableListPagerAdapter2(Context context, List<String> listGroup, Map<String,
        List<ChildItemSample>> listChild) {
    this.context = context;
    this.listGroup = listGroup;
    this.listChild = listChild;
    checkedBoxesCount = 0;
    checkedGroup = new boolean[listGroup.size()];
    child_items_per_page = context.getResources().getInteger(R.integer.pager_col_count) *
            context.getResources().getInteger(R.integer.pager_row_count);
}

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

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

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

@Override
public ChildItemSample getChild(int groupPosition, int childPosition) {
    return listChild.get(listGroup.get(groupPosition)).get(childPosition);
}

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

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

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

@Override
public View getGroupView(int groupPosition, boolean b, View view, ViewGroup viewGroup) {
    String itemGroup = getGroup(groupPosition);
    GroupViewHolder groupViewHolder;
    if(view == null){
        LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.expanded_list_group, null);
        groupViewHolder = new GroupViewHolder();
        groupViewHolder.tvGroup = view.findViewById(R.id.tv_group);
        groupViewHolder.cbGroup = view.findViewById(R.id.cb_group);
        groupViewHolder.cbGroup.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int pos = (int)view.getTag();
                checkedGroup[pos] = !checkedGroup[pos];
                for(ChildItemSample item : listChild.get(listGroup.get(pos))){
                    item.setChecked(checkedGroup[pos]);
                }
                notifyDataSetChanged();
            }
        });
        view.setTag(groupViewHolder);
    }else {
        groupViewHolder = (GroupViewHolder)view.getTag();
    }
    groupViewHolder.tvGroup.setText(String.format("%s (%d)", itemGroup, listChild.get(listGroup.get(groupPosition)).size()));
    if(checkedGroup[groupPosition]) groupViewHolder.cbGroup.setChecked(true);
    else groupViewHolder.cbGroup.setChecked(false);
    groupViewHolder.cbGroup.setTag(groupPosition);
    return view;
}

@Override
public View getChildView(int groupPosition, int childPosition, boolean b, View view, ViewGroup viewGroup) {
    LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View rowView = inflater.inflate(R.layout.list_child_pager, null);
    ViewPager childLayout = rowView.findViewById(R.id.layout_child);

    List<ChildItemSample> childItemSampleList = listChild.get(listGroup.get(groupPosition));
    ChildPagerAdapter adapter = new ChildPagerAdapter(childItemSampleList);
    childLayout.setAdapter(adapter);
    return rowView;
}

public class ChildPagerAdapter extends PagerAdapter {
    private List<ChildItemSample> pagerItemList;

    ChildPagerAdapter(List<ChildItemSample> pagerItemList) {
        this.pagerItemList = pagerItemList;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        int start_item = position*child_items_per_page;
        int itemCount = pagerItemList.size() - start_item;
        if(itemCount > child_items_per_page) itemCount = child_items_per_page;
        itemCount += start_item;

        LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        GridLayout pageView = (GridLayout)inflater.inflate(R.layout.list_pager_item, container, false);
        for(int i=start_item; i<itemCount; i++){
            ChildItemSample expandedListText = pagerItemList.get(i);
            CheckBox cbChild = new CheckBox(context);
            GridLayout.LayoutParams params = new GridLayout.LayoutParams();
            params.width = (int)(80 * context.getResources().getDisplayMetrics().density);
            cbChild.setLayoutParams(params);
            cbChild.setChecked(expandedListText.isChecked());
            cbChild.setText(expandedListText.getName() + "(" + expandedListText.getQty() + ")");
            cbChild.setTag(i);
            pageView.addView(cbChild);

            cbChild.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    int pos = (int) view.getTag();
                    final ChildItemSample selectedItem = pagerItemList.get(pos);
                    AlertDialog.Builder builder = new AlertDialog.Builder(context);
                    builder.setTitle(selectedItem.getName());
                    final EditText editText = new EditText(context);
                    editText.setText("");
                    editText.append(String.valueOf(selectedItem.getQty()));
                    builder.setView(editText);
                    builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            selectedItem.setQty(Integer.parseInt(editText.getText().toString()));
                            ExpandableListPagerAdapter2.this.notifyDataSetChanged();
                        }
                    });
                    builder.setNegativeButton("Cancel", null);;
                    builder.show();
                    editText.requestFocus();
                    editText.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            InputMethodManager keyboard = (InputMethodManager)
                                    context.getSystemService(Context.INPUT_METHOD_SERVICE);
                            keyboard.showSoftInput(editText, 0);
                        }
                    },200);
                }
            });
        }
        container.addView(pageView);
        return pageView;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View)object);
    }

    @Override
    public int getCount() {
        int remainedItemCount = pagerItemList.size()%child_items_per_page;
        if(remainedItemCount == 0)
            return (pagerItemList.size()/child_items_per_page);
        else
            return (pagerItemList.size()/child_items_per_page + 1);
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }
}

public void clearChecks() {
    for(int i=0; i<checkedGroup.length; i++) checkedGroup[i] = false;
    for(List<ChildItemSample> value : listChild.values()) {
        for (ChildItemSample sample : value) {
            sample.setChecked(false);
        }
    }
    checkedBoxesCount = 0;
    notifyDataSetChanged();
}

public ArrayList<ChildItemSample> getOrderList(){
    ArrayList<ChildItemSample> overallOrder = new ArrayList<>();
    for(int i=0; i<getGroupCount(); i++){
        for(int j=0; j<listChild.get(getGroup(i)).size(); j++){
            if(getChild(i,j).getQty() > 0){
                ChildItemSample newOrder = new ChildItemSample(getGroup(i) + ">" +
                        getChild(i, j).getName(), getChild(i, j).getQty());
                overallOrder.add(newOrder);
            }
        }
    }
    return overallOrder;
}

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

private class GroupViewHolder {
    CheckBox cbGroup;
    TextView tvGroup;
}
}
查看更多
霸刀☆藐视天下
3楼-- · 2020-02-01 19:43

can you check this API https://developer.android.com/reference/android/widget/ExpandableListView

A view that shows items in a vertically scrolling two-level list

查看更多
登录 后发表回答