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.
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.
– Tiago P Casemiro
@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.
– ThiagoFerreiraS
Maybe this video will help: https://www.youtube.com/watch?v=PMX7zRD3dhg
– Tiago P Casemiro
You have to put item by item in the list. In the video it explains well.
– Tiago P Casemiro