diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
index d6630c9c3..42ac62c59 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
@@ -1287,7 +1287,7 @@ public class VideoDetailFragment
                 .subscribe(state -> {
                     final int seconds = (int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime());
                     positionView.setMax((int) info.getDuration());
-                    positionView.setProgress(seconds);
+                    positionView.setProgressAnimated(seconds);
                     detailPositionView.setText(Localization.getDurationString(seconds));
                     animateView(positionView, true, 500);
                     animateView(detailPositionView, true, 500);
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java
index 53d549a46..d9c58fbf4 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java
@@ -101,7 +101,7 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
             updateFlags = 0;
         }
 
-        infoListAdapter.updateStates();
+        itemsList.post(infoListAdapter::updateStates);
     }
 
     /*//////////////////////////////////////////////////////////////////////////
diff --git a/app/src/main/java/org/schabi/newpipe/info_list/InfoListAdapter.java b/app/src/main/java/org/schabi/newpipe/info_list/InfoListAdapter.java
index 3cd06f3d6..7f5b07dbe 100644
--- a/app/src/main/java/org/schabi/newpipe/info_list/InfoListAdapter.java
+++ b/app/src/main/java/org/schabi/newpipe/info_list/InfoListAdapter.java
@@ -312,9 +312,26 @@ public class InfoListAdapter extends StateObjectsListAdapter {
         }
     }
 
+    @Override
+    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads) {
+        if (!payloads.isEmpty() && holder instanceof InfoItemHolder) {
+            for (Object payload : payloads) {
+                if (payload instanceof StreamStateEntity) {
+                    ((InfoItemHolder) holder).updateState(infoItemList.get(header == null ? position : position - 1),
+                            (StreamStateEntity) payload);
+                } else if (payload instanceof Boolean) {
+                    ((InfoItemHolder) holder).updateState(infoItemList.get(header == null ? position : position - 1),
+                            null);
+                }
+            }
+        } else {
+            onBindViewHolder(holder, position);
+        }
+    }
+
     @Override
     protected void onItemStateChanged(int position, @Nullable StreamStateEntity state) {
-        notifyItemChanged(header == null ? position : position + 1, state);
+        notifyItemChanged(header == null ? position : position + 1, state != null ? state : false);
     }
 
     public GridLayoutManager.SpanSizeLookup getSpanSizeLookup(final int spanCount) {
diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/InfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/InfoItemHolder.java
index 969d2682e..3bc0d9e54 100644
--- a/app/src/main/java/org/schabi/newpipe/info_list/holder/InfoItemHolder.java
+++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/InfoItemHolder.java
@@ -38,4 +38,7 @@ public abstract class InfoItemHolder extends RecyclerView.ViewHolder {
     }
 
     public abstract void updateFromItem(final InfoItem infoItem, @Nullable final StreamStateEntity state);
+
+    public void updateState(final InfoItem infoItem, @Nullable final StreamStateEntity state) {
+    }
 }
diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java
index a59cb009f..aa2a3f878 100644
--- a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java
+++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java
@@ -5,7 +5,6 @@ import android.support.v4.content.ContextCompat;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
-import android.widget.ProgressBar;
 import android.widget.TextView;
 
 import org.schabi.newpipe.R;
@@ -14,8 +13,10 @@ import org.schabi.newpipe.extractor.InfoItem;
 import org.schabi.newpipe.extractor.stream.StreamInfoItem;
 import org.schabi.newpipe.extractor.stream.StreamType;
 import org.schabi.newpipe.info_list.InfoItemBuilder;
+import org.schabi.newpipe.util.AnimationUtils;
 import org.schabi.newpipe.util.ImageDisplayConstants;
 import org.schabi.newpipe.util.Localization;
+import org.schabi.newpipe.views.AnimatedProgressBar;
 
 import java.util.concurrent.TimeUnit;
 
@@ -25,7 +26,7 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder {
     public final TextView itemVideoTitleView;
     public final TextView itemUploaderView;
     public final TextView itemDurationView;
-    public final ProgressBar itemProgressView;
+    public final AnimatedProgressBar itemProgressView;
 
     StreamMiniInfoItemHolder(InfoItemBuilder infoItemBuilder, int layoutId, ViewGroup parent) {
         super(infoItemBuilder, layoutId, parent);
@@ -99,6 +100,22 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder {
         }
     }
 
+    @Override
+    public void updateState(final InfoItem infoItem, @Nullable final StreamStateEntity state) {
+        final StreamInfoItem item = (StreamInfoItem) infoItem;
+        if (state != null && item.getDuration() > 0 && item.getStreamType() != StreamType.LIVE_STREAM) {
+            itemProgressView.setMax((int) item.getDuration());
+            if (itemProgressView.getVisibility() == View.VISIBLE) {
+                itemProgressView.setProgressAnimated((int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime()));
+            } else {
+                itemProgressView.setProgress((int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime()));
+                AnimationUtils.animateView(itemProgressView, true, 500);
+            }
+        } else if (itemProgressView.getVisibility() == View.VISIBLE) {
+            AnimationUtils.animateView(itemProgressView, false, 500);
+        }
+    }
+
     private void enableLongClick(final StreamInfoItem item) {
         itemView.setLongClickable(true);
         itemView.setOnLongClickListener(view -> {
diff --git a/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java b/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java
index 75d49e466..94672bd49 100644
--- a/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java
@@ -76,7 +76,8 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I>
             }
             updateFlags = 0;
         }
-        itemListAdapter.updateStates();
+
+        itemsList.post(itemListAdapter::updateStates);
     }
 
     /*//////////////////////////////////////////////////////////////////////////
diff --git a/app/src/main/java/org/schabi/newpipe/local/LocalItemListAdapter.java b/app/src/main/java/org/schabi/newpipe/local/LocalItemListAdapter.java
index 903712af2..d29e85ee3 100644
--- a/app/src/main/java/org/schabi/newpipe/local/LocalItemListAdapter.java
+++ b/app/src/main/java/org/schabi/newpipe/local/LocalItemListAdapter.java
@@ -285,9 +285,26 @@ public class LocalItemListAdapter extends StateObjectsListAdapter {
         }
     }
 
+    @Override
+    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads) {
+        if (!payloads.isEmpty() && holder instanceof LocalItemHolder) {
+            for (Object payload : payloads) {
+                if (payload instanceof StreamStateEntity) {
+                    ((LocalItemHolder) holder).updateState(localItems.get(header == null ? position : position - 1),
+                            (StreamStateEntity) payload);
+                } else if (payload instanceof Boolean) {
+                    ((LocalItemHolder) holder).updateState(localItems.get(header == null ? position : position - 1),
+                            null);
+                }
+            }
+        } else {
+            onBindViewHolder(holder, position);
+        }
+    }
+
     @Override
     protected void onItemStateChanged(int position, @Nullable StreamStateEntity state) {
-        notifyItemChanged(header == null ? position : position + 1, state);
+        notifyItemChanged(header == null ? position : position + 1, state != null ? state : false);
     }
 
     public GridLayoutManager.SpanSizeLookup getSpanSizeLookup(final int spanCount) {
diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalItemHolder.java
index 01af60f98..c00fa1fb4 100644
--- a/app/src/main/java/org/schabi/newpipe/local/holder/LocalItemHolder.java
+++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalItemHolder.java
@@ -41,4 +41,7 @@ public abstract class LocalItemHolder extends RecyclerView.ViewHolder {
     }
 
     public abstract void updateFromItem(final LocalItem item, @Nullable final StreamStateEntity state, final DateFormat dateFormat);
+
+    public void updateState(final LocalItem localItem, @Nullable final StreamStateEntity state) {
+    }
 }
diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamItemHolder.java
index 48bbbc81d..0c4e66c9d 100644
--- a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamItemHolder.java
+++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamItemHolder.java
@@ -6,7 +6,6 @@ import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
-import android.widget.ProgressBar;
 import android.widget.TextView;
 
 import org.schabi.newpipe.R;
@@ -15,8 +14,10 @@ import org.schabi.newpipe.database.playlist.PlaylistStreamEntry;
 import org.schabi.newpipe.database.stream.model.StreamStateEntity;
 import org.schabi.newpipe.extractor.NewPipe;
 import org.schabi.newpipe.local.LocalItemBuilder;
+import org.schabi.newpipe.util.AnimationUtils;
 import org.schabi.newpipe.util.ImageDisplayConstants;
 import org.schabi.newpipe.util.Localization;
+import org.schabi.newpipe.views.AnimatedProgressBar;
 
 import java.text.DateFormat;
 import java.util.concurrent.TimeUnit;
@@ -28,7 +29,7 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder {
     public final TextView itemAdditionalDetailsView;
     public final TextView itemDurationView;
     public final View itemHandleView;
-    public final ProgressBar itemProgressView;
+    public final AnimatedProgressBar itemProgressView;
 
     LocalPlaylistStreamItemHolder(LocalItemBuilder infoItemBuilder, int layoutId, ViewGroup parent) {
         super(infoItemBuilder, layoutId, parent);
@@ -92,6 +93,23 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder {
         itemHandleView.setOnTouchListener(getOnTouchListener(item));
     }
 
+    @Override
+    public void updateState(LocalItem localItem, @Nullable StreamStateEntity state) {
+        if (!(localItem instanceof PlaylistStreamEntry)) return;
+        final PlaylistStreamEntry item = (PlaylistStreamEntry) localItem;
+        if (state != null && item.duration > 0) {
+            itemProgressView.setMax((int) item.duration);
+            if (itemProgressView.getVisibility() == View.VISIBLE) {
+                itemProgressView.setProgressAnimated((int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime()));
+            } else {
+                itemProgressView.setProgress((int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime()));
+                AnimationUtils.animateView(itemProgressView, true, 500);
+            }
+        } else if (itemProgressView.getVisibility() == View.VISIBLE) {
+            AnimationUtils.animateView(itemProgressView, false, 500);
+        }
+    }
+
     private View.OnTouchListener getOnTouchListener(final PlaylistStreamEntry item) {
         return (view, motionEvent) -> {
             view.performClick();
diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java
index ac194b776..b24051a4f 100644
--- a/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java
+++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java
@@ -5,7 +5,6 @@ import android.support.v4.content.ContextCompat;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
-import android.widget.ProgressBar;
 import android.widget.TextView;
 
 import org.schabi.newpipe.R;
@@ -14,8 +13,10 @@ import org.schabi.newpipe.database.stream.StreamStatisticsEntry;
 import org.schabi.newpipe.database.stream.model.StreamStateEntity;
 import org.schabi.newpipe.extractor.NewPipe;
 import org.schabi.newpipe.local.LocalItemBuilder;
+import org.schabi.newpipe.util.AnimationUtils;
 import org.schabi.newpipe.util.ImageDisplayConstants;
 import org.schabi.newpipe.util.Localization;
+import org.schabi.newpipe.views.AnimatedProgressBar;
 
 import java.text.DateFormat;
 import java.util.concurrent.TimeUnit;
@@ -48,7 +49,7 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
     public final TextView itemDurationView;
     @Nullable
     public final TextView itemAdditionalDetails;
-    public final ProgressBar itemProgressView;
+    public final AnimatedProgressBar itemProgressView;
 
     public LocalStatisticStreamItemHolder(LocalItemBuilder itemBuilder, ViewGroup parent) {
         this(itemBuilder, R.layout.list_stream_item, parent);
@@ -121,4 +122,21 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
             return true;
         });
     }
+
+    @Override
+    public void updateState(LocalItem localItem, @Nullable StreamStateEntity state) {
+        if (!(localItem instanceof StreamStatisticsEntry)) return;
+        final StreamStatisticsEntry item = (StreamStatisticsEntry) localItem;
+        if (state != null && item.duration > 0) {
+            itemProgressView.setMax((int) item.duration);
+            if (itemProgressView.getVisibility() == View.VISIBLE) {
+                itemProgressView.setProgressAnimated((int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime()));
+            } else {
+                itemProgressView.setProgress((int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime()));
+                AnimationUtils.animateView(itemProgressView, true, 500);
+            }
+        } else if (itemProgressView.getVisibility() == View.VISIBLE) {
+            AnimationUtils.animateView(itemProgressView, false, 500);
+        }
+    }
 }
diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.java b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.java
index 364d50df6..b00ea05ea 100644
--- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.java
@@ -153,6 +153,8 @@ public class SubscriptionFragment extends BaseStateFragment<List<SubscriptionEnt
             }
             updateFlags = 0;
         }
+
+        itemsList.post(infoListAdapter::updateStates);
     }
 
     @Override
diff --git a/app/src/main/java/org/schabi/newpipe/views/AnimatedProgressBar.java b/app/src/main/java/org/schabi/newpipe/views/AnimatedProgressBar.java
index 39c6e707e..fe3e0d7bc 100644
--- a/app/src/main/java/org/schabi/newpipe/views/AnimatedProgressBar.java
+++ b/app/src/main/java/org/schabi/newpipe/views/AnimatedProgressBar.java
@@ -25,8 +25,7 @@ public final class AnimatedProgressBar extends ProgressBar {
 		super(context, attrs, defStyleAttr);
 	}
 
-	@Override
-	public synchronized void setProgress(int progress) {
+	public synchronized void setProgressAnimated(int progress) {
 		cancelAnimation();
 		animation = new ProgressBarAnimation(this, getProgress(), progress);
 		startAnimation(animation);
@@ -40,10 +39,6 @@ public final class AnimatedProgressBar extends ProgressBar {
 		clearAnimation();
 	}
 
-	private void setProgressInternal(int progress) {
-		super.setProgress(progress);
-	}
-
 	private static class ProgressBarAnimation extends Animation {
 
 		private final AnimatedProgressBar progressBar;
@@ -63,7 +58,7 @@ public final class AnimatedProgressBar extends ProgressBar {
 		protected void applyTransformation(float interpolatedTime, Transformation t) {
 			super.applyTransformation(interpolatedTime, t);
 			float value = from + (to - from) * interpolatedTime;
-			progressBar.setProgressInternal((int) value);
+			progressBar.setProgress((int) value);
 		}
 	}
 }
diff --git a/app/src/main/res/layout/list_stream_grid_item.xml b/app/src/main/res/layout/list_stream_grid_item.xml
index 7c918b27f..fc9235e8d 100644
--- a/app/src/main/res/layout/list_stream_grid_item.xml
+++ b/app/src/main/res/layout/list_stream_grid_item.xml
@@ -67,7 +67,7 @@
 		android:textSize="@dimen/video_item_search_uploader_text_size"
 		tools:text="Uploader"/>
 
-	<ProgressBar
+	<org.schabi.newpipe.views.AnimatedProgressBar
 		android:id="@+id/itemProgressView"
 		style="@style/Widget.AppCompat.ProgressBar.Horizontal"
 		android:progressDrawable="?progress_horizontal_drawable"
diff --git a/app/src/main/res/layout/list_stream_item.xml b/app/src/main/res/layout/list_stream_item.xml
index ccf325592..02e8f1531 100644
--- a/app/src/main/res/layout/list_stream_item.xml
+++ b/app/src/main/res/layout/list_stream_item.xml
@@ -80,7 +80,7 @@
         android:textSize="@dimen/video_item_search_upload_date_text_size"
         tools:text="2 years ago • 10M views"/>
 
-    <ProgressBar
+    <org.schabi.newpipe.views.AnimatedProgressBar
         android:id="@+id/itemProgressView"
         style="@style/Widget.AppCompat.ProgressBar.Horizontal"
         android:progressDrawable="?progress_horizontal_drawable"
diff --git a/app/src/main/res/layout/list_stream_mini_item.xml b/app/src/main/res/layout/list_stream_mini_item.xml
index 383580e59..667798128 100644
--- a/app/src/main/res/layout/list_stream_mini_item.xml
+++ b/app/src/main/res/layout/list_stream_mini_item.xml
@@ -70,7 +70,7 @@
         android:textSize="@dimen/video_item_search_uploader_text_size"
         tools:text="Uploader" />
 
-    <ProgressBar
+    <org.schabi.newpipe.views.AnimatedProgressBar
         android:id="@+id/itemProgressView"
         style="@style/Widget.AppCompat.ProgressBar.Horizontal"
         android:progressDrawable="?progress_horizontal_drawable"
diff --git a/app/src/main/res/layout/list_stream_playlist_item.xml b/app/src/main/res/layout/list_stream_playlist_item.xml
index 47c3ab93d..2747038f6 100644
--- a/app/src/main/res/layout/list_stream_playlist_item.xml
+++ b/app/src/main/res/layout/list_stream_playlist_item.xml
@@ -83,7 +83,7 @@
         android:textSize="@dimen/video_item_search_uploader_text_size"
         tools:text="Uploader" />
 
-    <ProgressBar
+    <org.schabi.newpipe.views.AnimatedProgressBar
         android:id="@+id/itemProgressView"
         style="@style/Widget.AppCompat.ProgressBar.Horizontal"
         android:progressDrawable="?progress_horizontal_drawable"