我建立一个聊天-喜欢安卓应用程序,类似于去处。为此目的,我使用一个垂直列表视图用 stackFromBottom=truetranscriptMode="normal".

该名单是排序,从旧的消息(上),年轻的信息(下)。在正常状态,列表视图是滚到底层,表示最年轻的信息。

列表视图利用反向无穷无尽的-滚动器装载更多(老年)的消息,一旦使用者滚动名单的.一旦老的邮件加载,他们加到名单。

所需的行为是列表视图保持其滚动位于名单的底部,当旧的消息都加入到它的顶部。也就是说,当旧的消息被添加到顶峰,滚动图应显示同样的消息显示之前,加入老年的消息。

不幸的是,这不起作用。而不是保持滚动位置的底部, 列表视图维护的滚动位置,列表的顶部.也就是说,在加入老年的邮件列表,列表显示了最顶部(i。e最古老的)的消息。

是有一个简单的方法来告诉列表视图保持其滚动位于底部,而不是顶,当添加的新项目的顶级的?

更新

为了示范的目的,我已经尽量减少使用情况和代码尽可能多的。以下的示例创建一个简单的字符串阵列表。点击一个项目将增加的另一个顶部的项目清单。长击的一个项目将增加的另一个项目在底部的名单。

一切正常工作时增加的项目名单的底部(长点击)。当添加项目的顶部列出(简单),随后有3种情况:

  • 如果该名单滚动到底,然后一切工作正常。在添加该项目的顶端,该名单仍然是滚到底层。
  • 如果名单不是滚到底层(也不顶端),则列表中将保持其动y位置(自上)。这使得名单中出现的"跳跃"的一个项目。我想名单不以"跳跃",在这种情况下,我.电子我想它来维持其滚动-y位从底部。
  • 如果名单滚动的顶端,那么同样发生在2的情况。优选的行为是相同的情况下2.

(过去的2情况下,实际上是相同的。我把他们分开,因为这个问题可以更好地表明在2的情况。)

代码

public class MyListActivity extends Activity {
  int topIndex = 1;

  int bottomIndex = 20;

  protected final void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.my_list_activity);

    final ListView list = (ListView) findViewById(R.id.list);
    list.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);
    list.setStackFromBottom(true);

    final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1);
    for (int i = topIndex; i <= bottomIndex; i++) {
      adapter.add(Integer.toString(i));
    }
    list.setAdapter(adapter);

    list.setOnItemClickListener(new OnItemClickListener() {
      @Override
      public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        adapter.insert(Integer.toString(--topIndex), 0);
      }
    });

    list.setOnItemLongClickListener(new OnItemLongClickListener() {
      @Override
      public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        adapter.add(Integer.toString(++bottomIndex));
        return true;
      }
    });
  }
}
有帮助吗?

解决方案

我已经找到了这一点。无论它是,你正在获取新数据,我所说的以下的前不断变化的数据在适配器:

int firstVisibleItem = list.getFirstVisiblePosition();
int oldCount = adapter.getCount();
View view = list.getChildAt(0);
int pos = (view == null ? 0 :  view.getBottom());

然后,我呼吁:

adapter.setData(data);

list.setSelectionFromTop(firstVisibleItem + adapter.getCount() - oldCount + 1, pos);

其他提示

第一,得到firstVisiblePosition(或最后一个,因为其上下颠倒。哟得尝试并检查它自己)和随后得到顶级的看法,这是列入名单和随后使用setSe;ectionFromTop()方法,你可以滚动到想要的位置。

代码:

int index = mList.getFirstVisiblePosition();
View v = mList.getChildAt(0); //or upside down (list.size - 1)
int top = (v == null) ? 0 : v.getTop(); //returns the top of the view its Y co-ordinates. [Doc][1]
mList.setSelectionFromTop(index, top);

来源。

编辑考虑的额外信息:

我想我已经找到了您的问题。我复制了你的描述使用的情况下通过使用一个独立的名单如只看在XML:

<ListView
    android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
</ListView>

我固定的问题,按照你希望的使用情况下通过筑巢的布局,在一个父的布局:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>

</FrameLayout>

之后插入记录在您的适配器你可以尝试使用

   yourListView.setSelection(yourAdapter.getCount() - 1);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top