Problem with animation loading more items in recyclerview

Asked

Viewed 259 times

0

I am applying an animation in displaying items in my recyclerview, however when I load more items, the last item in my recyclerview is animated again in a strange way.

Here are the snippets of my recyclerview related code.

Mainactivity.java

public class MainActivity extends BaseActivity implements RecyclerViewOnClickListenerHack {

    public static String IDENTIFIER = "MainActivity";

    private Locale myLocale;
    private List<Post> mList = null;
    private RecyclerView mRecyclerView;
    private PostAdapter mAdapter;

    private FrameLayout mProgress;
    private LinearLayout mSlowConnection;
    private LinearLayout mNotFound;

    private boolean mInRequest = false;
    private Integer mOffset = 0;
    private Integer mLimit = 50;

    private Button mBtnReload;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar.setTitle(getString(R.string.general));
        setSupportActionBar(toolbar);

        super.setDrawer(MainActivity.this, toolbar);

        mRecyclerView = (RecyclerView) findViewById(R.id.rvPostList);
        mRecyclerView.setHasFixedSize(true);

        final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(linearLayoutManager);
        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                if(mList.size() == linearLayoutManager.findLastCompletelyVisibleItemPosition() + 1){
                    if(!mInRequest){
                        getMorePosts();
                    }
                }
            }
        });

        mProgress = (FrameLayout) findViewById(R.id.fl_progress);
        mSlowConnection = (LinearLayout) findViewById(R.id.ll_slow_connection);
        mNotFound = (LinearLayout) findViewById(R.id.ll_not_found);

        mBtnReload = (Button) findViewById(R.id.btn_reload);
        mBtnReload.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mProgress.setVisibility(View.VISIBLE);
                mSlowConnection.setVisibility(View.GONE);
                getPosts();
            }
        });

        getPosts();

        setImgProfile();

    }

    public void getPosts(){
        Call<List<Post>> call = mService.getPostsPaginated(MonitorSettings.ALL, mLimit, mOffset);
        call.enqueue(new Callback<List<Post>>() {
            @Override
            public void onResponse(Call<List<Post>> call, Response<List<Post>> response) {
                mProgress.setVisibility(View.GONE);
                mSlowConnection.setVisibility(View.GONE);

                if(response.isSuccessful()){
                    mList = response.body();
                    if(!mList.isEmpty()){
                        mOffset++;
                        mAdapter = new PostAdapter(MainActivity.this, mList);
                        mAdapter.setRecyclerViewOnClickListenerHack(MainActivity.this);
                        mRecyclerView.setAdapter(mAdapter);
                    }
                    else{
                        mNotFound.setVisibility(View.VISIBLE);
                    }
                }
                else{
                    AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                    builder.setTitle(getString(R.string.oops));
                    builder.setMessage(getString(R.string.login_again));
                    builder.setCancelable(false);
                    builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            logout();
                        }
                    });
                    builder.show();
                }
            }

            @Override
            public void onFailure(Call<List<Post>> call, Throwable t) {
                mProgress.setVisibility(View.GONE);
                mSlowConnection.setVisibility(View.VISIBLE);
            }
        });
    }

    public void getMorePosts(){
        mInRequest = true;
        mAdapter.addProgressBar();
        mRecyclerView.scrollToPosition(mList.size() - 1);
        Call<List<Post>> call = mService.getPostsPaginated(MonitorSettings.ALL, mLimit, mOffset);
        call.enqueue(new Callback<List<Post>>() {
            @Override
            public void onResponse(Call<List<Post>> call, Response<List<Post>> response) {
                mAdapter.removeProgressBar();

                if(response.isSuccessful()){
                    if(!mList.isEmpty()){
                        mOffset++;
                        mInRequest = false;

                        List<Post> posts = response.body();
                        for(Post post : posts){
                            mAdapter.addListItem(post, mList.size());
                        }
                    }
                    else{
                        Snackbar.make(mRecyclerView, "Todas as publicações já foram carregadas", Snackbar.LENGTH_INDEFINITE)
                                .setAction("Ok", new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {

                                    }
                                }).show();
                    }
                }
                else{
                    AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                    builder.setTitle(getString(R.string.oops));
                    builder.setMessage(getString(R.string.login_again));
                    builder.setCancelable(false);
                    builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            logout();
                        }
                    });
                    builder.show();
                }
            }

            @Override
            public void onFailure(Call<List<Post>> call, Throwable t) {
                Snackbar.make(mRecyclerView, "Não foi possível carregar mais publicações. Tente novamente", Snackbar.LENGTH_INDEFINITE)
                        .setAction("Ok", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                getMorePosts();
                            }
                        }).show();
            }
        });
    }

    public void setLocale(String lang) {
        myLocale = new Locale(lang);
        Resources res = getResources();
        DisplayMetrics dm = res.getDisplayMetrics();
        Configuration conf = res.getConfiguration();
        conf.locale = myLocale;
        res.updateConfiguration(conf, dm);
        Intent refresh = new Intent(this, MainActivity.class);
        refresh.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(refresh);
    }

    @Override
    public void startActivity(Intent intent) {
        if(Intent.ACTION_SEARCH.equalsIgnoreCase(intent.getAction())){
            intent.putExtra("page", MonitorSettings.ALL);
        }
        super.startActivity(intent);
    }

    @Override
    public void onClickListener(View view, int position) {
        Intent intent = new Intent(MainActivity.this, PostDetailsActivity.class);
        intent.putExtra("title", mList.get(position).getStatus());
        intent.putExtra("page", MonitorSettings.ALL);
        intent.putExtra("postId", mList.get(position).getId());
        intent.putExtra("postType", mList.get(position).getPostType());
        startActivity(intent);
    }
}

Postadapter.java

public class PostAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{

    private Context mCtx;

    private LayoutInflater mLayoutInflater;
    private List<Post> mList;
    private RecyclerViewOnClickListenerHack mRecyclerViewOnClickListenerHack;

    private Integer mProgressPosition = -1;
    private Integer mLastPosition = -1;

    public PostAdapter(Context ctx, List<Post> postList){
        this.mCtx = ctx;
        mList = postList;
        mLayoutInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        RecyclerView.ViewHolder mvh;
        if(viewType == 0) {
            View v = mLayoutInflater.inflate(R.layout.post_item_main, parent, false);
            mvh = new PostViewHolder(v);
        }else {
            View v = mLayoutInflater.inflate(R.layout.ll_progress_item, parent, false);
            mvh = new ProgressViewHolder(v);
        }
        return mvh;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
        if(viewHolder instanceof ProgressViewHolder) {
            ((ProgressViewHolder) viewHolder).progressBar.setIndeterminate(true);
        }
        else if(viewHolder instanceof PostViewHolder){
            PostViewHolder holder = ((PostViewHolder) viewHolder);
            holder.txtStatus.setText(mList.get(position).getStatus());
            holder.txtId.setText(String.format(mCtx.getString(R.string.post_id), mList.get(position).getId().toString()));
            try {
                holder.txtDate.setText(MonitorApplication.getConvertedDate(mList.get(position).getCreated_at(), MonitorSettings.SMALL_DATE_FORMAT, MonitorSettings.OUTPUT_DATE_FORMAT));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            String name = mList.get(position).getAssignee();
            if (name != null && !name.isEmpty()) {
                holder.txtName.setText(mList.get(position).getAssignee());
            } else {
                holder.txtName.setText(mCtx.getString(R.string.user_unidentified));
            }
            if (mList.get(position).getAssignee() == null) {
//            holder.txtName.setVisibility(View.GONE);
                holder.txtName.setText(mCtx.getString(R.string.responsible_unidentified));
            }
            holder.txtSubject.setText(mList.get(position).getCategory());
            holder.txtLocale.setText(mList.get(position).getNeighborhood());

            setAnimation(holder.llContent, position);
        }
    }

    @Override
    public int getItemCount() {
        return mList.isEmpty() ? 0 : mList.size();
    }

    public void addListItem(Post post, int position){
        mList.add(post);
        notifyItemInserted(position);
    }

    public void addProgressBar(){
        mList.add(null);
        notifyItemInserted(mList.size());
        mProgressPosition = mList.size()-1;
    }

    public void removeProgressBar(){
        mList.remove(mList.size() - 1);
        notifyItemRemoved(mList.size() - 1);
        mProgressPosition = -1;
    }

    @Override
    public int getItemViewType(int position) {
        Log.d("Thiago", "position: " + position);
        Log.d("Thiago", "mProgressPosition: " + mProgressPosition);
        Log.d("Thiago", "position == mProgressPosition: " + (position == mProgressPosition));
        return position == mProgressPosition ? 1 : 0;
    }

    public void setRecyclerViewOnClickListenerHack(RecyclerViewOnClickListenerHack r){
        mRecyclerViewOnClickListenerHack = r;
    }

    public class PostViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        public TextView txtStatus;
        public TextView txtId;
        public TextView txtDate;
        public TextView txtName;
        public TextView txtSubject;
        public TextView txtLocale;
        public LinearLayout llContent;

        public PostViewHolder(View itemView) {
            super(itemView);

            llContent = (LinearLayout) itemView.findViewById(R.id.ll_content);
            txtStatus = (TextView) itemView.findViewById(R.id.txtStatus);
            txtId = (TextView) itemView.findViewById(R.id.txtId);
            txtDate = (TextView) itemView.findViewById(R.id.txtDate);
            txtName = (TextView) itemView.findViewById(R.id.txtName);
            txtSubject = (TextView) itemView.findViewById(R.id.txtSubject);
            txtLocale = (TextView) itemView.findViewById(R.id.txtLocale);

            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            if(mRecyclerViewOnClickListenerHack != null){
                mRecyclerViewOnClickListenerHack.onClickListener(v, getAdapterPosition());
            }
        }

        public void clearAnimation(){
            llContent.clearAnimation();
        }
    }

    public static class ProgressViewHolder extends RecyclerView.ViewHolder {
        public ProgressBar progressBar;
        public ProgressViewHolder(View v) {
            super(v);
            progressBar = (ProgressBar)v.findViewById(R.id.progress);
        }
    }

    private void setAnimation(View viewToAnimate, int position)
    {
        // If the bound view wasn't previously displayed on screen, it's animated
        Animation animation;

        if (position > mLastPosition){
//            Animation animation = AnimationUtils.loadAnimation(mCtx, android.R.anim.slide_in_left);
            animation = AnimationUtils.loadAnimation(mCtx, R.anim.slide_in_bottom);
        }
        else{
            animation = AnimationUtils.loadAnimation(mCtx, R.anim.slide_in_top);
        }

        mLastPosition = position;
        viewToAnimate.startAnimation(animation);
    }

    @Override
    public void onViewDetachedFromWindow(final RecyclerView.ViewHolder holder)
    {
        if(holder instanceof PostViewHolder){
            ((PostViewHolder)holder).clearAnimation();
        }
    }
}

Here’s a gif of how the animation is behaving.

inserir a descrição da imagem aqui

Does anyone have any idea what I’m doing wrong?

  • If you want animation only when the list is created. You have to call the animation only for new view.

  • @I want animation on every item on the list, even after it’s created. When I go to load more items I add the progressbar to the list and when I have the answer I remove it and add the new items and this is where the problem is. I believe I’m doing something wrong when it comes to removing the progressibar and adding the new items, but I can’t see what it is.

  • Maybe this video will help: https://www.youtube.com/watch?v=PMX7zRD3dhg

  • You have to put item by item in the list. In the video it explains well.

No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.