【问题标题】:keeping bottom element of ListView visible when keyboard appears出现键盘时保持 ListView 的底部元素可见
【发布时间】:2011-11-29 00:22:56
【问题描述】:

我有一个LinearLayout,其中包含一个ListView 和一个EditText。当通过触摸EditText 启动屏幕键盘时,ListView 会调整大小,以便仅显示顶部的几个元素。

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

(顺便说一句,我正在使用的当前修复涉及使用smoothScrollToPosition,但滞后的滚动行为使得这不受欢迎)

【问题讨论】:

标签: android android-layout android-listview


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    您可以使用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();
                    }
                }
            });
        }
    });
    

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

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 不,这不能解决问题——窗口已经设置为adjustResize模式;这是 ListView 的调整大小行为不符合预期。
      猜你喜欢
      • 2018-06-27
      • 2019-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-14
      • 1970-01-01
      • 2021-12-06
      相关资源
      最近更新 更多