I'm applying an animation in the display of 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 my code snippets related to recyclerview.
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 is a gif of how the animation is behaving.
Does anyone have any idea what I'm doing wrong?