Java 为什么recyclerview ScrollToBottom不能有效工作?

Java 为什么recyclerview ScrollToBottom不能有效工作?,java,android,android-recyclerview,Java,Android,Android Recyclerview,我彻底搜索并尝试实现不同的东西,但似乎不可能 要求: 在我的聊天应用程序中,当我打开特定的用户聊天屏幕时 它应该滚动到底部,以便用户可以看到最后的消息/对话 当任何新的消息/新的项目将添加在那个时候,它应该滚动到底部 请注意,如果我使用以下方法,则我的第一个要求无效 private void loadMessages() { try { DatabaseReference messageReference = rootReference.child(MES

我彻底搜索并尝试实现不同的东西,但似乎不可能

要求: 在我的聊天应用程序中,当我打开特定的用户聊天屏幕时

  • 它应该滚动到底部,以便用户可以看到最后的消息/对话
  • 当任何新的消息/新的项目将添加在那个时候,它应该滚动到底部
  • 请注意,如果我使用以下方法,则我的第一个要求无效

    private void loadMessages() {
            try {
                DatabaseReference messageReference = rootReference.child(MESSAGES).child(currentUId).child(chatUser);
                Query query = messageReference.orderByChild(TIME);
    
                ValueEventListener valueEventListener = new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        messagesList.clear();
                        for (DataSnapshot ds : dataSnapshot.getChildren()) {
                            try {
                                Messages messages = ds.getValue(Messages.class);
                                messagesList.add(messages);
                                setAdapter();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
    
                    @Override
                    public void onCancelled(DatabaseError databaseError) {
                        databaseError.getMessage();
                    }
                };
                query.addValueEventListener(valueEventListener);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    private void setAdapter() {
            try {
                if (mAdapter != null) {
                    mLayoutManager.smoothScrollToPosition(binding.recyclerViewLayout.recyclerView, null, messagesList.size());
                    mAdapter.notifyDataSetChanged();
                } else {
                    mAdapter = new MessageAdapter(this, messagesList);
                    mLayoutManager.setStackFromEnd(false);
                    mLayoutManager.setSmoothScrollbarEnabled(true);
                    binding.recyclerViewLayout.recyclerView.setLayoutManager(mLayoutManager);
                    binding.recyclerViewLayout.recyclerView.setAdapter(mAdapter);
                    binding.recyclerViewLayout.recyclerView.setVisibility(View.VISIBLE);
                }
            } catch (Exception exp) {
                exp.printStackTrace();
            }
        }
    
    如果我使用下面的方法,那么我的第二个要求不起作用

    private void loadMessages() {
                try {
                    DatabaseReference messageReference = rootReference.child(MESSAGES).child(currentUId).child(chatUser);
                    Query query = messageReference.orderByChild(TIME);
        
                    ValueEventListener valueEventListener = new ValueEventListener() {
                        @Override
                        public void onDataChange(DataSnapshot dataSnapshot) {
                            messagesList.clear();
                            for (DataSnapshot ds : dataSnapshot.getChildren()) {
                                try {
                                    Messages messages = ds.getValue(Messages.class);
                                    messagesList.add(messages);
                                    Comparator<Messages> compare = Collections.reverseOrder();
                                    Collections.sort(messagesList, compare);
                                    setAdapter();
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        }
        
                        @Override
                        public void onCancelled(DatabaseError databaseError) {
                            databaseError.getMessage();
                        }
                    };
                    query.addValueEventListener(valueEventListener);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
        
            private void setAdapter() {
                try {
                    if (mAdapter != null) {
                        mAdapter.notifyDataSetChanged();
                    } else {
                        mAdapter = new MessageAdapter(this, messagesList);
                        LinearLayoutManager mLayoutManager = new LinearLayoutManager(this);
                        mLayoutManager.setReverseLayout(true);
                        mLayoutManager.setStackFromEnd(true);
                        mLayoutManager.setSmoothScrollbarEnabled(true);
                        binding.recyclerViewLayout.recyclerView.setLayoutManager(mLayoutManager);
                        binding.recyclerViewLayout.recyclerView.scrollToPosition(mAdapter.getItemCount() - 1);
                        binding.recyclerViewLayout.recyclerView.setAdapter(mAdapter);
                        binding.recyclerViewLayout.recyclerView.setVisibility(View.VISIBLE);
                    }
                } catch (Exception exp) {
                    exp.printStackTrace();
                }
            }
    
    private void loadMessages(){
    试一试{
    DatabaseReference messageReference=rootReference.child(MESSAGES).child(currentUId).child(chatUser);
    Query Query=messageReference.orderByChild(时间);
    ValueEventListener ValueEventListener=新的ValueEventListener(){
    @凌驾
    公共void onDataChange(DataSnapshot DataSnapshot){
    messagesList.clear();
    对于(DataSnapshot ds:DataSnapshot.getChildren()){
    试一试{
    Messages=ds.getValue(Messages.class);
    messagesList.add(消息);
    Comparator compare=Collections.reverseOrder();
    Collections.sort(messagesList,compare);
    setAdapter();
    }捕获(例外e){
    e、 printStackTrace();
    }
    }
    }
    @凌驾
    已取消的公共void(DatabaseError DatabaseError){
    databaseError.getMessage();
    }
    };
    addValueEventListener(valueEventListener);
    }捕获(例外e){
    e、 printStackTrace();
    }
    }
    私有void setAdapter(){
    试一试{
    如果(mAdapter!=null){
    mAdapter.notifyDataSetChanged();
    }否则{
    mAdapter=newmessageadapter(这个,messagesList);
    LinearLayoutManager mLayoutManager=新的LinearLayoutManager(此);
    mLayoutManager.setReverseLayout(true);
    mLayoutManager.setStackFromEnd(true);
    mLayoutManager.setSmoothScrollbarEnabled(true);
    binding.recyclerViewLayout.recyclerView.setLayoutManager(mlLayoutManager);
    binding.recyclerViewLayout.recyclerView.scrollToPosition(mAdapter.getItemCount()-1);
    binding.recyclerViewLayout.recyclerView.setAdapter(mAdapter);
    binding.recyclerViewLayout.recyclerView.setVisibility(View.VISIBLE);
    }
    }捕获(异常扩展){
    exp.printStackTrace();
    }
    }
    
    请注意
    setAdapter()
    ,因为它在为每个循环调用时,第一次创建适配器,然后在循环的下一个增量立即调用notifydatasetchanged

    编辑:


    完整代码:

    编辑4:

  • 使其正常工作(通过在适配器中添加一个函数
    addItem()
    notifyItemInserted(messagesList.size());
    addItem()
    函数中添加一个函数

  • 在填充
    列表之后添加了
    recyclerView.scrollToPosition(mAdapter.getItemCount()-1);

  • 3.每次
    sendbutonClickEvent()
    添加
    recyclerView.scrollToPosition(mAdapter.getItemCount()-1);

    注意:完整的代码在下面给出的链接中

    main活动

    package studio.devcode.recyclerviewdemo;
    
    import android.os.Build;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.EditText;
    import android.widget.ImageView;
    
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.recyclerview.widget.LinearLayoutManager;
    import androidx.recyclerview.widget.RecyclerView;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import studio.devcode.recyclerviewdemo.MessageAdapter;
    import studio.devcode.recyclerviewdemo.Messages;
    import studio.devcode.recyclerviewdemo.R;
    
    public class MainActivity extends AppCompatActivity {
        private ImageView imageViewSend;
        private EditText editTextMessage;
        private List<Messages> messagesList;
        private MessageAdapter mAdapter;
        private LinearLayoutManager mLayoutManager;
        private RecyclerView recyclerView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mLayoutManager = new LinearLayoutManager(this);
            recyclerView = findViewById(R.id.recycler_view_layout);
            messagesList = new ArrayList<>();
    
            imageViewSend = findViewById(R.id.send);
            editTextMessage = findViewById(R.id.type_message);
    
            setData("12345", "abc");
            setData("12345", "hello");
            setData("123145", "you");
            setData("12345", "there");
            setData("121345", "aqqqbc");
            setData("123145", "abqqc");
            setData("123145", "aqqbc");
            setData("12345", "awwbc");
            setData("123145", "eeabc");
            setData("12345", "abeeec");
            setData("112345", "addbc");
            setData("12345", "abdcc");
            setData("112345", "abccc");
            setData("121345", "abccc");
            setData("12345", "abccc");
            setAdapter();
    
            recyclerView.scrollToPosition(mAdapter.getItemCount() - 1);
            onSendButtonClick();
            onSoftInputKeyboardOpen();
        }
    
        private void setData(String from, String message) {
            messagesList.add(new Messages(message, "text", from));
        }
    
    
        private void onSendButtonClick(){
            imageViewSend.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if(!editTextMessage.getText().toString().isEmpty() || !editTextMessage.getText().toString().equals(" ")){
                        mAdapter.addItem(new Messages(editTextMessage.getText().toString().toUpperCase(), "text", "Ali"));
                        editTextMessage.setText("");
                        recyclerView.scrollToPosition(mAdapter.getItemCount() - 1);
                    }
                }
            });
        }
    
    
        private void setAdapter() {
            try {
                if (mAdapter != null) {
                    mAdapter.notifyDataSetChanged();
                    recyclerView.scrollToPosition(mAdapter.getItemCount());
    
    
                } else {
                    mAdapter = new MessageAdapter(this, messagesList, "12345");
                    mLayoutManager.setSmoothScrollbarEnabled(true);
                    mLayoutManager.setStackFromEnd(true);
                    recyclerView.setLayoutManager(mLayoutManager);
                    recyclerView.setAdapter(mAdapter);
                    recyclerView.setVisibility(View.VISIBLE);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        private void onSoftInputKeyboardOpen(){
            recyclerView.addOnLayoutChangeListener(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) {
                     if (bottom < oldBottom) {
                         recyclerView.postDelayed(new Runnable() {
                             @Override
                             public void run() {
                                 recyclerView.smoothScrollToPosition(
                                         recyclerView.getAdapter().getItemCount() - 1);
                             }
                         }, 100);
                     }
                 }
             });
        }
    }
    
    消息适配器

    package studio.devcode.recyclerviewdemo;
    
    import android.content.Context;
    import android.os.Build;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    
    import androidx.annotation.NonNull;
    import androidx.recyclerview.widget.RecyclerView;
    
    
    
    import java.util.List;
    
    
    
    public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.MyViewHolder> {
    
        private Context context;
        private List<Messages> messagesList;
        private String currentUid;
    
        public MessageAdapter(Context context, List<Messages> messagesList, String currentUid) {
            try {
                this.currentUid = currentUid;
                this.messagesList = messagesList;
                this.context = context;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        @NonNull
        @Override
        public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = null;
            MyViewHolder myViewHolder;
            try {
                view = LayoutInflater.from(parent.getContext()).inflate(
                        R.layout.message_single_layout, parent, false);
            } catch (Exception e) {
                e.printStackTrace();
            }
            myViewHolder = new MyViewHolder(view);
            return myViewHolder;
        }
    
        protected void showLog(String msg) {
            Log.d(this.getClass().getSimpleName(), msg);
        }
    
        protected boolean checkNull(String data) {
            return data != null && (!data.isEmpty());
        }
    
        @Override
        public void onBindViewHolder(@NonNull final MyViewHolder holder, int position) {
            try {
                Messages messages = messagesList.get(position);
                if (messages != null) {
                    String messageType = messages.getType();
                    if (checkNull(messages.getFrom()) && messages.getFrom().equals(currentUid)) {
                        if (checkNull(messageType) && messageType.equals("text")) {
                            holder.chatText_1.setText(messages.getMessage());
                            holder.messageSingleLayout.setVisibility(View.GONE);
                            holder.messageSingleLayout_1.setVisibility(View.VISIBLE);
                        }
                    } else {
                        if (checkNull(messageType) && messageType.equals("text")) {
                            holder.chatText.setText(messages.getMessage());
                            holder.messageSingleLayout.setVisibility(View.VISIBLE);
                            holder.messageSingleLayout_1.setVisibility(View.GONE);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public int getItemCount() {
            return messagesList.size();
        }
    
        public static class MyViewHolder extends RecyclerView.ViewHolder {
            public TextView chatText, chatText_1, chatTime, chatTime_1;
            public LinearLayout messageSingleLayout, messageSingleLayout_1;
            private final ImageView fileDownload;
            private final ImageView fileDownload_1;
    
            public MyViewHolder(View itemView) {
                super(itemView);
                chatText = itemView.findViewById(R.id.chatText);
                chatText_1 = itemView.findViewById(R.id.chatText_1);
                chatTime = itemView.findViewById(R.id.chatTime);
                chatTime_1 = itemView.findViewById(R.id.chatTime_1);
                messageSingleLayout = itemView.findViewById(R.id.messageSingleLayout);
                messageSingleLayout_1 = itemView.findViewById(R.id.messageSingleLayout_1);
                fileDownload = itemView.findViewById(R.id.fileDownload);
                fileDownload_1 = itemView.findViewById(R.id.fileDownload_1);
    
            }
        }
    
        public void addItem(Messages message) {
            messagesList.add(message);
            notifyItemInserted(messagesList.size());
        }
    
    
    }
    
    package studio.devcode.recycleServiceWdemo;
    导入android.content.Context;
    导入android.os.Build;
    导入android.util.Log;
    导入android.view.LayoutInflater;
    导入android.view.view;
    导入android.view.ViewGroup;
    导入android.widget.ImageView;
    导入android.widget.LinearLayout;
    导入android.widget.TextView;
    导入androidx.annotation.NonNull;
    导入androidx.recyclerview.widget.recyclerview;
    导入java.util.List;
    公共类MessageAdapter扩展了RecyclerView.Adapter{
    私人语境;
    私有列表消息列表;
    私有字符串currentUid;
    公共消息适配器(上下文上下文、列表消息列表、字符串currentUid){
    试一试{
    this.currentUid=currentUid;
    this.messagesList=messagesList;
    this.context=上下文;
    }捕获(例外e){
    e、 printStackTrace();
    }
    }
    @非空
    @凌驾
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup父级,int-viewType){
    视图=空;
    MyViewHolder MyViewHolder;
    试一试{
    view=LayoutInflater.from(parent.getContext()).flate(
    R.layout.message_single_layout,parent,false);
    }捕获(例外e){
    e、 printStackTrace();
    }
    myViewHolder=新的myViewHolder(视图);
    返回myViewHolder;
    }
    受保护的void showLog(字符串msg){
    Log.d(this.getClass().getSimpleName(),msg);
    }
    受保护的布尔校验空(字符串数据){
    返回数据!=null&(!data.isEmpty());
    }
    @凌驾
    public void onBindViewHolder(@NonNull final MyViewHolder,int位置){
    试一试{
    Messages=messagesList.get(位置);
    如果(消息!=null){
    字符串messageType=messages.getType();
    if(checkNull(messages.getFrom())&&messages.getFrom().equals(currentUid)){
    如果(检查)
    
    package studio.devcode.recyclerviewdemo;
    
    import android.content.Context;
    import android.os.Build;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    
    import androidx.annotation.NonNull;
    import androidx.recyclerview.widget.RecyclerView;
    
    
    
    import java.util.List;
    
    
    
    public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.MyViewHolder> {
    
        private Context context;
        private List<Messages> messagesList;
        private String currentUid;
    
        public MessageAdapter(Context context, List<Messages> messagesList, String currentUid) {
            try {
                this.currentUid = currentUid;
                this.messagesList = messagesList;
                this.context = context;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        @NonNull
        @Override
        public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = null;
            MyViewHolder myViewHolder;
            try {
                view = LayoutInflater.from(parent.getContext()).inflate(
                        R.layout.message_single_layout, parent, false);
            } catch (Exception e) {
                e.printStackTrace();
            }
            myViewHolder = new MyViewHolder(view);
            return myViewHolder;
        }
    
        protected void showLog(String msg) {
            Log.d(this.getClass().getSimpleName(), msg);
        }
    
        protected boolean checkNull(String data) {
            return data != null && (!data.isEmpty());
        }
    
        @Override
        public void onBindViewHolder(@NonNull final MyViewHolder holder, int position) {
            try {
                Messages messages = messagesList.get(position);
                if (messages != null) {
                    String messageType = messages.getType();
                    if (checkNull(messages.getFrom()) && messages.getFrom().equals(currentUid)) {
                        if (checkNull(messageType) && messageType.equals("text")) {
                            holder.chatText_1.setText(messages.getMessage());
                            holder.messageSingleLayout.setVisibility(View.GONE);
                            holder.messageSingleLayout_1.setVisibility(View.VISIBLE);
                        }
                    } else {
                        if (checkNull(messageType) && messageType.equals("text")) {
                            holder.chatText.setText(messages.getMessage());
                            holder.messageSingleLayout.setVisibility(View.VISIBLE);
                            holder.messageSingleLayout_1.setVisibility(View.GONE);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public int getItemCount() {
            return messagesList.size();
        }
    
        public static class MyViewHolder extends RecyclerView.ViewHolder {
            public TextView chatText, chatText_1, chatTime, chatTime_1;
            public LinearLayout messageSingleLayout, messageSingleLayout_1;
            private final ImageView fileDownload;
            private final ImageView fileDownload_1;
    
            public MyViewHolder(View itemView) {
                super(itemView);
                chatText = itemView.findViewById(R.id.chatText);
                chatText_1 = itemView.findViewById(R.id.chatText_1);
                chatTime = itemView.findViewById(R.id.chatTime);
                chatTime_1 = itemView.findViewById(R.id.chatTime_1);
                messageSingleLayout = itemView.findViewById(R.id.messageSingleLayout);
                messageSingleLayout_1 = itemView.findViewById(R.id.messageSingleLayout_1);
                fileDownload = itemView.findViewById(R.id.fileDownload);
                fileDownload_1 = itemView.findViewById(R.id.fileDownload_1);
    
            }
        }
    
        public void addItem(Messages message) {
            messagesList.add(message);
            notifyItemInserted(messagesList.size());
        }
    
    
    }