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

时间:2011-11-29 00:22:56

标签: android android-layout android-listview

我的LinearLayout包含ListViewEditText。通过触摸EditText启动屏幕键盘时,ListView会调整大小,以便只有前几个元素保持可见。

正在使用ListView的上下文中,底部的几个元素在视觉上比顶部更具有相关性,因此我希望它能够调整大小以使底部保持可见,而不是顶部。有什么指针吗?

(顺便说一句,我正在使用的当前修复程序涉及使用smoothScrollToPosition,但是延迟滚动行为会导致这种情况不受欢迎)

3 个答案:

答案 0 :(得分:1)

我今天早上刚刚解决了类似的问题,并认为我会在此发布我的结果,以便将来的搜索者受益。我的问题是滚动到底部并没有帮助,因为我在视图实际改变大小之前调用它。解决方案?等到它确实使用GlobalLayoutListener

更改大小

步骤: 1)在持有listview的活动中实现以下方法

public void scrollToBottom(){
    //I think this is supposed to run on the UI thread
    listView.setSelection(mAdapter.getCount() - 1);
}

2)创建以下类

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

答案 1 :(得分:0)

您可以使用setSelectionFromTop()并在自定义列表视图中覆盖onSizeChanged()来实现此目的。在您的布局中,您应该让RelativeLayout具有父容器,并将listview放在edittext上方。

通过创建自己的列表视图并覆盖onSizeChange(),您可以在列表视图大小调整之前获取最后一个可见项目的位置并获得其新高度,以便最终设置&#34 ;以前"列表的位置,其高度偏移。

工作原理:您的列表会将上一个最后一个可见项置于其顶部,您将添加像素以在其底部(位于编辑文本上方)滚动它。

要覆盖方法并使用偏移显示它,请执行以下操作:

@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之前获得最后一个项目的高度。然后,如果你的listview包含许多类型的项目(没有相同的高度),我更喜欢在事件发生时,就在SoftKeyboard打开之前获得所选的高度。

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

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

注意:there is another possible solution但您必须在列表视图中设置android:stackFromBottom="true",它会从底部堆叠其内容。相反,此解决方案可以显示特定项目,而不会强制内容从底部开始,具有默认列表视图的行为。

第二个注意事项:(以防万一)不要忘记在清单中添加android:windowSoftInputMode="adjustResize"

答案 2 :(得分:-1)

您应该在活动的清单中添加此属性并为其选择正确的值(可能您会选择“adjustResize”):

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