简体   繁体   中英

why RecyclerView.OnScrollListener() affects on only last item of recyclerview

I want to have this functionality in my App

在此处输入图片说明

means when ever RecyclerView is scrolled the TextView showing time should appear and dis-appear after little fragment of time, my effort goes in this way, the targeting TextView has Visiblity.GONE and adapter looks like

public class ChatMessageAdapter extends RecyclerView.Adapter<ViewHolder> {

    private List<ChatMessage> mMessageList;
    private Context mContext;
    private boolean isMe = false;

    private ThemMessageHolder messageHolder;

    public ChatMessageAdapter(Context mContext, List<ChatMessage> mMessageList){
        this.mContext = mContext;
        this.mMessageList = mMessageList;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View rootView = LayoutInflater.from(mContext).inflate( R.layout.chat_them_container, parent, false );
        return new ThemMessageHolder(rootView);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        messageHolder = (ThemMessageHolder) holder;
        messageHolder.mMessageTextView.setText(mMessageList.get(position).getMessage());
        messageHolder.mSentAtTextView.setText(mMessageList.get(position).getSentAt());
    }

    @Override
    public int getItemCount() {
        return mMessageList.size();
    }

    public void showAndHideDate(){
        messageHolder.mSentAtTextView.setVisibility(View.VISIBLE);
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                messageHolder.mSentAtTextView.setVisibility(View.GONE);
            }
        },3500);

    }

}

and in MainActivity I have simply

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);        

        mMessageList = new CopyOnWriteArrayList<>();

        mChatMessagesRecyclerView = (RecyclerView) findViewById(R.id.chat_msg_rv);
        mChatMessagesRecyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
        mChatMessageAdapter = new ChatMessageAdapter(MainActivity.this, mMessageList);
        mChatMessagesRecyclerView.setAdapter(mChatMessageAdapter);

        mChatMessagesRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                mChatMessageAdapter.showAndHideDate(); // Here I'm calling the method defined in Adapter class
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
            }
        });
    }

through above code I get the desired effect on only last item of RecyclerView as shown

在此处输入图片说明

How to apply that desired effect on all the items of RecyclerView?

The problem is that you are ussing ONLY ONE ThemMessageHolder variable in your adapter. Means that, the variable it's been overwrited with every onBindViewHolder() call. Then, messageHolder will be pointing to the last created holder, and the showAndHideDate() will work only with it.

The solution could be find all the visible holders (pseudocode):

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (initChatBarUI()){
            mSendImageButton.setOnClickListener(MainActivity.this);
            mEmoImageButton.setOnClickListener(MainActivity.this);
        }

        mMessageList = new CopyOnWriteArrayList<>();

        final LinearLayoutManager layoutManager = new LinearLayoutManager(MainActivity.this);
        mChatMessagesRecyclerView = (RecyclerView) findViewById(R.id.chat_msg_rv);
        mChatMessagesRecyclerView.setLayoutManager(layoutManager);
        mChatMessageAdapter = new ChatMessageAdapter(MainActivity.this, mMessageList);
        mChatMessagesRecyclerView.setAdapter(mChatMessageAdapter);

        mChatMessagesRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                final int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
                final int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition();
                mChatMessageAdapter.showAndHideDate(mChatMessagesRecyclerView, firstVisibleItemPosition, lastVisibleItemPosition); // Here I'm calling the method defined in Adapter class
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
            }
        });   
    }

and showAndHideDate() may look like

public void showAndHideDate(RecyclerView mRecyclerView, int firstVisibleItemPosition, int lastVisibleItemPosition){

    for (int i = firstVisibleItemPosition; i <= lastVisibleItemPosition; ++i) {
        final ThemMessageHolder holder = (ThemMessageHolder) mRecyclerView.findViewHolderForAdapterPosition(i);
        holder.mSentAtTextView.setVisibility(View.VISIBLE);
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                holder.mSentAtTextView.setVisibility(View.GONE);
            }
        },3500);
    }       

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM