当ListView的大小发生更改时,保持ListView的最后一个可见项

我想要的很简单,至less我认为这很简单。 我只想要一个窗口的EditText在屏幕的底部,其余的空间填充ListView。 不幸的是,它没有像我预期的那样工作。 我想要的是以下图像。 有没有简单的方法来在XML中做到这一点,或者我应该写一些特殊的代码呢? 我想要的是

我有问题的Android源代码。

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="fill_parent" android:orientation="vertical" > <ListView android:id="@+id/demolist" android:layout_width="match_parent" android:layout_height="fill_parent" android:layout_weight="1" > </ListView> <EditText android:id="@+id/editText1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0"> </EditText> </LinearLayout > 

Solutions Collecting From Web of "当ListView的大小发生更改时,保持ListView的最后一个可见项"

你想要什么

最后一个可见项目没有键盘

最后一个可见项目没有键盘

最后一个可见的项目与键盘

最后一个可见的项目与键盘

最后一个可见项目input较大

最后一个可见项目输入较大

这是我如何做到的。

概要

  • 在列表视图中设置android:stackFromBottom =“true”android:transcriptMode =“alwaysScroll”
  • 在Activity中设置android:windowSoftInputMode =“adjustPan”
  • 调用adapter.notifyDataSetChanged(); 当你添加新的聊天,以便列表视图将始终滚动到最后的位置
  • 在EditText中设置android:inputType =“textMultiLine”android:maxLines =“4”

细节

活动

 <activity android:name="MainActivity" android:screenOrientation="portrait" android:windowSoftInputMode="adjustPan"></activity> 

聊天视图

 <RelativeLayout android:id="@+id/chat_header" android:layout_width="fill_parent" android:layout_height="40dp" android:padding="3dp" > <Button android:id="@+id/btnBackChat" android:layout_width="35dp" android:layout_height="35dp" android:layout_alignParentLeft="true" android:background="@drawable/back_button" /> <TextView android:id="@+id/txt_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/btnBackChat" android:layout_centerHorizontal="true" android:textColor="@android:color/white" android:textSize="18sp" /> <ImageView android:id="@+id/imgViewProfileChat" android:layout_width="35dp" android:layout_height="35dp" android:layout_alignParentRight="true" /> </RelativeLayout> <ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_above="@+id/form" android:layout_below="@+id/chat_header" android:stackFromBottom="true" android:transcriptMode="alwaysScroll"/> <RelativeLayout android:id="@+id/form" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:orientation="vertical" > <ImageButton android:id="@+id/btnAttach" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:contentDescription="@string/attach" android:src="@drawable/attach_icon" /> <EditText android:id="@+id/txtChat" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_toLeftOf="@+id/btnSend" android:layout_toRightOf="@+id/btnAttach" android:inputType="textMultiLine" android:maxLines="4" /> <Button android:id="@+id/btnSend" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:text="@string/send" /> </RelativeLayout> 

我想你可能想在显示键盘之前使用AdapterView.getLastVisiblePosition() 。

两个解决scheme:

  • 点击EditText
  • 感谢一个OnScrollListener(及其onScroll函数)监听你的ListView

然后使用AdapterView.setSelection在EditText焦点之后跳转到此项(或索引-2或索引-3)。

您可以在AndroidManifest.xml中使用android:windowSoftInputMode="adjustPan" ,如下所示

  <activity android:name="com.example.SimpleListView" android:label="@string/app_name" android:windowSoftInputMode="adjustPan" > 

这应该会产生你想要的输出。 官方的android文档 。

如果您想自动滚动到列表视图的末尾,您可以select指定抄录模式(如果您正在处理某些聊天function)列表视图。 你也可以检查android:transcriptMode="normal" ,看看是否合适。

一个相关的答案 。 官方安卓文档 。

 <ListView android:id="@+id/comments" android:layout_width="match_parent" android:layout_height="match_parent" android:transcriptMode="alwaysScroll"> 

这应该解决你的大部分问题,也许除了最后一个(在图像中),我还没有testing。

只需重写ListView#onSizeChanged(int w,int h,int oldw,int oldh)的方法如下:PS:您的ListView的高度不能为0,如果它可能为0,则不起作用。

 @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { if (getChildCount() == 0) { return; } final int lastVisiblePosition = getLastVisiblePosition(); int firstVisiblePosition = getFirstVisiblePosition(); View last = getChildAt(lastVisiblePosition - firstVisiblePosition); int top = last.getTop(); final int newTop = top + (h - oldh); Log.d(getClass().getSimpleName(), "onSizeChanged(" + w + ", " + h + ", " + oldw + ", " + oldh + ")"); if (mFocusSelector == null) { mFocusSelector = new FocusSelector(); } post(mFocusSelector.setup(lastVisiblePosition, newTop)); super.onSizeChanged(w, h, oldw, oldh); } private class FocusSelector implements Runnable { private int mPosition; private int mPositionTop; public FocusSelector setup(int position, int top) { mPosition = position; mPositionTop = top; return this; } public void run() { setSelectionFromTop(mPosition, mPositionTop); } } 

我实际上得到了相同的行为,你需要通过添加到清单android:windowSoftInputMode="adjustResize" Activity声明android:windowSoftInputMode="adjustResize"ListView声明android:transcriptMode="normal" 。 用于键盘和方向更改。

我也需要这个function。 这是我的尝试,但它不工作 – 滚动是有点不稳定(并不总是结束它应该),它会干扰旋转屏幕时保持滚动位置。

 @Override public void onResume() { super.onResume(); getListView().addOnLayoutChangeListener(stickyLastItemHandler); } @Override public void onPause() { super.onPause(); getListView().removeOnLayoutChangeListener(stickyLastItemHandler); } View.OnLayoutChangeListener stickyLastItemHandler = new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { final int heightChange = (bottom - top) - (oldBottom - oldTop); if (heightChange != 0) { ((AbsListView)v).smoothScrollBy(-heightChange, 1000); } } }; 

你可以通过xml来完成:

 <ListView android:stackFromBottom="true" android:layout_height=0dp android:layout_weight=1 /> 

从底部堆叠将保持ListView向下滚动默认情况下,设置ListView的权重将填充垂直LinearLayout的父母的所有可能的空间。

我为Android创build了一个布局引擎,允许您监听键盘隐藏和可见的状态变化(以及许多其他核心function)。 这个库可在http://phil-brown.github.io/AbLE/获&#x5F97; 。

只需将jar添加到libs目录(如果该目录不存在,则创build该文件夹),而不是从Activityinheritance, AbLEActivityAbLEActivityinheritance。 接下来,覆盖onKeyboardShownonKeyboardHidden方法,在这些方法中,您可以根据需要向上或向下设置内容视图的animation效果:

 @Override public void onKeyboardShown() { //animate up } @Override public void onKeyboardHidden() { //animate down } 

只是检查了这一点:希望这会帮助你….

假设您知道列表数据何时发生变化,您可以通过将列表select设置为最后一行来手动指示列表滚动到底部。 像这样的东西:

 private void scrollMyListViewToBottom() { myListView.post(new Runnable() { @Override public void run() { // Select the last row so it will scroll into view... myListView.setSelection(myListAdapter.getCount() - 1) ; } }); } 

或者你也可以尝试这个..它适用于我:

 ChatAdapter adapter = new ChatAdapter(this); ListView lview = (ListView) findViewById(R.id.chatList); lview .setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL); lview .setAdapter(adapter); adapter.registerDataSetObserver(new DataSetObserver() { @Override public void onChanged() { super.onChanged(); lv.setSelection(adapter.getCount() - 1); } }); 
 Follow these steps -------------------- 1. Update your activity in AndroidManifest.xml file like below <activity android:name=".MyListActivity" android:windowSoftInputMode="adjustResize" /> 2. Set your list view with like below. mListView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL); mListView.setStackFromBottom(true); 

我希望它能解决你的问题。

在你的ListAdapter中,你可以做这样的事情:

  public View getView(int position, View convertView, ViewGroup parent) { //buttonMore if( position >= super.getCount() ) return textField ; .... 

这样,您将始终将列表中的最后一项作为文本框。

你需要设置select的位置…但是 – 以一种奇怪的方式,我不明白为什么 – 你需要用post()

 public void ScrollToLast() { yourList.clearFocus(); yourList.post(new Runnable() { @Override public void run() { yourList.setSelection(items.size() - 1); } }); } 

所以你可以为你的editText添加一个TextWatcher,你可以在这里调用这个方法…所以你的列表将滚动到底部。