当键盘出现时,保持ListView底部元素可见

5
我有一个包含ListViewEditTextLinearLayout。当通过触摸EditText启动屏幕键盘时,ListView会调整大小以便仅保留顶部几个元素可见。
在上下文中,ListView用于底部几个元素比顶部更加重要,因此我希望它调整大小以便底部保持可见,而不是顶部。有什么建议吗?
(顺便说一句,我目前使用的解决方法涉及使用smoothScrollToPosition,但滚动行为的延迟使这种方法不理想)

尝试使用以下链接解决问题: https://dev59.com/dWQo5IYBdhLWcg3wVuKPhttps://dev59.com/Pmox5IYBdhLWcg3wNRxj - MSaudi
3个回答

1
我今早刚解决了一个类似的问题,想在这里发布我的结果以供未来的搜索者受益。我的问题是滚动到底部没有帮助,因为我在视图实际改变大小之前调用它。解决方案?使用GlobalLayoutListener等待其改变大小。
步骤: 1)在持有listview的activity中实现以下方法
public void scrollToBottom(){
    //I think this is supposed to run on the UI thread
    listView.setSelection(mAdapter.getCount() - 1);
}

创建以下类:
public class OnGlobalLayoutListenerWithScrollToBottom implements OnGlobalLayoutListener{

    private boolean scroll;
    private OnScrollToBottomListener listener;
    public interface OnScrollToBottomListener{
        public void scrollToBottom();
    }

    public OnGlobalLayoutListenerWithScrollToBottom(OnScrollToBottomListener listener){
        this.listener = listener;
    }

    @Override
    public void onGlobalLayout() {
        if(scroll){
            listener.scrollToBottom();
            scroll = false;
        }
    }

    /**
     * Lets the listener know to request a scroll to bottom the next time it is layed out
     */
    public void scrollToBottomAtNextOpportunity(){
        scroll = true;
    }

};

3)在您的活动中,实现来自此类的接口。然后,在您的活动中创建此OnGlobalLayoutListener的实例,并将其设置为listView的侦听器

    //make sure your class implements OnGlobalLayoutListenerWithScrollToBottom.OnScrollToBottomListener
    listViewLayoutListener = new OnGlobalLayoutListenerWithScrollToBottom(this);
    listView.getViewTreeObserver().addOnGlobalLayoutListener(listViewLayoutListener);

4) 在您的活动中,在进行会影响列表视图大小的更改之前,例如显示和隐藏其他视图或将内容添加到列表视图中,请简单地让布局监听器知道在下一个机会滚动。

listViewLayoutListener.scrollToBottomAtNextOpportunity();

0

您可以通过 setSelectionFromTop() 和在自定义列表视图中覆盖 onSizeChanged() 来实现此目的。在您的布局中,您应该有一个 RelativeLayout 作为父容器,并将列表视图放置在编辑文本框上方。

通过创建自己的列表视图并覆盖 onSizeChange(),您将能够在列表视图调整大小之前获取最后可见项的位置并获取其新高度,以便最终使用其高度的偏移量设置列表的“前一个”位置。

工作原理:您的列表将把前一个最后可见项放在其顶部,并将像素添加到其底部以滚动到其上方,就在您的编辑文本框上方。

要覆盖该方法并带有偏移量显示它,请按以下步骤操作:

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    // get last visible item's position before resizing
    int lastPosition = super.getLastVisiblePosition();
    // call the super method to resize the listview
    super.onSizeChanged(w, h, oldw, oldh);
    // after resizing, show the last visible item at the bottom of new listview's height
    super.setSelectionFromTop(lastPosition, (h - lastItemHeight));
}

lastItemHeight 是一个小技巧,因为我没有找到在 onSizeChanged 被调用之前如何获取最后一个项目的高度。然后,在您的列表视图包含许多类型的项目(高度不同)的情况下,我更喜欢在事件发生时,在软键盘打开之前获取所选高度。

因此,在自定义列表视图中,您有这个全局变量:

int lastItemHeight = 0;

在活动(或片段,无论哪个)中,您可以在OnClickListener中更新此值:

edittext.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // set a new Thread
        listview.post(new Runnable() {
            @Override
            public void run() {
                // get last visible position of items
                int lastPosition = listview.getLastVisiblePosition() - 1;
                // if the view's last child can be retrieved
                if ( listview.getChildAt(lastPosition) != null ) {
                    // update the height of the last child in custom listview
                    listview.lastItemHeight = listview.getChildAt(lastPosition).getHeight();
                }
            }
        });
    }
});

注意:还有另一种可能的解决方案,但是您必须在ListView上设置android:stackFromBottom="true",它会将内容从底部堆叠起来。与此不同的是,这里的解决方案可以显示特定的项目,而不强制内容从底部开始,遵循默认的ListView行为。
第二个注意事项:(以防万一)不要忘记在清单文件中添加android:windowSoftInputMode="adjustResize"

-1

你应该在清单文件中为你的活动添加这个属性,并选择正确的值(可能会选择“adjustResize”):

<activity android:name="package.yourActivity" android:windowSoftInputMode="adjustResize"/>

不,这并不能解决问题——窗口已经设置为adjustResize模式;问题在于ListView的调整大小行为不符合预期。 - chrisjrn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接