简体   繁体   中英

Android ExpandableListView: how to detect when the scroll hits the bottom/end of list

I'm implementing an ExpandableListView on my app and I try to detect when the scroll hits the bottom of this ExpandableListView . I've tried using onScrollListener and onScrollChangedListener .

For the onScrollListener , it is called way too many times to be an acceptable solution.

However for the onScrollChangedListener , it seems to be what I want. The problem is that as ExpandableListView doesn't have 1 child level but 2, I don't manage to find a way to identify the last visible element.

Has anyone already implemented this kind of behaviour on an ExpandableListView ?

You can done via getting position of last group when it expand

expandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
        @Override
        public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
            if(groupPosition == expandableListView.getExpandableListAdapter().getGroupCount()){
            // your code goes here
            }
            return false;
        }
    });

Try below sample:-

activity_main.xml:

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

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

</LinearLayout>

MainActivity.java:

public class MainActivity extends AppCompatActivity {
ArrayList<String> mainGroupList;
HashMap<String, ArrayList<String>> mainChildList;
CustomAdapter mainAdapter;
ExpandableListView elvMain;
int newDataSet = 0;

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

    elvMain = findViewById(R.id.elvMain);
    mainGroupList = new ArrayList<>();
    mainChildList = new HashMap<>();
    for(int i = 0; i < 20; i++){
        ArrayList<String> tmpList = new ArrayList<>();
        for(int j = 0; j< 17; j++){
            tmpList.add("Child " + j);
        }
        mainChildList.put("Group " + i, tmpList);
        mainGroupList.add("Group " + i);
    }
    mainAdapter = new CustomAdapter(this, mainGroupList, mainChildList);
    elvMain.setAdapter(mainAdapter);

    elvMain.setOnScrollListener(new AbsListView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(AbsListView absListView, int i) {}
        @Override
        public void onScroll(AbsListView absListView, int i, int i1, int i2) {
            if(i2 == i + i1){
                View lastView = absListView.getChildAt(i1 - 1);
                if(lastView.getBottom() == absListView.getBottom()){
                    try{
                        String viewTag = lastView.getTag().toString();
                        if(viewTag.equals("Group")){
                            Toast.makeText(getApplicationContext(),
                                    "No more data, unless expanded the last group!!",
                                    Toast.LENGTH_SHORT).show();
                            //elvMain.expandGroup(mainAdapter.getGroupCount() - 1);
                        }
                    }catch(Exception e){
                        addNewData();
                    }
                }
            }
        }
    });
}

private void addNewData(){
    newDataSet++;
    for(int i = 0; i < 5; i++){
        ArrayList<String> tmpList = new ArrayList<>();
        for(int j = 0; j< 7; j++){
            tmpList.add("Child " + j);
        }
        mainChildList.put("Added " + newDataSet + ",Group " + i, tmpList);
        mainGroupList.add("Added " + newDataSet + ",Group " + i);
    }
    mainAdapter.notifyDataSetChanged();
}
}

CustomAdapter.java:

public class CustomAdapter extends BaseExpandableListAdapter {
ArrayList<String> groupList;
HashMap<String, ArrayList<String>> childList;
LayoutInflater inflater;

public CustomAdapter(Context context, ArrayList<String> groupList, HashMap<String, ArrayList<String>> childList) {
    this.inflater = LayoutInflater.from(context);
    this.groupList = groupList;
    this.childList = childList;
}

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

@Override
public int getChildrenCount(int i) {
    return childList.get(groupList.get(i)).size();
}

@Override
public String getGroup(int i) {
    return groupList.get(i);
}

@Override
public String getChild(int i, int i1) {
    return childList.get(groupList.get(i)).get(i1);
}

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

@Override
public long getChildId(int i, int i1) {
    return 0;
}

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

@Override
public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) {
    if(view == null) view = inflater.inflate(android.R.layout.simple_list_item_1, null);
    TextView textView = view.findViewById(android.R.id.text1);
    textView.setText(getGroup(i));
    view.setTag("Group");
    return view;
}

@Override
public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewGroup) {
    if(view == null) view = inflater.inflate(android.R.layout.simple_list_item_1, null);
    TextView textView = view.findViewById(android.R.id.text1);
    textView.setText(getChild(i, i1));
    return view;
}

@Override
public boolean isChildSelectable(int i, int i1) {
    return false;
}
}

In this sample, I use setTag() to identify the view is "Group". If you use different layouts for group view and child view, then you may use findViewById() to find a view that is inside the group view and so no changes in your adapter.

In addition, inside the try-catch, you can comment out the Toast() and enable the code elvMain.expandGroup(mainAdapter.getGroupCount() - 1); which automatically expand the last group when the list is scrolled to the bottom, so the ExpandableListView becomes endless.

Hope that helps!

try this solution Detect when RecyclerView reaches the bottom most position while scrolling - check answer of Kaustubh Bhagwat

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);

        if (!recyclerView.canScrollVertically(1)) {
            Toast.makeText(YourActivity.this, "Last", Toast.LENGTH_LONG).show();

        }
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM