解决ListView的scrollListBy()方法不生效问题

如果开发同学的项目使用的布局是在ListView添加头部Item显示细分条目并且头布局中放置指示器的布局可能会出现这种问题,一旦你将ListView的的Select条目选中第一个就会出现指示器被遮挡的问题,当你满心欢喜找到ListView的scrollListBy()方法以为不用在你的Adapter中加入一个Type而使代码变得复杂时却发现调用这个方法之后不生效,WTF! 明明这个API是这样用的啊,不要着急,其实不是这个方法没用,而是因为在ListView没有布局完成时是不知道自己的位置的,此时调用scrollListBy()必然不生效,我们可以通过延时的方式来调用这个方法

mListView.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (mListView != null) {
                    mListView.scrollListBy(-height);
                }
            }
        }, 100);

但是用之后可能会发现在低版本上失效或者直接报错显示需要API19以上,大多数的应用是需要做向下兼容的,所以这个方法无法完全满足我们的需求,但是ListViwe的父类AbsListView提供一个trackMotionScroll()方法,这是一个private方法,但是我们可以通过反射调用,因为是AbsListView的方法所以我们不能反射ListView而是应该反射AbsListView,那么做判断,API19以上用现有方法,API19以下反射调用

//让listView下滑一定距离露出“全部评论  赞”的头部,免去在adapter中加入一个类型
    private void trackMotionScroll() {
        final int height = mDivAllCommentsAndPraise.getHeight();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            mListView.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                        if (mListView != null) {
                            mListView.scrollListBy(-height);
                        }
                    }
                }
            }, 100);
        } else {
            mListView.postDelayed(new Runnable() {
                @Override
                public void run() {
                    try {
                        if (mListView != null) {
                            ReflectUtil.invokeMethod(mListView, "trackMotionScroll", new Object[]{height, height}, new Class[]{int.class, int.class});
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }, 100);
        }
    }

这里是我的反射工具类

public class ReflectUtil {
    /**
     * 遍历当前类以及父类去查找并执行方法
     *
     * @param targetObject
     * @param methodName
     * @param params
     * @param paramTypes
     * @return
     */
    public static Object invokeMethod(Object targetObject, String methodName, Object[] params, Class[] paramTypes) {
        Object returnObj = null;
        if (targetObject == null || TextUtils.isEmpty(methodName)) {
            return null;
        }
        Class cls = targetObject.getClass();
        Method method = null;
        for (; cls != Object.class; cls = cls.getSuperclass()) {
            try {
                method = cls.getDeclaredMethod(methodName, paramTypes);
                break;
            } catch (Exception e) {
                return null;
            }
        }
        if (method != null) {
            method.setAccessible(true);
            try {
                returnObj = method.invoke(targetObject, params);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return returnObj;
    }
}

基本可以直接拿来用,将里面获取View高度的地方换成你想要滚动相当高度的View就可以了,负值是向下滚,正值是向上滚。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容