带有自定义网格布局的可扩展ListView

时间:2018-08-13 07:43:02

标签: android android-recyclerview

我观看了来自此link的教程,该教程创建了可扩展的recyclerview,而没有使用第三方应用程序来扩展recyclerview并在其中填充自定义网格布局。

下面是使用的代码:

MainActivity

public class MainActivity extends AppCompatActivity {

RecyclerView expanderRecyclerView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    expanderRecyclerView = findViewById(R.id.recyclerView);

    initiateExpander();

}


private void initiateExpander() {

    ArrayList<String> parentList = new ArrayList<>();
    ArrayList<ArrayList> childListHolder = new ArrayList<>();

    parentList.add("Fruits & Vegetables");
    parentList.add("Beverages & Health");
    parentList.add("Home & Kitchen");

    ArrayList<String> childNameList = new ArrayList<>();
    childNameList.add("Apple");
    childNameList.add("Mango");
    childNameList.add("Banana");

    childListHolder.add(childNameList);

    childNameList = new ArrayList<>();
    childNameList.add("Red bull");
    childNameList.add("Maa");
    childNameList.add("Horlicks");

    childListHolder.add(childNameList);

    childNameList = new ArrayList<>();
    childNameList.add("Knife");
    childNameList.add("Vessels");
    childNameList.add("Spoons");

    childListHolder.add(childNameList);

    ExpandableRecyclerViewAdapter expandableCategoryRecyclerViewAdapter =
            new ExpandableRecyclerViewAdapter(getApplicationContext(), parentList,
                    childListHolder);

    expanderRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));

    expanderRecyclerView.setAdapter(expandableCategoryRecyclerViewAdapter);
}

}  

ExpandableRecyclerViewAdapter

public class ExpandableRecyclerViewAdapter extends 
RecyclerView.Adapter<ExpandableRecyclerViewAdapter.ViewHolder> {

int previousExpandedPosition = -1, mExpandedPosition=-1;
ArrayList<String> nameList = new ArrayList<String>();
ArrayList<String> image = new ArrayList<String>();
ArrayList<Integer> counter = new ArrayList<Integer>();
ArrayList<ArrayList> itemNameList = new ArrayList<ArrayList>();
boolean isExpanded=true;
Context context;

public ExpandableRecyclerViewAdapter(Context context,
                                     ArrayList<String> nameList,
                                     ArrayList<ArrayList> itemNameList) {
    this.nameList = nameList;
    this.itemNameList = itemNameList;
    this.context = context;
    Log.d("namelist", nameList.toString());
    for (int i = 0; i < nameList.size(); i++) {
        counter.add(0);
    }

}

public class ViewHolder extends RecyclerView.ViewHolder {
    TextView name;
    ImageButton dropBtn;
    RecyclerView cardRecyclerView;
    CardView cardView;

    public ViewHolder(View itemView) {
        super(itemView);
        name = itemView.findViewById(R.id.categoryTitle);
        dropBtn = itemView.findViewById(R.id.categoryExpandBtn);
        cardRecyclerView = itemView.findViewById(R.id.innerRecyclerView);
        cardView = itemView.findViewById(R.id.cardView);
    }
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.card_collapseview, parent, false);
    ExpandableRecyclerViewAdapter.ViewHolder vh = new ExpandableRecyclerViewAdapter.ViewHolder(v);
    return vh;

}

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
    holder.name.setText(nameList.get(position));
    InnerRecyclerViewAdapter itemInnerRecyclerView = new InnerRecyclerViewAdapter(context ,itemNameList.get(position));
    holder.cardRecyclerView.setLayoutManager(new GridLayoutManager(context, 2));
    holder.cardView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (counter.get(position) % 2 == 0) {
                holder.cardRecyclerView.setVisibility(View.VISIBLE);
            } else {
                holder.cardRecyclerView.setVisibility(View.GONE);
            }
            counter.set(position, counter.get(position) + 1);
        }
    });
    holder.cardRecyclerView.setAdapter(itemInnerRecyclerView);
}

@Override
public int getItemCount() {
    return nameList.size();
}
}

InnerRecyclerViewAdapter

public class InnerRecyclerViewAdapter extends 
RecyclerView.Adapter<InnerRecyclerViewAdapter.ViewHolder> {
public ArrayList<String> nameList = new ArrayList<String>();
Context context;

public InnerRecyclerViewAdapter(Context context, ArrayList<String> nameList) 
{
    this.nameList = nameList;
    this.context=context;
}

public class ViewHolder extends RecyclerView.ViewHolder {
    TextView name;
    CardView cardView;

    public ViewHolder(View itemView) {
        super(itemView);
        name = itemView.findViewById(R.id.itemTextView);
        cardView=itemView.findViewById(R.id.cardView);
    }
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.card_expand_item_view, parent, false);
    InnerRecyclerViewAdapter.ViewHolder vh = new InnerRecyclerViewAdapter.ViewHolder(v);
    return vh;
}

@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
    holder.name.setText(nameList.get(position));
    holder.cardView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Toast.makeText(context, "Clicked on "+nameList.get(position),Toast.LENGTH_LONG).show();
        }
    });
}

@Override
public int getItemCount() {
    return nameList.size();
}
}

我无法弄清楚如何修改此代码,以使recyclerview一次扩展一行...如果已经扩展了另一行,则应在另一行扩展时自动将其关闭行。

请指导我该怎么做。

1 个答案:

答案 0 :(得分:1)

所以我自己找到了使用自定义recyclerview进行扩展的gridlayout的答案。
实际上,我按照@ADM的建议删除了recyclerview并使用了ExpandableListView
还使用gridlayout在子级布局中添加了自定义recyclerview,一次只能打开一个子级。

如果有人需要,我将在下面发布代码...

MainActivity

public class MainActivity extends AppCompatActivity {
private static ExpandableListView expandableListView;
private static ExpandableListAdapter adapter;

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

    expandableListView = (ExpandableListView) findViewById(R.id.simple_expandable_listview);

    // Setting group indicator null for custom indicator
    expandableListView.setGroupIndicator(null);

    setItems();
    setListener();

}

// Setting headers and childs to expandable listview
void setItems() {

    // Array list for header
    ArrayList<String> header = new ArrayList<String>();

    // Array list for child items
    List<String> child1 = new ArrayList<String>();
    List<String> child2 = new ArrayList<String>();
    List<String> child3 = new ArrayList<String>();
    List<String> child4 = new ArrayList<String>();

    // Hash map for both header and child
    HashMap<String, List<String>> hashMap = new HashMap<String, List<String>>();

    // Adding headers to list
    for (int i = 1; i < 5; i++) {
        header.add("Group " + i);

    }
    // Adding child data
    for (int i = 1; i < 5; i++) {
        child1.add("Group 1  - " + " : Child" + i);

    }
    // Adding child data
    for (int i = 1; i < 5; i++) {
        child2.add("Group 2  - " + " : Child" + i);

    }
    // Adding child data
    for (int i = 1; i < 6; i++) {
        child3.add("Group 3  - " + " : Child" + i);

    }
    // Adding child data
    for (int i = 1; i < 7; i++) {
        child4.add("Group 4  - " + " : Child" + i);

    }

    // Adding header and childs to hash map
    hashMap.put(header.get(0), child1);
    hashMap.put(header.get(1), child2);
    hashMap.put(header.get(2), child3);
    hashMap.put(header.get(3), child4);

    adapter = new ExpandableListAdapter(MainActivity.this, header, hashMap);

    // Setting adpater over expandablelistview
    expandableListView.setAdapter(adapter);
}

// Setting different listeners to expandablelistview
void setListener() {

    // This listener will show toast on group click
    expandableListView.setOnGroupClickListener(new OnGroupClickListener() {

        @Override
        public boolean onGroupClick(ExpandableListView listview, View view,
                int group_pos, long id) {

            Toast.makeText(MainActivity.this,
                    "You clicked : " + adapter.getGroup(group_pos),
                    Toast.LENGTH_SHORT).show();
            return false;
        }
    });

    // This listener will expand one group at one time
    // You can remove this listener for expanding all groups
    expandableListView
            .setOnGroupExpandListener(new OnGroupExpandListener() {

                // Default position
                int previousGroup = -1;

                @Override
                public void onGroupExpand(int groupPosition) {
                    if (groupPosition != previousGroup)

                        // Collapse the expanded group
                        expandableListView.collapseGroup(previousGroup);
                    previousGroup = groupPosition;
                }

            });

    // This listener will show toast on child click
    expandableListView.setOnChildClickListener(new OnChildClickListener() {

        @Override
        public boolean onChildClick(ExpandableListView listview, View view,
                int groupPos, int childPos, long id) {
            Toast.makeText(
                    MainActivity.this,
                    "You clicked : " + adapter.getChild(groupPos, childPos),
                    Toast.LENGTH_SHORT).show();
            return false;
        }
    });
}
}

ExpandableListAdapter

//For expandable list view use BaseExpandableListAdapter
public class ExpandableListAdapter extends BaseExpandableListAdapter {
private Context _context;
private List<String> header; // header titles
RecyclerView recyclerView;
// Child data in format of header title, child title
private HashMap<String, List<String>> child;

public ExpandableListAdapter(Context context, List<String> listDataHeader,
        HashMap<String, List<String>> listChildData) {
    this._context = context;
    this.header = listDataHeader;
    this.child = listChildData;
}

@Override
public Object getChild(int groupPosition, int childPosititon) {

    // This will return the child
    return this.child.get(this.header.get(groupPosition)).get(
            childPosititon);
}

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

@Override
public View getChildView(int groupPosition, final int childPosition,
        boolean isLastChild, View convertView, ViewGroup parent) {
    View v=convertView;
    if (v == null) {
        v = LayoutInflater.from(parent.getContext()).inflate(R.layout.childs, parent, 
false);
        String groupname=header.get(groupPosition);
        recyclerView = (RecyclerView) v.findViewById(R.id.recyclerview);
        InnerRecyclerViewAdapter sbc=new InnerRecyclerViewAdapter(_context, 
child,groupPosition,groupname);
        recyclerView.setLayoutManager(new GridLayoutManager(_context,2));
        recyclerView.setAdapter(sbc);
    }else
    {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.childs,parent,false);
        String groupname=header.get(groupPosition);
        recyclerView = (RecyclerView) v.findViewById(R.id.recyclerview);
        InnerRecyclerViewAdapter sbc=new InnerRecyclerViewAdapter(_context, 
child,groupPosition,groupname);
        recyclerView.setLayoutManager(new GridLayoutManager(_context,2));
        recyclerView.setAdapter(sbc);

    }

    return v;
}

@Override
public int getChildrenCount(int groupPosition) {

    // return children count
    return 1;
}

@Override
public Object getGroup(int groupPosition) {

    // Get header position
    return this.header.get(groupPosition);
}

@Override
public int getGroupCount() {

    // Get header size
    return this.header.size();
}

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

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

    // Getting header title
    String headerTitle = (String) getGroup(groupPosition);

    // Inflating header layout and setting text
    if (convertView == null) {
        LayoutInflater infalInflater = (LayoutInflater) this._context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = infalInflater.inflate(R.layout.header, parent, false);
    }

    TextView header_text = (TextView) convertView.findViewById(R.id.header);

    header_text.setText(headerTitle);

    // If group is expanded then change the text into bold and change the
    // icon
    if (isExpanded) {
        header_text.setTypeface(null, Typeface.BOLD);
        header_text.setCompoundDrawablesWithIntrinsicBounds(0, 0,
                R.drawable.ic_up, 0);
    } else {
        // If group is not expanded then change the text back into normal
        // and change the icon

        header_text.setTypeface(null, Typeface.NORMAL);
        header_text.setCompoundDrawablesWithIntrinsicBounds(0, 0,
                R.drawable.ic_down, 0);
    }

    return convertView;
}

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

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

InnerRecyclerViewAdapter

public class InnerRecyclerViewAdapter extends RecyclerView.Adapter<InnerRecyclerViewAdapter.ViewHolder> {
private HashMap<String, List<String>> child;
Context context;
int groupPosition;
String groupname;

public InnerRecyclerViewAdapter(Context context, HashMap<String, List<String>> child,int groupPosition,String groupname) {
    this.child = child;
    this.context=context;
    this.groupPosition=groupPosition;
    this.groupname=groupname;
}

public class ViewHolder extends RecyclerView.ViewHolder {
    TextView name;
    CardView cardView;

    public ViewHolder(View itemView) {
        super(itemView);
        name = itemView.findViewById(R.id.itemTextView);
        cardView=itemView.findViewById(R.id.cardView);
    }
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.card_expand_item_view, parent, false);
    InnerRecyclerViewAdapter.ViewHolder vh = new InnerRecyclerViewAdapter.ViewHolder(v);
    return vh;
}

@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
    final String childText = (String) getChild(groupPosition,position);
    holder.name.setText(childText);
    holder.cardView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Toast.makeText(context, "Clicked on "+childText, Toast.LENGTH_LONG).show();
        }
    });
}

@Override
public int getItemCount() {
    return child.size();
}

public Object getChild(int groupPosition, int childPosititon) {

    // This will return the child
    return this.child.get(groupname).get(
            childPosititon);
}
}

XML如下:

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:padding="5dp" >

    <ExpandableListView
        android:id="@+id/simple_expandable_listview"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:divider="#000000"
        android:dividerHeight="1dp" >
    </ExpandableListView>

</LinearLayout>  

card_expand_item_view.xml

<?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.support.v7.widget.CardView
        android:id="@+id/cardView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="2dp">


        <LinearLayout
            android:id="@+id/linearLayoutHolder"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="10dp">


            <TextView
                android:id="@+id/itemTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginTop="5dp"
                android:text="Fresh Fruits"
                android:textAlignment="center"
                android:textSize="14sp" />


        </LinearLayout>

    </android.support.v7.widget.CardView>


</RelativeLayout>  

childs.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/rv1"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="5dp"
        android:scrollbars="vertical"/>

</RelativeLayout>

header.xml

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

    <TextView
        android:id="@+id/header"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dp"
        android:textColor="#ff00"
        android:drawablePadding="10dp"
        android:textSize="18sp" />

</LinearLayout>

使用此命令后的输出将类似于this