15

I have a recyclerview with multiple items. and recyclerview has different viewtypes with different heights..

So these are what i tried

recyclerview.scrollToPosition(adapterWrapper.getAdapter().getItemCount()-1);

and

app:layoutManager="LinearLayoutManager"
app:stackFromEnd="true"

They work well for me when i apply them on single view types only.. But in multiview types. It's not scrolling to bottom. It's being stuck at 9 items before the bottom.

I was using stackFromBottom in listview before and it was working fine..

So what's the solution for it in recyclerview?

It's actually a chat app with different types of layout including images,gif etc..

RecyclerAdapter code,

package com.buckydroid.anonchat.Adapters;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.URLUtil;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;
import android.widget.Toast;

import com.buckydroid.anonchat.Async.DownloadManager;
import com.buckydroid.anonchat.Chatroom.ChatRoom;
import com.buckydroid.anonchat.Pages.FullScreenImageView;
import com.buckydroid.anonchat.Pages.Profile;
import com.buckydroid.anonchat.Pages.VideoPlayer;
import com.buckydroid.anonchat.R;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.load.resource.gif.GifDrawable;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.GlideDrawableImageViewTarget;
import com.bumptech.glide.request.target.Target;
import com.firebase.client.DataSnapshot;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.client.ValueEventListener;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.FirebaseDatabase;
import com.vanniktech.emoji.EmojiTextView;

import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

import de.hdodenhof.circleimageview.CircleImageView;

/**
 * Created by buckydroid on 27/04/17.
 */

public class ChatRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
    List<String> message = new ArrayList<>();
    List<Integer> image = new ArrayList<>();
    List<String> usernames = new ArrayList<>();
    List<String> keys = new ArrayList<>();
    ChatRoom chatroom = new ChatRoom();
    String name;
    Context c;
    String username;
    String otherusername;
    String groupName;
    public GifDrawable gifDrawable;
    List<Integer> type = new ArrayList<>();
    String id;
    ArrayList<String> zcode = new ArrayList<>();

    public ChatRecyclerAdapter(String id, String s, List<String> message, List<Integer> image, Context c, String username, String otherusername, List<Integer> type, List<String> usernames, String j, ArrayList<String> zcode) {
        this.message = message;
        this.image = image;
        this.c = c;
        this.username = username;
        this.otherusername = otherusername;
        this.type = type;
        this.usernames = usernames;
        this.groupName = j;
        this.name = s;
        this.id = id;
        this.zcode = zcode;

    }


    class ViewHolder extends  RecyclerView.ViewHolder{
        ImageView imageView;
        EmojiTextView messageView;
        CircleImageView profileImage;
        ImageView gif;
        TextView groupactionmessage;
        ImageView thumbnail;
        TextView filename;
        TextView filesize;
        TextView morevert;
        public ViewHolder(View itemView) {
            super(itemView);
            messageView = (EmojiTextView) itemView.findViewById(R.id.message_view);
            imageView = (ImageView) itemView.findViewById(R.id.imageMessage);
            profileImage = (CircleImageView) itemView.findViewById(R.id.profile_image);
            thumbnail = (ImageView) itemView.findViewById(R.id.thumbnail);
            filename = (TextView) itemView.findViewById(R.id.filename);
            gif = (ImageView) itemView.findViewById(R.id.gifmessage);
            groupactionmessage = (TextView) itemView.findViewById(R.id.group_action_message);


        }
    }



    @Override
    public int getItemViewType(int position) {
        if (username.equals(usernames.get(position))) {
            Log.i("type", String.valueOf(type.get(position)));
            return type.get(position);
        }
        else
            return type.get(position)+7;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = null;
        switch (viewType){

            case 0:
                v = LayoutInflater.from (parent.getContext ()).inflate (R.layout.sender_message_bubble, parent, false);
                System.out.println("Type 0");
                return new ViewHolder(v);


            case 7:
                v = LayoutInflater.from (parent.getContext ()).inflate (R.layout.message_item, parent, false);;
                System.out.println("Type 7");
                return new ViewHolder(v);


            case 1:
                v = LayoutInflater.from (parent.getContext ()).inflate (R.layout.sender_image_layout, parent, false);
                System.out.println("Type 1");
                return new ViewHolder(v);


            case 8:
                v = LayoutInflater.from (parent.getContext ()).inflate (R.layout.chatroom_image, parent, false);
                System.out.println("Type 8");
                return new ViewHolder(v);
            case 2:
                v = LayoutInflater.from (parent.getContext ()).inflate (R.layout.sender_gif, parent, false);
                System.out.println("Type 2");
                return new ViewHolder(v);


            case 9:
                v = LayoutInflater.from (parent.getContext ()).inflate (R.layout.chatroom_gif, parent, false);
                System.out.println("Type 9");

            case 3:
                v = LayoutInflater.from (parent.getContext ()).inflate (R.layout.group_actions_list, parent, false);
                System.out.println("Type 3");
                return new ViewHolder(v);


            case 10:
                v = LayoutInflater.from (parent.getContext ()).inflate (R.layout.group_actions_list, parent, false);
                System.out.println("Type 10");
                return new ViewHolder(v);


            case 4:
                v = LayoutInflater.from (parent.getContext ()).inflate (R.layout.video_thumbnail_message, parent, false);
                System.out.println("Type 4");
                return new ViewHolder(v);

            case 11:
                v = LayoutInflater.from (parent.getContext ()).inflate (R.layout.video_thumbnail_message2, parent, false);
                System.out.println("Type 11");
                return new ViewHolder(v);

            case 5:
                v = LayoutInflater.from (parent.getContext ()).inflate (R.layout.file_layout, parent, false);
                System.out.println("Type 5");
                return new ViewHolder(v);

            case 12:
                v = LayoutInflater.from (parent.getContext ()).inflate (R.layout.sender_file_layout, parent, false);
                System.out.println("Type 12");
                return new ViewHolder(v);

            default:
                v = LayoutInflater.from (parent.getContext ()).inflate (R.layout.message_item, parent, false);
                return new ViewHolder(v);

        }




    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        switch (holder.getItemViewType()){
            case 0:
            case 7:

                Log.i("Type on message", String.valueOf(type.get(position)) + "  " +message.get(position) + "   "+holder.getItemViewType());

                ViewHolder messageHolder = (ViewHolder)holder;
                if (!username.equals(usernames.get(position)))
                    messageHolder.profileImage.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Intent i = new Intent(c, Profile.class);
                            i.putExtra("username",usernames.get(position));
                            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            c.startActivity(i);
                        }
                    });
                Firebase userdata = new Firebase("https://droidchatz.firebaseio.com/userdata/"+usernames.get(position));
                userdata.addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        if (!usernames.get(position).equals(username))
                            Glide.with (c.getApplicationContext())
                                    .load (dataSnapshot.child("pic").getValue(String.class))
                                    .diskCacheStrategy(DiskCacheStrategy.ALL)

                                    .error (R.drawable.dog)
                                    .into (messageHolder.profileImage);

                    }

                    @Override
                    public void onCancelled(FirebaseError firebaseError) {

                    }
                });

               messageHolder.messageView.setText(message.get(position));




                messageHolder.messageView.setOnLongClickListener(new View.OnLongClickListener() {
                    @Override
                    public boolean onLongClick(View v) {
                        PopupMenu popupMenu = new PopupMenu(c, messageHolder.messageView);
                        popupMenu.getMenuInflater().inflate(R.menu.messsage_popup_menu, popupMenu.getMenu());
                        popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                            @Override
                            public boolean onMenuItemClick(MenuItem item) {
                                switch (item.getItemId()) {
                                    case R.id.action_reply:
                                        String te = usernames.get(position) + " : " + messageHolder.messageView.getText() + "\n\n\n";
                                        ChatRoom.input.setText(te);
                                        ChatRoom.input.setSelection(te.length());
                                        break;
                                    case R.id.action_copy:
                                        android.content.ClipboardManager clipboard = (android.content.ClipboardManager) c.getSystemService(Context.CLIPBOARD_SERVICE);
                                        android.content.ClipData clip = android.content.ClipData.newPlainText(messageHolder.messageView.getText(), messageHolder.messageView.getText());
                                        clipboard.setPrimaryClip(clip);
                                        Toast.makeText(c, "Text Copied...", Toast.LENGTH_SHORT).show();
                                        break;
                                    case R.id.action_report:
                                        new Firebase("https://droidchatz.firebaseio.com/groupchat/" + name).child("report").child(usernames.get(position)).child(FirebaseAuth.getInstance().getCurrentUser().getUid()).setValue(true);

                                        break;

                                }
                                return false;
                            }
                        });
                        popupMenu.show();
                        return false;
                    }
                });

                break;





            case 1:
            case 8:
                ViewHolder imageHolder = (ViewHolder)holder;

                Log.i("Type on image", String.valueOf(type.get(position)) + "  " +message.get(position)+"   "+holder.getItemViewType());

                imageHolder.imageView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Intent i = new Intent(c, FullScreenImageView.class);
                        i.putExtra("uri", message.get(position));
                        i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        c.startActivity(i);
                    }
                });



                imageHolder.imageView.setAdjustViewBounds(true);
                GlideDrawableImageViewTarget imageViewPreview = new GlideDrawableImageViewTarget(imageHolder.imageView);
                Glide
                        .with(c)
                        .load(message.get(position))
                        .centerCrop()
                        .listener(new RequestListener<String, GlideDrawable>() {
                            @Override
                            public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
                                return false;
                            }

                            @Override
                            public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                                return false;
                            }
                        })
                        .into(imageViewPreview);

                Firebase userdata2 = new Firebase("https://droidchatz.firebaseio.com/userdata/"+usernames.get(position));
                userdata2.addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        if (!usernames.get(position).equals(username)) {
                            Glide.with (c)
                                    .load (dataSnapshot.child("pic").getValue(String.class))
                                    .error (R.drawable.dog)
                                    .into (imageHolder.profileImage);


                        }                }

                    @Override
                    public void onCancelled(FirebaseError firebaseError) {

                    }
                });




                break;
            case 2:
            case 9:

                Log.i("Type on gif", String.valueOf(type.get(position)) + "  " +message.get(position)+"   "+holder.getItemViewType());

                ViewHolder gifHolder = (ViewHolder)holder;
                gifHolder.gif.setAdjustViewBounds(true);
                GlideDrawableImageViewTarget imageViewPreview2 = new GlideDrawableImageViewTarget(gifHolder.gif);
                Glide
                        .with(c)
                        .load(message.get(position))
                        .listener(new RequestListener<String, GlideDrawable>() {
                            @Override
                            public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
                                return false;
                            }

                            @Override
                            public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                                return false;
                            }
                        })
                        .into(imageViewPreview2);
                if (!username.equals(usernames.get(position)))
                    gifHolder.profileImage.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Intent i = new Intent(c, Profile.class);
                            i.putExtra("username",usernames.get(position));
                            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            c.startActivity(i);
                        }
                    });


                Firebase userdata3 = new Firebase("https://droidchatz.firebaseio.com/userdata/"+usernames.get(position));
                userdata3.addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        if (!usernames.get(position).equals(username))
                            Glide.with (c)
                                    .load (dataSnapshot.child("pic").getValue(String.class))
                                    .error (R.drawable.dog)
                                    .into (gifHolder.profileImage);

                    }

                    @Override
                    public void onCancelled(FirebaseError firebaseError) {

                    }
                });


                break;
            case 3:
            case 10:
                Log.i("Type on action", String.valueOf(type.get(position)) + "  " +message.get(position)+"   "+holder.getItemViewType());

                ViewHolder actionHolder = (ViewHolder)holder;
                actionHolder.groupactionmessage.setText(message.get(position));


                break;

            case 4:
            case 11:

                ViewHolder videoHolder = (ViewHolder)holder;
                Log.i("Type on video", String.valueOf(type.get(position)) + "  " +message.get(position)+"   "+holder.getItemViewType());
                FirebaseDatabase.getInstance().getReference().child("thumbnails").child(name).child(zcode.get(position)).addValueEventListener(new com.google.firebase.database.ValueEventListener() {
                    @Override
                    public void onDataChange(com.google.firebase.database.DataSnapshot dataSnapshot) {
                        Glide.with(c).load(dataSnapshot.getValue(String.class)).centerCrop().into(videoHolder.thumbnail);
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {

                    }
                });


                if (!username.equals(usernames.get(position)))
                    videoHolder.profileImage.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Intent i = new Intent(c, Profile.class);
                            i.putExtra("username",usernames.get(position));
                            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            c.startActivity(i);
                        }
                    });
                videoHolder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Intent i = new Intent(c, VideoPlayer.class);
                        i.putExtra("link", message.get(position));
                        i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                        c.startActivity(i);

                    }
                });
                Firebase userdata4 = new Firebase("https://droidchatz.firebaseio.com/userdata/"+usernames.get(position));

                userdata4.addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        if (!usernames.get(position).equals(username))
                            Glide.with (c)
                                    .load (dataSnapshot.child("pic").getValue(String.class))
                                    .error (R.drawable.dog)
                                    .into (videoHolder.profileImage);

                    }

                    @Override
                    public void onCancelled(FirebaseError firebaseError) {

                    }
                });



                break;
            case 5:
            case 12:



                ViewHolder fileHolder = (ViewHolder)holder;
                Firebase userdata5 = new Firebase("https://droidchatz.firebaseio.com/userdata/"+usernames.get(position));
                if (!username.equals(usernames.get(position)))
                    fileHolder.profileImage.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Intent i = new Intent(c, Profile.class);
                            i.putExtra("username",usernames.get(position));
                            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            c.startActivity(i);
                        }
                    });
                userdata5.addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        if (!usernames.get(position).equals(username))

                            Glide.with (c)
                                    .load (dataSnapshot.child("pic").getValue(String.class))
                                    .error (R.drawable.dog)
                                    .into (fileHolder.profileImage);

                    }

                    @Override
                    public void onCancelled(FirebaseError firebaseError) {

                    }
                });
                fileHolder.filename.setText(URLUtil.guessFileName(message.get(position), null, null));
                final URL[] uri = new URL[1];
                final URLConnection[] ucon = new URLConnection[1];
                final String[] contentLengthStr = new String[1];
                Thread size = new Thread();
                Runnable getfilesize;
                fileHolder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(message.get(position)));
                        c.startActivity(browserIntent);
                    }
                });
                break;


        }




    }



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


    }

Thanx!!!

Doge
  • 853
  • 11
  • 35
  • where do you call this method ?recyclerview.scrollToPosition(adapterWrapper.getAdapter().getItemCount()-1); try this mRecyclerView.post(new Runnable() { @Override public void run() { mRecyclerView.scrollToPosition(mData.size()-1); } }); – Reyansh Mishra May 02 '17 at 02:17
  • @ReyanshMishra I tried setStackFromEnd in oncreate. ScrollToPostion after recyclerview.setAdapter – Doge May 02 '17 at 02:19
  • once your all data is loaded and your recyclerview and adapter is ready then you should call this method calling before or in between can confuse the recyclerview to calculate the sizes of the item in its adapter. try above code and let me know. – Reyansh Mishra May 02 '17 at 02:22

3 Answers3

11

I don't know the reason, But I changed my RecyclerView height to match_parent and it's working properly.

And it's scrolling to complete bottom and I'm still using same function .setstacktoend(true)

Thanx to everyone who tried to help me :)

Doge
  • 853
  • 11
  • 35
7

Can you show us your whole code of recyclerview and its adapter.

maybe this will work

recyclerview.scrollToPosition(mData.size()-1);

where mData is the list which you are passing into the recyclerview's adapter those its pretty hard to figure out what's wrong with such a little code.

Reyansh Mishra
  • 1,879
  • 1
  • 14
  • 26
  • Added the adapter class. And i can't share the whole activity code cuz it's 4000+ lines.... – Doge Apr 30 '17 at 06:08
  • did try this solution http://stackoverflow.com/questions/26580723/how-to-scroll-to-the-bottom-of-a-recyclerview-scrolltoposition-doesnt-work ? – Reyansh Mishra Apr 30 '17 at 06:16
  • Yeah as i said i tried setstackfromend it's not working.. May be this is somehow working. lemme give an example. I have 100 list items.. the bottom scrolling stops at 94 – Doge Apr 30 '17 at 06:18
  • Imo, `mData.size() - 1` is the correct position to scroll to. – azizbekian May 01 '17 at 05:21
0

It seems that no one here has mentioned the actual reason. I've encountered a similar issue. If you are using Glide to load images and your imageView's width and height are dynamic, what will happen if you call recyclerview.scrollToPosition before the onResourceReady callback?

If you call recyclerview.scrollToPosition before the onResourceReady callback is triggered, the RecyclerView will scroll to the desired position immediately, without waiting for Glide to finish loading the image and adjusting the imageView's dimensions. As a result, after Glide finishes loading the image and the imageView's dimensions change, the content may shift or become misaligned, causing an offset.

To avoid this issue, it is recommended to wait until all the images are loaded before calling scrollToPosition. You can achieve this by using Glide's listener methods or other mechanisms to determine when all the images have been loaded, and then trigger the scrollToPosition method. This ensures that the RecyclerView scrolls to the correct position after all the images have finished loading and their dimensions have been adjusted.

lazy
  • 149
  • 8