Android ExpandableListView:如何检测滚动条何时到达列表的底部/末端

Android ExpandableListView:如何检测滚动条何时到达列表的底部/末端,android,kotlin,expandablelistview,Android,Kotlin,Expandablelistview,我正在我的应用程序上实现一个ExpandableListView,我试图检测滚动条何时到达这个ExpandableListView的底部。我试过使用onScrollListener和onScrollChangedListener 对于onScrollListener,它被调用的次数太多,不可能是一个可接受的解决方案 然而,对于onScrollChangedListener,这似乎是我想要的。问题是,由于ExpandableListView没有1个子级别,只有2个子级别,因此我无法找到识别最后一个

我正在我的应用程序上实现一个ExpandableListView,我试图检测滚动条何时到达这个ExpandableListView的底部。我试过使用onScrollListener和onScrollChangedListener

对于onScrollListener,它被调用的次数太多,不可能是一个可接受的解决方案

然而,对于onScrollChangedListener,这似乎是我想要的。问题是,由于ExpandableListView没有1个子级别,只有2个子级别,因此我无法找到识别最后一个可见元素的方法

有人已经在ExpandableListView上实现了这种行为吗?

试试这个解决方案 -检查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();

        }
    }
});
试试这个解决方案 -检查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();

        }
    }
});

您可以通过在最后一个组展开时获取其位置来完成

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;
        }
    });

您可以通过在最后一个组展开时获取其位置来完成

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;
        }
    });
请尝试以下示例:-

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;
}
}
在这个示例中,我使用setTag来标识视图是组。如果对组视图和子视图使用不同的布局,则可以使用findViewById查找组视图内部的视图,从而在适配器中不进行任何更改

此外,在try catch中,您可以注释掉Toast并启用代码elvMain.expandGroupmainAdapter.getGroupCount-1;当列表滚动到底部时,它会自动展开最后一个组,因此ExpandableListView变得无穷无尽

希望有帮助

尝试以下示例:-

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;
}
}
在这个示例中,我使用setTag来标识视图是组。如果对组视图和子视图使用不同的布局,则可以使用findViewById查找组视图内部的视图,从而在适配器中不进行任何更改

此外,在try catch中,您可以注释掉Toast并启用代码elvMain.expandGroupmainAdapter.getGroupCount-1;当列表滚动到底部时,它会自动展开最后一个组,因此ExpandableListView变得无穷无尽


希望有帮助

最后,onScrollChangedListener不是我需要的。我需要一个只在用户抛出时触发的监听器,考虑到onScrollChangedListener是我能找到的ExpandableListView最精确的监听器,我认为onScrollChangedListener适合于此。你知道是否有可能把它放在一个可扩展的列表视图上吗?我正在试图理解你的问题。。。您需要侦听器才能访问可扩展listview的最后一条记录最后一条记录?我要做的是:当用户位于列表末尾时,在可扩展listview上加载更多数据。第一个问题是ExpandableListView有组和子级。我没有方法确定最后一个元素是封闭组还是扩展组的子元素。第二个问题是,由于onScrollListener和onScrollChangeListener的调用过于频繁,导致加载更多数据时调用过多。请以编程方式将一个子项添加到最后一个组的末尾。如果子项可见,则加载更多数据。。。可能是你的工作。如果你喜欢suggetion,让我知道,或者如果我不理解你的意思,你可以标记我的答案-1question@A.Danibo你尝试过我上面发布的解决方案吗?最后,onScrollChangedListener不是我需要的。我需要一个只在用户抛出时触发的监听器,考虑到onScrollChangedListener是我能找到的ExpandableListView最精确的监听器,我认为onScrollChangedListener适合于此。你知道是否有可能把它放在一个可扩展的列表视图上吗?我正在试图理解你的问题。。。您需要侦听器才能访问可扩展listview的最后一条记录最后一条记录?我要做的是:当用户位于列表末尾时,在可扩展listview上加载更多数据。第一个问题是ExpandableListView有组和子级。我没有方法确定最后一个元素是封闭组还是扩展组的子元素。第二个问题是,由于onScrollListener和onScrollChangeListener的调用过于频繁,导致加载更多数据时调用过多。请以编程方式将一个子项添加到最后一个组的末尾。如果子项可见,则加载更多数据。。。可能是你的工作。如果你喜欢suggetion,让我知道,或者如果我不理解你的意思,你可以标记我的答案-1question@A.Danibo你试过我上面贴的解决方案了吗?