Recycle View Items animation crashing while adding first item

Viewed 809

I am developing a small app where users can post something and comment on a post. I am using the Instamaterial project on github as a reference.

https://github.com/frogermcs/InstaMaterial/blob/master/app/src/main/java/io/github/froger/instamaterial/ui/activity/CommentsActivity.java

There is a comment activity with animation while users post a new comment. Everything is working cool ... but when I post the very first comment... the app is crashing and not showing the comment animation (scroll to top) I spent the whole day trying ... but could not find the solution.

public class CommentsActivity extends AppCompatActivity implements SendCommentButton.OnSendClickListener {
    public static final String ARG_DRAWING_START_LOCATION = "arg_drawing_start_location";

    LinearLayout contentRoot;
    RecyclerView rvComments;
    LinearLayout llAddComment;
    EditText etComment;
    SendCommentButton btnSendComment;

    private CommentsAdapter commentsAdapter;
    private int drawingStartLocation;
    Toolbar toolbar;
    private int currentPostID;

    DatabaseHelper db;
    private PreferencesManager preferencesManager;
    ArrayList<PostResponse.PostComments> comments;

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

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        contentRoot = (LinearLayout) findViewById(R.id.contentRoot);
        rvComments = (RecyclerView) findViewById(R.id.rvComments);
        llAddComment = (LinearLayout) findViewById(R.id.llAddComment);
        etComment = (EditText) findViewById(R.id.etComment);
        btnSendComment = (SendCommentButton) findViewById(R.id.btnSendComment);

        preferencesManager = new PreferencesManager(CommentsActivity.this);
        db = new DatabaseHelper(CommentsActivity.this);

        setupToolbar();
        setupComments();
        setupSendCommentButton();

        drawingStartLocation = getIntent().getIntExtra(ARG_DRAWING_START_LOCATION, 0);
        if (savedInstanceState == null) {
            contentRoot.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    contentRoot.getViewTreeObserver().removeOnPreDrawListener(this);
                    startIntroAnimation();
                    return true;
                }
            });
        }
    }

    protected void setupToolbar() {
        if (toolbar != null) {
            setSupportActionBar(toolbar);
            getSupportActionBar().setDisplayShow
HomeEnabled(true);
            toolbar.setNavigationIcon(R.mipmap.ic_menu_cancel);
            toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onBackPressed();
                }
            });
        }
    }

    private void setupComments() {
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        rvComments.setLayoutManager(linearLayoutManager);
        rvComments.setHasFixedSize(true);
        currentPostID = getIntent().getIntExtra(PostResponse.KEY_ID, -1);
        comments = db.getCommentsByPostID(currentPostID);

        commentsAdapter = new CommentsAdapter(this, comments);
        rvComments.setAdapter(commentsAdapter);
        rvComments.setOverScrollMode(View.OVER_SCROLL_NEVER);
        rvComments.setOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
                    commentsAdapter.setAnimationsLocked(true);
                }
            }
        });
    }

    private void setupSendCommentButton() {
        btnSendComment.setOnSendClickListener(this);
    }

    private void startIntroAnimation() {
        ViewCompat.setElevation(getToolbar(), 0);
        contentRoot.setScaleY(0.1f);
        contentRoot.setPivotY(drawingStartLocation);
        llAddComment.setTranslationY(200);

        contentRoot.animate()
                .scaleY(1)
                .setDuration(200)
                .setInterpolator(new AccelerateInterpolator())
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        ViewCompat.setElevation(getToolbar(), Utils.dpToPx(8));
                        animateContent();
                    }
                })
                .start();
    }

    private void animateContent() {
        commentsAdapter.updateItems();
        llAddComment.animate().translationY(0)
                .setInterpolator(new DecelerateInterpolator())
                .setDuration(200)
                .start();
    }

    @Override
    public void onBackPressed() {
        ViewCompat.setElevation(getToolbar(), 0);

        contentRoot.postDelayed(new Runnable() {
            @Override
            public void run() {
                contentRoot.animate()
                        .translationY(Utils.getScreenHeight(CommentsActivity.this))
                        .setDuration(200)
                        .setListener(new AnimatorListenerAdapter() {
                            @Override
                            public void onAnimationEnd(Animator animation) {
                                CommentsActivity.super.onBackPressed();
                                overridePendingTransition(0, 0);
                            }
                        })
                        .start();
            }
        }, 100);
    }

    @Override
    public void onSendClickListener(View v) {
        if (validateComment()) {
            publishComment(etComment.getText().toString());

            PostResponse.PostComments newComment = new PostResponse().new PostComments();
            newComment.user_id = Integer.parseInt(preferencesManager.getUserID());
            newComment.comment = etComment.getText().toString();
            newComment.post_id = currentPostID;

            commentsAdapter.addItem(newComment);

            commentsAdapter.setAnimationsLocked(false);
            commentsAdapter.setDelayEnterAnimation(true);
            rvComments.smoothScrollBy(0, rvComments.getChildAt(0).getHeight() * commentsAdapter.getItemCount());

            etComment.setText(null);
            btnSendComment.setCurrentState(SendCommentButton.STATE_DONE);
        }
    }


    private boolean validateComment() {
        if (TextUtils.isEmpty(etComment.getText())) {
            btnSendComment.startAnimation(AnimationUtils.loadAnimation(this, R.anim.shake_error));
            return false;
        }

        return true;
    }

    private Toolbar getToolbar(){
        return toolbar;
    }



    /************************************************
     * VOLLEY CALLS TO PUBLISH A COMMENT
     * *****************************************************/
    private void publishComment(final String comment) {
       //Code here

    }

}

This is my adapter

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

    private Context context;
    private int lastAnimatedPosition = -1;
    private int avatarSize;
    private int itemsCount = 0;


    private boolean animationsLocked = false;
    private boolean delayEnterAnimation = true;
    List<PostResponse.PostComments> mItems;

    public CommentsAdapter(Context context, List<PostResponse.PostComments> mItems) {
        this.context = context;
        this.mItems = mItems;
        avatarSize = context.getResources().getDimensionPixelSize(R.dimen.comment_avatar_size);
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        final View view = LayoutInflater.from(context).inflate(R.layout.item_comment, parent, false);
        return new CommentViewHolder(view);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
        runEnterAnimation(viewHolder.itemView, position);
        CommentViewHolder holder = (CommentViewHolder) viewHolder;
        holder.tvComment.setText(mItems.get(position).comment);

        Picasso.with(context)
                .load(R.drawable.user_profile)
                .centerCrop()
                .resize(avatarSize, avatarSize)
                .transform(new RoundedTransformation())
                .into(holder.ivUserAvatar);
    }

    private void runEnterAnimation(View view, int position) {
        if (animationsLocked) return;

        if (position > lastAnimatedPosition) {
            lastAnimatedPosition = position;
            view.setTranslationY(100);
            view.setAlpha(0.f);
            view.animate()
                    .translationY(0).alpha(1.f)
                    .setStartDelay(delayEnterAnimation ? 20 * (position) : 0)
                    .setInterpolator(new DecelerateInterpolator(2.f))
                    .setDuration(300)
                    .setListener(new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            animationsLocked = true;
                        }
                    })
                    .start();
        }
    }

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

    public void updateItems() {
        notifyDataSetChanged();
    }

    public void addItem(PostResponse.PostComments newComment) {
        mItems.add(newComment);
        notifyItemInserted(mItems.size() - 1);
    }

    public void setAnimationsLocked(boolean animationsLocked) {
        this.animationsLocked = animationsLocked;
    }

    public void setDelayEnterAnimation(boolean delayEnterAnimation) {
        this.delayEnterAnimation = delayEnterAnimation;
    }

    public static class CommentViewHolder extends RecyclerView.ViewHolder {
        @Bind(R.id.ivUserAvatar)
        ImageView ivUserAvatar;
        @Bind(R.id.tvComment)
        TextView tvComment;

        public CommentViewHolder(View view) {
            super(view);
            ButterKnife.bind(this, view);
        }
    }
}

Here is the screens.

enter image description here Working Well

enter image description here

The first works well but adding the first comment never works. I get this exception.

// Here is the exception

java.lang.NullPointerException
at com.test.abc.CommentsActivity.onSendClickListener(CommentsActivity.java:214)
at com.test.abc.views.SendCommentButton.onClick(SendCommentButton.java:80)
at android.view.View.performClick(View.java:4463)
at android.view.View$PerformClick.run(View.java:18770)
at android.os.Handler.handleCallback(Handler.java:808)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:193)
1 Answers
Related