Android 如何更新ListView条目并让用户继续滚动ListView值?
我试图在用户滚动列表时更新listView列表,并为用户提供继续滚动新条目的选项,但没有成功,我需要帮助 在我的应用程序中,我有一个聊天记录,我正在SQLite上保存聊天记录。当用户进入聊天室时,应用程序只读取最后25条消息,并在列表底部显示最新消息。 为此,我在XML上使用了以下选项:Android 如何更新ListView条目并让用户继续滚动ListView值?,android,android-listview,Android,Android Listview,我试图在用户滚动列表时更新listView列表,并为用户提供继续滚动新条目的选项,但没有成功,我需要帮助 在我的应用程序中,我有一个聊天记录,我正在SQLite上保存聊天记录。当用户进入聊天室时,应用程序只读取最后25条消息,并在列表底部显示最新消息。 为此,我在XML上使用了以下选项: android:transcriptMode="alwaysScroll" android:stackFromBottom="true" 它工作得很好。 现在,当用户开始向上滚动并检查聊天记录
android:transcriptMode="alwaysScroll"
android:stackFromBottom="true"
它工作得很好。
现在,当用户开始向上滚动并检查聊天记录时,当他到达列表顶部时,我正在访问数据库并检索另外25条消息并将它们添加到列表顶部,我正在呼叫:
notifyDataSetChanged()
但当用户试图向上滚动时,不会显示任何内容,只有在再次向下和向上滚动后,才会显示新条目
我曾尝试使用setSelection和smoothScrollToPosition设置列表视图的位置,但这并没有真正起作用
它如何用新条目更新列表,并为用户提供继续和向上滚动的选项
以下是相关代码:
<ListView
android:id="@+id/chatList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:layout_margin="2dp"
android:layout_weight="1"
android:transcriptMode="alwaysScroll"
android:stackFromBottom="true"
android:background="@drawable/frame_tab"></ListView>
public void showChatLines() {
chatLinesView = chatTextDialog.findViewById(R.id.chatList);
chatAdaptor = new GenericAdapter<ChatLine>(activity, chatLines) {
@Override
public View getMyView(int position, View convertView, ViewGroup parent, ChatLine chatLine) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.chat_line, null);
TextView chatLineText = view.findViewById(R.id.chatLine);
chatLineText.setText(chatLine.messageText);
TextView chatLineTime = view.findViewById(R.id.chatLineTime);
chatLineTime.setText(chatLine.displayDateTime);
TextView chatLineUserName = view.findViewById(R.id.userName);
chatLineUserName.setText(chatLine.userDisplayName);
chatLineUserName.setTextColor(activity.getColor(Constants.colors[getColorBy(chatLine.userName)]));
LinearLayout chatLineLayout = view.findViewById(R.id.chatLineLayout);
LinearLayout.LayoutParams chatLineLayoutParams = (LinearLayout.LayoutParams) chatLineLayout.getLayoutParams();
CardView chatLineBackground = view.findViewById(R.id.chatLineBackground);
LinearLayout.LayoutParams chatLineBackgroundParams = (LinearLayout.LayoutParams) chatLineBackground.getLayoutParams();
LinearLayout chatLineSubLayout = view.findViewById(R.id.chatLineSubLayout);
FrameLayout.LayoutParams chatLineSubLayoutParams = (FrameLayout.LayoutParams) chatLineSubLayout.getLayoutParams();
if (chatLine.userName.equals(logonUserName)) {
CardView charLineCard = view.findViewById(R.id.chatLineBackground);
charLineCard.setCardBackgroundColor(activity.getColor(R.color.focusedColor));
((ViewGroup) chatLineUserName.getParent()).removeView(chatLineUserName);
} else {
chatLineLayoutParams.gravity = Gravity.RIGHT;
chatLineLayout.setLayoutParams(chatLineLayoutParams);
chatLineSubLayoutParams.gravity = Gravity.RIGHT;
chatLineSubLayout.setLayoutParams(chatLineSubLayoutParams);
chatLineBackgroundParams.gravity = Gravity.RIGHT;
chatLineBackground.setLayoutParams(chatLineBackgroundParams);
}
if (position==0 & fromLine!=0) {
getNextChatLinesFromDb(position);
}
return view;
}
};
chatLinesView.setAdapter(chatAdaptor);
}
private void getNextChatLinesFromDb(int position) {
toLine = fromLine - 1;
fromLine -= pageSize;
if (fromLine < 0) {
fromLine = 0;
}
ArrayList<ChatLine> newChatLines = db.getChatLines(chatRoomId, fromLine, toLine);
chatLines.addAll(0, newChatLines);
chatAdaptor.notifyDataSetChanged();
}
公共空间展示热线(){
chatLinesView=chatTextDialog.findviewbyd(R.id.chatList);
ChatAdapter=新的通用适配器(活动、聊天线路){
@凌驾
公共视图getMyView(int位置、视图转换视图、视图组父视图、聊天线聊天线){
LayoutFlater充气器=(LayoutFlater)context.getSystemService(context.LAYOUT\u充气器\u服务);
视图=充气机。充气(R.layout.chat_行,空);
TextView chatLineText=view.findviewbyd(R.id.chatLine);
chatLineText.setText(chatLine.messageText);
TextView chatLineTime=view.findviewbyd(R.id.chatLineTime);
chatLine.setText(chatLine.displayDateTime);
TextView chatLineUserName=view.findviewbyd(R.id.userName);
chatLineUserName.setText(chatLine.userDisplayName);
chatLineUserName.setTextColor(activity.getColor(Constants.colors[getColorBy(chatLine.userName)]);
LinearLayout chatLineLayout=view.findViewById(R.id.chatLineLayout);
LinearLayout.LayoutParams chatLineLayoutParams=(LinearLayout.LayoutParams)chatLineLayout.getLayoutParams();
cardwiew chatLineBackground=view.findviewbyd(R.id.chatLineBackground);
LinearLayout.LayoutParams chatLineBackgroundParams=(LinearLayout.LayoutParams)chatLineBackground.getLayoutParams();
LinearLayout chatLineSubLayout=view.findViewById(R.id.chatLineSubLayout);
FrameLayout.LayoutParams chatLineSubLayoutParams=(FrameLayout.LayoutParams)chatLineSubLayout.getLayoutParams();
if(chatLine.userName.equals(logonUserName)){
cardwiew charLineCard=view.findviewbyd(R.id.chatLineBackground);
charLineCard.setCardBackgroundColor(activity.getColor(R.color.focusedColor));
((查看组)chatLineUserName.getParent()).removeView(chatLineUserName);
}否则{
chatLineLayoutParams.gravity=gravity.RIGHT;
setLayoutParams(chatLineLayoutParams);
chatLineSubLayoutParams.gravity=gravity.RIGHT;
chatLineSubLayout.setLayoutParams(chatLineSubLayoutParams);
chatLineBackgroundParams.gravity=gravity.RIGHT;
setLayoutParams(chatLineBackgroundParams);
}
如果(位置==0和fromLine!=0){
getNextChatLinesFromDb(位置);
}
返回视图;
}
};
chatLinesView.setAdapter(chatLinesView.setAdapter);
}
私有void getNextChatLinesFromDb(内部位置){
toLine=fromLine-1;
fromLine-=页面大小;
if(fromLine<0){
fromLine=0;
}
ArrayList newChatLines=db.getChatLines(聊天室ID、fromLine、toLine);
addAll(0,newChatLines);
notifyDataSetChanged();
}
我认为此代码将帮助您:
// get position of listview
int index = chatLinesView.getFirstVisiblePosition();
View v = chatLinesView.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
// notify dataset changed or re-assign adapter here
//re-assign the position of listview after setting the adapter again
chatLinesView.setSelectionFromTop(index, top);
编辑
int h1 = chatLinesView.getHeight();
int h2 = chatLinesViewRow.getHeight();
chatLinesView.smoothScrollToPositionFromTop(position, h1/2 - h2/2, duration);
参数
位置->要滚动到的位置
偏移量-->所需的距离(以像素为单位),该距离的位置与屏幕顶部的距离相同
滚动完成时查看
持续时间->用于滚动的毫秒数
请尝试以下示例代码:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<ListView
android:id="@+id/listView"
android:transcriptMode="alwaysScroll"
android:stackFromBottom="true"
android:layout_width="match_parent"
android:layout_height="match_parent"></ListView>
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity implements AbsListView.OnScrollListener{
final static private int ADD_DATA_SIZE = 10;
ArrayList<String> dataList;
ListView listView;
ArrayAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dataList = new ArrayList<>();
for(int i=0; i<30; i++){
dataList.add("Item " + i);
}
listView = findViewById(R.id.listView);
adapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_list_item_1, dataList);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(getApplicationContext(), adapterView.getItemAtPosition(i) + " Clicked!", Toast.LENGTH_SHORT).show();
}
});
listView.setOnScrollListener(this);
}
private void addNewData() {
ArrayList<String> tmpList = new ArrayList<>();
for(int i=0; i<ADD_DATA_SIZE; i++){
tmpList.add("Add " + (dataList.size() - 20)/10 + ": Item " + i);
}
dataList.addAll(0, tmpList);
// Try this:
//listView.setSelection(ADD_DATA_SIZE);
//adapter.notifyDataSetInvalidated();
// or this:
adapter.notifyDataSetChanged();
listView.setSelection(ADD_DATA_SIZE);
}
@Override
public void onScrollStateChanged(AbsListView absListView, int i) {}
@Override
public void onScroll(AbsListView absListView, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if(firstVisibleItem == 0){
View view = absListView.getChildAt(0);
if(view != null){
if (view.getTop() == absListView.getTop()) {
absListView.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_DISABLED);
Toast.makeText(getApplicationContext(), "TRANSCRIPT MODE CHANGED TO: "
+ absListView.getTranscriptMode(), Toast.LENGTH_SHORT).show();
addNewData();
}
}
} else if (totalItemCount == (firstVisibleItem + visibleItemCount)){
View view = absListView.getChildAt(visibleItemCount - 1);
if (view.getBottom() == absListView.getBottom()) {
absListView.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
Toast.makeText(getApplicationContext(), "TRANSCRIPT MODE CHANGED TO: "
+ absListView.getTranscriptMode(), Toast.LENGTH_SHORT).show();
}
}
}
}
公共类MainActivity扩展AppCompatActivity实现AbsListView.OnScrollListener{
最终静态私有int ADD_DATA_SIZE=10;
ArrayList数据表;
列表视图列表视图;
阵列适配器;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dataList=newarraylist();
对于(int i=0;我可以发布您的代码吗?我已经添加了相关的代码。我已经尝试过了,但替换了Log.v(标记“向上滚动”);我的条件是从数据库中获取新条目,但它仍然不起作用。向上滚动在最后一个原始条目处停止,只有在向下和向上滚动后才能识别新条目。实际上,发生的情况是当ChatAdapter.notifyDataSetChanged();被调用listView正在跳到列表的末尾。我已尝试调用chatLinesView.setStackFromBottom(false);因此,在这种情况下,listview会跳到列表的顶部。是的,只需保持您在setSelectionFromTop中想要的位置您的新建议也不起作用……一旦我通知更改,listview会跳到listview的末尾。无论如何,我阅读了setSelectionFromTop的文档,它会说“设置所选项目,并将所选项目从ListView的上边缘定位为y像素。”