mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 15:23:00 +00:00 
			
		
		
		
	Merge pull request #5333 from Isira-Seneviratne/Convert_AnimationUtils_to_extensions
Convert AnimationUtils functions to extension functions.
This commit is contained in:
		| @@ -37,7 +37,7 @@ import icepick.State; | ||||
| import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; | ||||
| import io.reactivex.rxjava3.disposables.Disposable; | ||||
|  | ||||
| import static org.schabi.newpipe.util.AnimationUtils.animateView; | ||||
| import static org.schabi.newpipe.ktx.ViewUtils.animate; | ||||
|  | ||||
| public abstract class BaseStateFragment<I> extends BaseFragment implements ViewContract<I> { | ||||
|     @State | ||||
| @@ -131,35 +131,35 @@ public abstract class BaseStateFragment<I> extends BaseFragment implements ViewC | ||||
|     @Override | ||||
|     public void showLoading() { | ||||
|         if (emptyStateView != null) { | ||||
|             animateView(emptyStateView, false, 150); | ||||
|             animate(emptyStateView, false, 150); | ||||
|         } | ||||
|         if (loadingProgressBar != null) { | ||||
|             animateView(loadingProgressBar, true, 400); | ||||
|             animate(loadingProgressBar, true, 400); | ||||
|         } | ||||
|         animateView(errorPanelRoot, false, 150); | ||||
|         animate(errorPanelRoot, false, 150); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void hideLoading() { | ||||
|         if (emptyStateView != null) { | ||||
|             animateView(emptyStateView, false, 150); | ||||
|             animate(emptyStateView, false, 150); | ||||
|         } | ||||
|         if (loadingProgressBar != null) { | ||||
|             animateView(loadingProgressBar, false, 0); | ||||
|             animate(loadingProgressBar, false, 0); | ||||
|         } | ||||
|         animateView(errorPanelRoot, false, 150); | ||||
|         animate(errorPanelRoot, false, 150); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void showEmptyState() { | ||||
|         isLoading.set(false); | ||||
|         if (emptyStateView != null) { | ||||
|             animateView(emptyStateView, true, 200); | ||||
|             animate(emptyStateView, true, 200); | ||||
|         } | ||||
|         if (loadingProgressBar != null) { | ||||
|             animateView(loadingProgressBar, false, 0); | ||||
|             animate(loadingProgressBar, false, 0); | ||||
|         } | ||||
|         animateView(errorPanelRoot, false, 150); | ||||
|         animate(errorPanelRoot, false, 150); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -174,11 +174,11 @@ public abstract class BaseStateFragment<I> extends BaseFragment implements ViewC | ||||
|  | ||||
|         errorTextView.setText(message); | ||||
|         if (showRetryButton) { | ||||
|             animateView(errorButtonRetry, true, 600); | ||||
|             animate(errorButtonRetry, true, 600); | ||||
|         } else { | ||||
|             animateView(errorButtonRetry, false, 0); | ||||
|             animate(errorButtonRetry, false, 0); | ||||
|         } | ||||
|         animateView(errorPanelRoot, true, 300); | ||||
|         animate(errorPanelRoot, true, 300); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -76,11 +76,12 @@ import org.schabi.newpipe.fragments.BaseStateFragment; | ||||
| import org.schabi.newpipe.fragments.EmptyFragment; | ||||
| import org.schabi.newpipe.fragments.list.comments.CommentsFragment; | ||||
| import org.schabi.newpipe.fragments.list.videos.RelatedVideosFragment; | ||||
| import org.schabi.newpipe.ktx.AnimationType; | ||||
| import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; | ||||
| import org.schabi.newpipe.local.dialog.PlaylistCreationDialog; | ||||
| import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||
| import org.schabi.newpipe.player.Player; | ||||
| import org.schabi.newpipe.player.MainPlayer; | ||||
| import org.schabi.newpipe.player.Player; | ||||
| import org.schabi.newpipe.player.event.OnKeyDownListener; | ||||
| import org.schabi.newpipe.player.event.PlayerServiceExtendedEventListener; | ||||
| import org.schabi.newpipe.player.helper.PlayerHelper; | ||||
| @@ -125,7 +126,7 @@ import static org.schabi.newpipe.extractor.stream.StreamExtractor.NO_AGE_LIMIT; | ||||
| import static org.schabi.newpipe.player.helper.PlayerHelper.globalScreenOrientationLocked; | ||||
| import static org.schabi.newpipe.player.helper.PlayerHelper.isClearingQueueConfirmationRequired; | ||||
| import static org.schabi.newpipe.player.playqueue.PlayQueueItem.RECOVERY_UNSET; | ||||
| import static org.schabi.newpipe.util.AnimationUtils.animateView; | ||||
| import static org.schabi.newpipe.ktx.ViewUtils.animate; | ||||
| import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView; | ||||
|  | ||||
| public final class VideoDetailFragment | ||||
| @@ -745,8 +746,10 @@ public final class VideoDetailFragment | ||||
|             } | ||||
|  | ||||
|             if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { | ||||
|                 animateView(appendControlsDetail, true, 250, 0, () -> | ||||
|                         animateView(appendControlsDetail, false, 1500, 1000)); | ||||
|                 animate(appendControlsDetail, true, 250, AnimationType.ALPHA, | ||||
|                         0, () -> | ||||
|                         animate(appendControlsDetail, false, 1500, | ||||
|                                 AnimationType.ALPHA, 1000)); | ||||
|             } | ||||
|             return false; | ||||
|         }; | ||||
| @@ -1334,8 +1337,8 @@ public final class VideoDetailFragment | ||||
|  | ||||
|         thumbnailImageView.setImageDrawable( | ||||
|                 AppCompatResources.getDrawable(requireContext(), imageResource)); | ||||
|         animateView(thumbnailImageView, false, 0, 0, | ||||
|                 () -> animateView(thumbnailImageView, true, 500)); | ||||
|         animate(thumbnailImageView, false, 0, AnimationType.ALPHA, 0, | ||||
|                 () -> animate(thumbnailImageView, true, 500)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -1417,14 +1420,14 @@ public final class VideoDetailFragment | ||||
|             contentRootLayoutHiding.setVisibility(View.INVISIBLE); | ||||
|         } | ||||
|  | ||||
|         animateView(thumbnailPlayButton, false, 50); | ||||
|         animateView(detailDurationView, false, 100); | ||||
|         animateView(detailPositionView, false, 100); | ||||
|         animateView(positionView, false, 50); | ||||
|         animate(thumbnailPlayButton, false, 50); | ||||
|         animate(detailDurationView, false, 100); | ||||
|         animate(detailPositionView, false, 100); | ||||
|         animate(positionView, false, 50); | ||||
|  | ||||
|         videoTitleTextView.setText(title); | ||||
|         videoTitleTextView.setMaxLines(1); | ||||
|         animateView(videoTitleTextView, true, 0); | ||||
|         animate(videoTitleTextView, true, 0); | ||||
|  | ||||
|         videoDescriptionRootLayout.setVisibility(View.GONE); | ||||
|         videoTitleToggleArrow.setVisibility(View.GONE); | ||||
| @@ -1466,7 +1469,7 @@ public final class VideoDetailFragment | ||||
|                         player != null && player.isFullscreen() ? View.GONE : View.VISIBLE); | ||||
|             } | ||||
|         } | ||||
|         animateView(thumbnailPlayButton, true, 200); | ||||
|         animate(thumbnailPlayButton, true, 200); | ||||
|         videoTitleTextView.setText(title); | ||||
|  | ||||
|         if (!isEmpty(info.getSubChannelName())) { | ||||
| @@ -1530,12 +1533,12 @@ public final class VideoDetailFragment | ||||
|             detailDurationView.setText(Localization.getDurationString(info.getDuration())); | ||||
|             detailDurationView.setBackgroundColor( | ||||
|                     ContextCompat.getColor(activity, R.color.duration_background_color)); | ||||
|             animateView(detailDurationView, true, 100); | ||||
|             animate(detailDurationView, true, 100); | ||||
|         } else if (info.getStreamType() == StreamType.LIVE_STREAM) { | ||||
|             detailDurationView.setText(R.string.duration_live); | ||||
|             detailDurationView.setBackgroundColor( | ||||
|                     ContextCompat.getColor(activity, R.color.live_duration_background_color)); | ||||
|             animateView(detailDurationView, true, 100); | ||||
|             animate(detailDurationView, true, 100); | ||||
|         } else { | ||||
|             detailDurationView.setVisibility(View.GONE); | ||||
|         } | ||||
| @@ -1703,8 +1706,8 @@ public final class VideoDetailFragment | ||||
|                 // Show saved position from backStack if user allows it | ||||
|                 showPlaybackProgress(playQueue.getItem().getRecoveryPosition(), | ||||
|                         playQueue.getItem().getDuration() * 1000); | ||||
|                 animateView(positionView, true, 500); | ||||
|                 animateView(detailPositionView, true, 500); | ||||
|                 animate(positionView, true, 500); | ||||
|                 animate(detailPositionView, true, 500); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
| @@ -1718,8 +1721,8 @@ public final class VideoDetailFragment | ||||
|                 .observeOn(AndroidSchedulers.mainThread()) | ||||
|                 .subscribe(state -> { | ||||
|                     showPlaybackProgress(state.getProgressTime(), info.getDuration() * 1000); | ||||
|                     animateView(positionView, true, 500); | ||||
|                     animateView(detailPositionView, true, 500); | ||||
|                     animate(positionView, true, 500); | ||||
|                     animate(detailPositionView, true, 500); | ||||
|                 }, e -> { | ||||
|                     if (DEBUG) { | ||||
|                         e.printStackTrace(); | ||||
| @@ -1747,8 +1750,8 @@ public final class VideoDetailFragment | ||||
|             detailPositionView.setText(position); | ||||
|         } | ||||
|         if (positionView.getVisibility() != View.VISIBLE) { | ||||
|             animateView(positionView, true, 100); | ||||
|             animateView(detailPositionView, true, 100); | ||||
|             animate(positionView, true, 100); | ||||
|             animate(detailPositionView, true, 100); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -1802,8 +1805,8 @@ public final class VideoDetailFragment | ||||
|                         && player.getPlayQueue() != null | ||||
|                         && player.getPlayQueue().getItem() != null | ||||
|                         && player.getPlayQueue().getItem().getUrl().equals(url)) { | ||||
|                     animateView(positionView, true, 100); | ||||
|                     animateView(detailPositionView, true, 100); | ||||
|                     animate(positionView, true, 100); | ||||
|                     animate(detailPositionView, true, 100); | ||||
|                 } | ||||
|                 break; | ||||
|         } | ||||
|   | ||||
| @@ -46,7 +46,7 @@ import java.util.Arrays; | ||||
| import java.util.List; | ||||
| import java.util.Queue; | ||||
|  | ||||
| import static org.schabi.newpipe.util.AnimationUtils.animateView; | ||||
| import static org.schabi.newpipe.ktx.ViewUtils.animate; | ||||
|  | ||||
| public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> | ||||
|         implements ListViewContract<I, N>, StateSaver.WriteRead, | ||||
| @@ -406,23 +406,17 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> | ||||
|     // Contract | ||||
|     //////////////////////////////////////////////////////////////////////////*/ | ||||
|  | ||||
|     @Override | ||||
|     public void showLoading() { | ||||
|         super.showLoading(); | ||||
|         // animateView(itemsList, false, 400); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void hideLoading() { | ||||
|         super.hideLoading(); | ||||
|         animateView(itemsList, true, 300); | ||||
|         animate(itemsList, true, 300); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void showError(final String message, final boolean showRetryButton) { | ||||
|         super.showError(message, showRetryButton); | ||||
|         showListFooter(false); | ||||
|         animateView(itemsList, false, 200); | ||||
|         animate(itemsList, false, 200); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -37,12 +37,12 @@ import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException; | ||||
| import org.schabi.newpipe.extractor.exceptions.ExtractionException; | ||||
| import org.schabi.newpipe.extractor.stream.StreamInfoItem; | ||||
| import org.schabi.newpipe.fragments.list.BaseListInfoFragment; | ||||
| import org.schabi.newpipe.ktx.AnimationType; | ||||
| import org.schabi.newpipe.local.subscription.SubscriptionManager; | ||||
| import org.schabi.newpipe.player.playqueue.ChannelPlayQueue; | ||||
| import org.schabi.newpipe.player.playqueue.PlayQueue; | ||||
| import org.schabi.newpipe.report.ErrorActivity; | ||||
| import org.schabi.newpipe.report.UserAction; | ||||
| import org.schabi.newpipe.util.AnimationUtils; | ||||
| import org.schabi.newpipe.util.ExtractorHelper; | ||||
| import org.schabi.newpipe.util.ImageDisplayConstants; | ||||
| import org.schabi.newpipe.util.Localization; | ||||
| @@ -64,9 +64,9 @@ import io.reactivex.rxjava3.functions.Consumer; | ||||
| import io.reactivex.rxjava3.functions.Function; | ||||
| import io.reactivex.rxjava3.schedulers.Schedulers; | ||||
|  | ||||
| import static org.schabi.newpipe.util.AnimationUtils.animateBackgroundColor; | ||||
| import static org.schabi.newpipe.util.AnimationUtils.animateTextColor; | ||||
| import static org.schabi.newpipe.util.AnimationUtils.animateView; | ||||
| import static org.schabi.newpipe.ktx.TextViewUtils.animateTextColor; | ||||
| import static org.schabi.newpipe.ktx.ViewUtils.animate; | ||||
| import static org.schabi.newpipe.ktx.ViewUtils.animateBackgroundColor; | ||||
|  | ||||
| public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> | ||||
|         implements View.OnClickListener { | ||||
| @@ -224,7 +224,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> | ||||
|  | ||||
|     private void monitorSubscription(final ChannelInfo info) { | ||||
|         final Consumer<Throwable> onError = (Throwable throwable) -> { | ||||
|             animateView(headerBinding.channelSubscribeButton, false, 100); | ||||
|             animate(headerBinding.channelSubscribeButton, false, 100); | ||||
|             showSnackBarError(throwable, UserAction.SUBSCRIPTION, | ||||
|                     NewPipe.getNameOfService(currentInfo.getServiceId()), | ||||
|                     "Get subscription status", 0); | ||||
| @@ -379,8 +379,8 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> | ||||
|                     subscribedText); | ||||
|         } | ||||
|  | ||||
|         animateView(headerBinding.channelSubscribeButton, AnimationUtils.Type.LIGHT_SCALE_AND_ALPHA, | ||||
|                 true, 100); | ||||
|         animate(headerBinding.channelSubscribeButton, true, 100, | ||||
|                 AnimationType.LIGHT_SCALE_AND_ALPHA); | ||||
|     } | ||||
|  | ||||
|     /*////////////////////////////////////////////////////////////////////////// | ||||
| @@ -436,7 +436,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> | ||||
|         IMAGE_LOADER.cancelDisplayTask(headerBinding.channelBannerImage); | ||||
|         IMAGE_LOADER.cancelDisplayTask(headerBinding.channelAvatarView); | ||||
|         IMAGE_LOADER.cancelDisplayTask(headerBinding.subChannelAvatarView); | ||||
|         animateView(headerBinding.channelSubscribeButton, false, 100); | ||||
|         animate(headerBinding.channelSubscribeButton, false, 100); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -16,8 +16,8 @@ import org.schabi.newpipe.extractor.ListExtractor; | ||||
| import org.schabi.newpipe.extractor.NewPipe; | ||||
| import org.schabi.newpipe.extractor.comments.CommentsInfo; | ||||
| import org.schabi.newpipe.fragments.list.BaseListInfoFragment; | ||||
| import org.schabi.newpipe.ktx.ViewUtils; | ||||
| import org.schabi.newpipe.report.UserAction; | ||||
| import org.schabi.newpipe.util.AnimationUtils; | ||||
| import org.schabi.newpipe.util.ExtractorHelper; | ||||
|  | ||||
| import io.reactivex.rxjava3.core.Single; | ||||
| @@ -84,16 +84,14 @@ public class CommentsFragment extends BaseListInfoFragment<CommentsInfo> { | ||||
|     public void handleResult(@NonNull final CommentsInfo result) { | ||||
|         super.handleResult(result); | ||||
|  | ||||
|         AnimationUtils.slideUp(requireView(), 120, 150, 0.06f); | ||||
|         ViewUtils.slideUp(requireView(), 120, 150, 0.06f); | ||||
|  | ||||
|         if (!result.getErrors().isEmpty()) { | ||||
|             showSnackBarError(result.getErrors(), UserAction.REQUESTED_COMMENTS, | ||||
|                     NewPipe.getNameOfService(result.getServiceId()), result.getUrl(), 0); | ||||
|         } | ||||
|  | ||||
|         if (disposables != null) { | ||||
|             disposables.clear(); | ||||
|         } | ||||
|         disposables.clear(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -28,7 +28,7 @@ import org.schabi.newpipe.util.Localization; | ||||
| import icepick.State; | ||||
| import io.reactivex.rxjava3.core.Single; | ||||
|  | ||||
| import static org.schabi.newpipe.util.AnimationUtils.animateView; | ||||
| import static org.schabi.newpipe.ktx.ViewUtils.animate; | ||||
|  | ||||
| /** | ||||
|  * Created by Christian Schabesberger on 23.09.17. | ||||
| @@ -160,7 +160,7 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> { | ||||
|     @Override | ||||
|     public void showLoading() { | ||||
|         super.showLoading(); | ||||
|         animateView(itemsList, false, 100); | ||||
|         animate(itemsList, false, 100); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -61,7 +61,7 @@ import io.reactivex.rxjava3.core.Single; | ||||
| import io.reactivex.rxjava3.disposables.CompositeDisposable; | ||||
| import io.reactivex.rxjava3.disposables.Disposable; | ||||
|  | ||||
| import static org.schabi.newpipe.util.AnimationUtils.animateView; | ||||
| import static org.schabi.newpipe.ktx.ViewUtils.animate; | ||||
| import static org.schabi.newpipe.util.ThemeHelper.resolveResourceIdFromAttr; | ||||
|  | ||||
| public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> { | ||||
| @@ -261,19 +261,19 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> { | ||||
|     @Override | ||||
|     public void showLoading() { | ||||
|         super.showLoading(); | ||||
|         animateView(headerBinding.getRoot(), false, 200); | ||||
|         animateView(itemsList, false, 100); | ||||
|         animate(headerBinding.getRoot(), false, 200); | ||||
|         animate(itemsList, false, 100); | ||||
|  | ||||
|         IMAGE_LOADER.cancelDisplayTask(headerBinding.uploaderAvatarView); | ||||
|         animateView(headerBinding.uploaderLayout, false, 200); | ||||
|         animate(headerBinding.uploaderLayout, false, 200); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void handleResult(@NonNull final PlaylistInfo result) { | ||||
|         super.handleResult(result); | ||||
|  | ||||
|         animateView(headerBinding.getRoot(), true, 100); | ||||
|         animateView(headerBinding.uploaderLayout, true, 300); | ||||
|         animate(headerBinding.getRoot(), true, 100); | ||||
|         animate(headerBinding.uploaderLayout, true, 300); | ||||
|         headerBinding.uploaderLayout.setOnClickListener(null); | ||||
|         // If we have an uploader put them into the UI | ||||
|         if (!TextUtils.isEmpty(result.getUploaderName())) { | ||||
|   | ||||
| @@ -51,12 +51,12 @@ import org.schabi.newpipe.extractor.services.peertube.linkHandler.PeertubeSearch | ||||
| import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory; | ||||
| import org.schabi.newpipe.fragments.BackPressable; | ||||
| import org.schabi.newpipe.fragments.list.BaseListFragment; | ||||
| import org.schabi.newpipe.ktx.AnimationType; | ||||
| import org.schabi.newpipe.ktx.ExceptionUtils; | ||||
| import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||
| import org.schabi.newpipe.report.ErrorActivity; | ||||
| import org.schabi.newpipe.report.ErrorInfo; | ||||
| import org.schabi.newpipe.report.UserAction; | ||||
| import org.schabi.newpipe.util.AnimationUtils; | ||||
| import org.schabi.newpipe.util.Constants; | ||||
| import org.schabi.newpipe.util.DeviceUtils; | ||||
| import org.schabi.newpipe.util.ExtractorHelper; | ||||
| @@ -82,7 +82,7 @@ import io.reactivex.rxjava3.subjects.PublishSubject; | ||||
|  | ||||
| import static androidx.recyclerview.widget.ItemTouchHelper.Callback.makeMovementFlags; | ||||
| import static java.util.Arrays.asList; | ||||
| import static org.schabi.newpipe.util.AnimationUtils.animateView; | ||||
| import static org.schabi.newpipe.ktx.ViewUtils.animate; | ||||
| import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView; | ||||
|  | ||||
| public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.InfoItemsPage<?>> | ||||
| @@ -413,7 +413,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|                 searchEditText.setText(""); | ||||
|                 showKeyboardSearch(); | ||||
|             } | ||||
|             animateView(errorPanelRoot, false, 200); | ||||
|             animate(errorPanelRoot, false, 200); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -644,8 +644,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|             Log.d(TAG, "showSuggestionsPanel() called"); | ||||
|         } | ||||
|         suggestionsPanelVisible = true; | ||||
|         animateView(searchBinding.suggestionsPanel, AnimationUtils.Type.LIGHT_SLIDE_AND_ALPHA, | ||||
|                 true, 200); | ||||
|         animate(searchBinding.suggestionsPanel, true, 200, | ||||
|                 AnimationType.LIGHT_SLIDE_AND_ALPHA); | ||||
|     } | ||||
|  | ||||
|     private void hideSuggestionsPanel() { | ||||
| @@ -653,8 +653,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|             Log.d(TAG, "hideSuggestionsPanel() called"); | ||||
|         } | ||||
|         suggestionsPanelVisible = false; | ||||
|         animateView(searchBinding.suggestionsPanel, AnimationUtils.Type.LIGHT_SLIDE_AND_ALPHA, | ||||
|                 false, 200); | ||||
|         animate(searchBinding.suggestionsPanel, false, 200, | ||||
|                 AnimationType.LIGHT_SLIDE_AND_ALPHA); | ||||
|     } | ||||
|  | ||||
|     private void showKeyboardSearch() { | ||||
|   | ||||
| @@ -20,8 +20,8 @@ import org.schabi.newpipe.extractor.ListExtractor; | ||||
| import org.schabi.newpipe.extractor.NewPipe; | ||||
| import org.schabi.newpipe.extractor.stream.StreamInfo; | ||||
| import org.schabi.newpipe.fragments.list.BaseListInfoFragment; | ||||
| import org.schabi.newpipe.ktx.ViewUtils; | ||||
| import org.schabi.newpipe.report.UserAction; | ||||
| import org.schabi.newpipe.util.AnimationUtils; | ||||
| import org.schabi.newpipe.util.RelatedStreamInfo; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| @@ -123,7 +123,7 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf | ||||
|         if (headerBinding != null) { | ||||
|             headerBinding.getRoot().setVisibility(View.VISIBLE); | ||||
|         } | ||||
|         AnimationUtils.slideUp(getView(), 120, 96, 0.06f); | ||||
|         ViewUtils.slideUp(requireView(), 120, 96, 0.06f); | ||||
|  | ||||
|         if (!result.getErrors().isEmpty()) { | ||||
|             showSnackBarError(result.getErrors(), UserAction.REQUESTED_STREAM, | ||||
|   | ||||
| @@ -13,8 +13,8 @@ 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.ktx.ViewUtils; | ||||
| import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||
| import org.schabi.newpipe.util.AnimationUtils; | ||||
| import org.schabi.newpipe.util.ImageDisplayConstants; | ||||
| import org.schabi.newpipe.util.Localization; | ||||
| import org.schabi.newpipe.views.AnimatedProgressBar; | ||||
| @@ -125,10 +125,10 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { | ||||
|             } else { | ||||
|                 itemProgressView.setProgress((int) TimeUnit.MILLISECONDS | ||||
|                         .toSeconds(state.getProgressTime())); | ||||
|                 AnimationUtils.animateView(itemProgressView, true, 500); | ||||
|                 ViewUtils.animate(itemProgressView, true, 500); | ||||
|             } | ||||
|         } else if (itemProgressView.getVisibility() == View.VISIBLE) { | ||||
|             AnimationUtils.animateView(itemProgressView, false, 500); | ||||
|             ViewUtils.animate(itemProgressView, false, 500); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
							
								
								
									
										47
									
								
								app/src/main/java/org/schabi/newpipe/ktx/TextView.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								app/src/main/java/org/schabi/newpipe/ktx/TextView.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| @file:JvmName("TextViewUtils") | ||||
|  | ||||
| package org.schabi.newpipe.ktx | ||||
|  | ||||
| import android.animation.Animator | ||||
| import android.animation.AnimatorListenerAdapter | ||||
| import android.animation.ArgbEvaluator | ||||
| import android.animation.ValueAnimator | ||||
| import android.util.Log | ||||
| import android.widget.TextView | ||||
| import androidx.annotation.ColorInt | ||||
| import androidx.interpolator.view.animation.FastOutSlowInInterpolator | ||||
| import org.schabi.newpipe.MainActivity | ||||
|  | ||||
| private const val TAG = "TextViewUtils" | ||||
|  | ||||
| /** | ||||
|  * Animate the text color of any view that extends [TextView] (Buttons, EditText...). | ||||
|  * | ||||
|  * @param duration   the duration of the animation | ||||
|  * @param colorStart the text color to start with | ||||
|  * @param colorEnd   the text color to end with | ||||
|  */ | ||||
| fun TextView.animateTextColor(duration: Long, @ColorInt colorStart: Int, @ColorInt colorEnd: Int) { | ||||
|     if (MainActivity.DEBUG) { | ||||
|         Log.d( | ||||
|             TAG, | ||||
|             "animateTextColor() called with: " + | ||||
|                 "view = [" + this + "], duration = [" + duration + "], " + | ||||
|                 "colorStart = [" + colorStart + "], colorEnd = [" + colorEnd + "]" | ||||
|         ) | ||||
|     } | ||||
|     val viewPropertyAnimator = ValueAnimator.ofObject(ArgbEvaluator(), colorStart, colorEnd) | ||||
|     viewPropertyAnimator.interpolator = FastOutSlowInInterpolator() | ||||
|     viewPropertyAnimator.duration = duration | ||||
|     viewPropertyAnimator.addUpdateListener { setTextColor(it.animatedValue as Int) } | ||||
|     viewPropertyAnimator.addListener(object : AnimatorListenerAdapter() { | ||||
|         override fun onAnimationEnd(animation: Animator) { | ||||
|             setTextColor(colorEnd) | ||||
|         } | ||||
|  | ||||
|         override fun onAnimationCancel(animation: Animator) { | ||||
|             setTextColor(colorEnd) | ||||
|         } | ||||
|     }) | ||||
|     viewPropertyAnimator.start() | ||||
| } | ||||
							
								
								
									
										324
									
								
								app/src/main/java/org/schabi/newpipe/ktx/View.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										324
									
								
								app/src/main/java/org/schabi/newpipe/ktx/View.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,324 @@ | ||||
| @file:JvmName("ViewUtils") | ||||
|  | ||||
| package org.schabi.newpipe.ktx | ||||
|  | ||||
| import android.animation.Animator | ||||
| import android.animation.AnimatorListenerAdapter | ||||
| import android.animation.ArgbEvaluator | ||||
| import android.animation.ValueAnimator | ||||
| import android.content.res.ColorStateList | ||||
| import android.util.Log | ||||
| import android.view.View | ||||
| import androidx.annotation.ColorInt | ||||
| import androidx.annotation.FloatRange | ||||
| import androidx.core.view.ViewCompat | ||||
| import androidx.core.view.isGone | ||||
| import androidx.core.view.isInvisible | ||||
| import androidx.core.view.isVisible | ||||
| import androidx.interpolator.view.animation.FastOutSlowInInterpolator | ||||
| import org.schabi.newpipe.MainActivity | ||||
|  | ||||
| private const val TAG = "ViewUtils" | ||||
|  | ||||
| inline var View.backgroundTintListCompat: ColorStateList? | ||||
|     get() = ViewCompat.getBackgroundTintList(this) | ||||
|     set(value) = ViewCompat.setBackgroundTintList(this, value) | ||||
|  | ||||
| /** | ||||
|  * Animate the view. | ||||
|  * | ||||
|  * @param enterOrExit   true to enter, false to exit | ||||
|  * @param duration      how long the animation will take, in milliseconds | ||||
|  * @param animationType Type of the animation | ||||
|  * @param delay         how long the animation will wait to start, in milliseconds | ||||
|  * @param execOnEnd     runnable that will be executed when the animation ends | ||||
|  */ | ||||
| @JvmOverloads | ||||
| fun View.animate( | ||||
|     enterOrExit: Boolean, | ||||
|     duration: Long, | ||||
|     animationType: AnimationType = AnimationType.ALPHA, | ||||
|     delay: Long = 0, | ||||
|     execOnEnd: Runnable? = null | ||||
| ) { | ||||
|     if (MainActivity.DEBUG) { | ||||
|         val id = try { | ||||
|             resources.getResourceEntryName(id) | ||||
|         } catch (e: Exception) { | ||||
|             id.toString() + "" | ||||
|         } | ||||
|         val msg = String.format( | ||||
|             "%8s →  [%s:%s] [%s %s:%s] execOnEnd=%s", enterOrExit, | ||||
|             javaClass.simpleName, id, animationType, duration, delay, execOnEnd | ||||
|         ) | ||||
|         Log.d(TAG, "animate(): $msg") | ||||
|     } | ||||
|     if (isVisible && enterOrExit) { | ||||
|         if (MainActivity.DEBUG) { | ||||
|             Log.d(TAG, "animate(): view was already visible > view = [$this]") | ||||
|         } | ||||
|         animate().setListener(null).cancel() | ||||
|         isVisible = true | ||||
|         alpha = 1f | ||||
|         execOnEnd?.run() | ||||
|         return | ||||
|     } else if ((isGone || isInvisible) && !enterOrExit) { | ||||
|         if (MainActivity.DEBUG) { | ||||
|             Log.d(TAG, "animate(): view was already gone > view = [$this]") | ||||
|         } | ||||
|         animate().setListener(null).cancel() | ||||
|         isGone = true | ||||
|         alpha = 0f | ||||
|         execOnEnd?.run() | ||||
|         return | ||||
|     } | ||||
|     animate().setListener(null).cancel() | ||||
|     isVisible = true | ||||
|     when (animationType) { | ||||
|         AnimationType.ALPHA -> animateAlpha(enterOrExit, duration, delay, execOnEnd) | ||||
|         AnimationType.SCALE_AND_ALPHA -> animateScaleAndAlpha(enterOrExit, duration, delay, execOnEnd) | ||||
|         AnimationType.LIGHT_SCALE_AND_ALPHA -> animateLightScaleAndAlpha(enterOrExit, duration, delay, execOnEnd) | ||||
|         AnimationType.SLIDE_AND_ALPHA -> animateSlideAndAlpha(enterOrExit, duration, delay, execOnEnd) | ||||
|         AnimationType.LIGHT_SLIDE_AND_ALPHA -> animateLightSlideAndAlpha(enterOrExit, duration, delay, execOnEnd) | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Animate the background color of a view. | ||||
|  * | ||||
|  * @param duration   the duration of the animation | ||||
|  * @param colorStart the background color to start with | ||||
|  * @param colorEnd   the background color to end with | ||||
|  */ | ||||
| fun View.animateBackgroundColor(duration: Long, @ColorInt colorStart: Int, @ColorInt colorEnd: Int) { | ||||
|     if (MainActivity.DEBUG) { | ||||
|         Log.d( | ||||
|             TAG, | ||||
|             "animateBackgroundColor() called with: " + | ||||
|                 "view = [" + this + "], duration = [" + duration + "], " + | ||||
|                 "colorStart = [" + colorStart + "], colorEnd = [" + colorEnd + "]" | ||||
|         ) | ||||
|     } | ||||
|     val empty = arrayOf(IntArray(0)) | ||||
|     val viewPropertyAnimator = ValueAnimator.ofObject(ArgbEvaluator(), colorStart, colorEnd) | ||||
|     viewPropertyAnimator.interpolator = FastOutSlowInInterpolator() | ||||
|     viewPropertyAnimator.duration = duration | ||||
|     viewPropertyAnimator.addUpdateListener { animation: ValueAnimator -> | ||||
|         backgroundTintListCompat = ColorStateList(empty, intArrayOf(animation.animatedValue as Int)) | ||||
|     } | ||||
|     viewPropertyAnimator.addListener(object : AnimatorListenerAdapter() { | ||||
|         override fun onAnimationEnd(animation: Animator) { | ||||
|             backgroundTintListCompat = ColorStateList(empty, intArrayOf(colorEnd)) | ||||
|         } | ||||
|  | ||||
|         override fun onAnimationCancel(animation: Animator) { | ||||
|             onAnimationEnd(animation) | ||||
|         } | ||||
|     }) | ||||
|     viewPropertyAnimator.start() | ||||
| } | ||||
|  | ||||
| fun View.animateHeight(duration: Long, targetHeight: Int): ValueAnimator { | ||||
|     if (MainActivity.DEBUG) { | ||||
|         Log.d( | ||||
|             TAG, | ||||
|             "animateHeight: duration = [" + duration + "], " + | ||||
|                 "from " + height + " to → " + targetHeight + " in: " + this | ||||
|         ) | ||||
|     } | ||||
|     val animator = ValueAnimator.ofFloat(height.toFloat(), targetHeight.toFloat()) | ||||
|     animator.interpolator = FastOutSlowInInterpolator() | ||||
|     animator.duration = duration | ||||
|     animator.addUpdateListener { animation: ValueAnimator -> | ||||
|         val value = animation.animatedValue as Float | ||||
|         layoutParams.height = value.toInt() | ||||
|         requestLayout() | ||||
|     } | ||||
|     animator.addListener(object : AnimatorListenerAdapter() { | ||||
|         override fun onAnimationEnd(animation: Animator) { | ||||
|             layoutParams.height = targetHeight | ||||
|             requestLayout() | ||||
|         } | ||||
|  | ||||
|         override fun onAnimationCancel(animation: Animator) { | ||||
|             layoutParams.height = targetHeight | ||||
|             requestLayout() | ||||
|         } | ||||
|     }) | ||||
|     animator.start() | ||||
|     return animator | ||||
| } | ||||
|  | ||||
| fun View.animateRotation(duration: Long, targetRotation: Int) { | ||||
|     if (MainActivity.DEBUG) { | ||||
|         Log.d( | ||||
|             TAG, | ||||
|             "animateRotation: duration = [" + duration + "], " + | ||||
|                 "from " + rotation + " to → " + targetRotation + " in: " + this | ||||
|         ) | ||||
|     } | ||||
|     animate().setListener(null).cancel() | ||||
|     animate() | ||||
|         .rotation(targetRotation.toFloat()).setDuration(duration) | ||||
|         .setInterpolator(FastOutSlowInInterpolator()) | ||||
|         .setListener(object : AnimatorListenerAdapter() { | ||||
|             override fun onAnimationCancel(animation: Animator) { | ||||
|                 rotation = targetRotation.toFloat() | ||||
|             } | ||||
|  | ||||
|             override fun onAnimationEnd(animation: Animator) { | ||||
|                 rotation = targetRotation.toFloat() | ||||
|             } | ||||
|         }).start() | ||||
| } | ||||
|  | ||||
| private fun View.animateAlpha(enterOrExit: Boolean, duration: Long, delay: Long, execOnEnd: Runnable?) { | ||||
|     if (enterOrExit) { | ||||
|         animate().setInterpolator(FastOutSlowInInterpolator()).alpha(1f) | ||||
|             .setDuration(duration).setStartDelay(delay) | ||||
|             .setListener(object : AnimatorListenerAdapter() { | ||||
|                 override fun onAnimationEnd(animation: Animator) { | ||||
|                     execOnEnd?.run() | ||||
|                 } | ||||
|             }).start() | ||||
|     } else { | ||||
|         animate().setInterpolator(FastOutSlowInInterpolator()).alpha(0f) | ||||
|             .setDuration(duration).setStartDelay(delay) | ||||
|             .setListener(object : AnimatorListenerAdapter() { | ||||
|                 override fun onAnimationEnd(animation: Animator) { | ||||
|                     isGone = true | ||||
|                     execOnEnd?.run() | ||||
|                 } | ||||
|             }).start() | ||||
|     } | ||||
| } | ||||
|  | ||||
| private fun View.animateScaleAndAlpha(enterOrExit: Boolean, duration: Long, delay: Long, execOnEnd: Runnable?) { | ||||
|     if (enterOrExit) { | ||||
|         scaleX = .8f | ||||
|         scaleY = .8f | ||||
|         animate() | ||||
|             .setInterpolator(FastOutSlowInInterpolator()) | ||||
|             .alpha(1f).scaleX(1f).scaleY(1f) | ||||
|             .setDuration(duration).setStartDelay(delay) | ||||
|             .setListener(object : AnimatorListenerAdapter() { | ||||
|                 override fun onAnimationEnd(animation: Animator) { | ||||
|                     execOnEnd?.run() | ||||
|                 } | ||||
|             }).start() | ||||
|     } else { | ||||
|         scaleX = 1f | ||||
|         scaleY = 1f | ||||
|         animate() | ||||
|             .setInterpolator(FastOutSlowInInterpolator()) | ||||
|             .alpha(0f).scaleX(.8f).scaleY(.8f) | ||||
|             .setDuration(duration).setStartDelay(delay) | ||||
|             .setListener(object : AnimatorListenerAdapter() { | ||||
|                 override fun onAnimationEnd(animation: Animator) { | ||||
|                     isGone = true | ||||
|                     execOnEnd?.run() | ||||
|                 } | ||||
|             }).start() | ||||
|     } | ||||
| } | ||||
|  | ||||
| private fun View.animateLightScaleAndAlpha(enterOrExit: Boolean, duration: Long, delay: Long, execOnEnd: Runnable?) { | ||||
|     if (enterOrExit) { | ||||
|         alpha = .5f | ||||
|         scaleX = .95f | ||||
|         scaleY = .95f | ||||
|         animate() | ||||
|             .setInterpolator(FastOutSlowInInterpolator()) | ||||
|             .alpha(1f).scaleX(1f).scaleY(1f) | ||||
|             .setDuration(duration).setStartDelay(delay) | ||||
|             .setListener(object : AnimatorListenerAdapter() { | ||||
|                 override fun onAnimationEnd(animation: Animator) { | ||||
|                     execOnEnd?.run() | ||||
|                 } | ||||
|             }).start() | ||||
|     } else { | ||||
|         alpha = 1f | ||||
|         scaleX = 1f | ||||
|         scaleY = 1f | ||||
|         animate() | ||||
|             .setInterpolator(FastOutSlowInInterpolator()) | ||||
|             .alpha(0f).scaleX(.95f).scaleY(.95f) | ||||
|             .setDuration(duration).setStartDelay(delay) | ||||
|             .setListener(object : AnimatorListenerAdapter() { | ||||
|                 override fun onAnimationEnd(animation: Animator) { | ||||
|                     isGone = true | ||||
|                     execOnEnd?.run() | ||||
|                 } | ||||
|             }).start() | ||||
|     } | ||||
| } | ||||
|  | ||||
| private fun View.animateSlideAndAlpha(enterOrExit: Boolean, duration: Long, delay: Long, execOnEnd: Runnable?) { | ||||
|     if (enterOrExit) { | ||||
|         translationY = -height.toFloat() | ||||
|         alpha = 0f | ||||
|         animate() | ||||
|             .setInterpolator(FastOutSlowInInterpolator()).alpha(1f).translationY(0f) | ||||
|             .setDuration(duration).setStartDelay(delay) | ||||
|             .setListener(object : AnimatorListenerAdapter() { | ||||
|                 override fun onAnimationEnd(animation: Animator) { | ||||
|                     execOnEnd?.run() | ||||
|                 } | ||||
|             }).start() | ||||
|     } else { | ||||
|         animate() | ||||
|             .setInterpolator(FastOutSlowInInterpolator()) | ||||
|             .alpha(0f).translationY(-height.toFloat()) | ||||
|             .setDuration(duration).setStartDelay(delay) | ||||
|             .setListener(object : AnimatorListenerAdapter() { | ||||
|                 override fun onAnimationEnd(animation: Animator) { | ||||
|                     isGone = true | ||||
|                     execOnEnd?.run() | ||||
|                 } | ||||
|             }).start() | ||||
|     } | ||||
| } | ||||
|  | ||||
| private fun View.animateLightSlideAndAlpha(enterOrExit: Boolean, duration: Long, delay: Long, execOnEnd: Runnable?) { | ||||
|     if (enterOrExit) { | ||||
|         translationY = -height / 2.0f | ||||
|         alpha = 0f | ||||
|         animate() | ||||
|             .setInterpolator(FastOutSlowInInterpolator()).alpha(1f).translationY(0f) | ||||
|             .setDuration(duration).setStartDelay(delay) | ||||
|             .setListener(object : AnimatorListenerAdapter() { | ||||
|                 override fun onAnimationEnd(animation: Animator) { | ||||
|                     execOnEnd?.run() | ||||
|                 } | ||||
|             }).start() | ||||
|     } else { | ||||
|         animate().setInterpolator(FastOutSlowInInterpolator()) | ||||
|             .alpha(0f).translationY(-height / 2.0f) | ||||
|             .setDuration(duration).setStartDelay(delay) | ||||
|             .setListener(object : AnimatorListenerAdapter() { | ||||
|                 override fun onAnimationEnd(animation: Animator) { | ||||
|                     isGone = true | ||||
|                     execOnEnd?.run() | ||||
|                 } | ||||
|             }).start() | ||||
|     } | ||||
| } | ||||
|  | ||||
| fun View.slideUp(duration: Long, delay: Long, @FloatRange(from = 0.0, to = 1.0) translationPercent: Float) { | ||||
|     val newTranslationY = (resources.displayMetrics.heightPixels * translationPercent).toInt() | ||||
|     animate().setListener(null).cancel() | ||||
|     alpha = 0f | ||||
|     translationY = newTranslationY.toFloat() | ||||
|     visibility = View.VISIBLE | ||||
|     animate() | ||||
|         .alpha(1f) | ||||
|         .translationY(0f) | ||||
|         .setStartDelay(delay) | ||||
|         .setDuration(duration) | ||||
|         .setInterpolator(FastOutSlowInInterpolator()) | ||||
|         .start() | ||||
| } | ||||
|  | ||||
| enum class AnimationType { | ||||
|     ALPHA, SCALE_AND_ALPHA, LIGHT_SCALE_AND_ALPHA, SLIDE_AND_ALPHA, LIGHT_SLIDE_AND_ALPHA | ||||
| } | ||||
| @@ -24,7 +24,7 @@ import org.schabi.newpipe.databinding.PignateFooterBinding; | ||||
| import org.schabi.newpipe.fragments.BaseStateFragment; | ||||
| import org.schabi.newpipe.fragments.list.ListViewContract; | ||||
|  | ||||
| import static org.schabi.newpipe.util.AnimationUtils.animateView; | ||||
| import static org.schabi.newpipe.ktx.ViewUtils.animate; | ||||
|  | ||||
| /** | ||||
|  * This fragment is design to be used with persistent data such as | ||||
| @@ -185,10 +185,10 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I> | ||||
|     public void showLoading() { | ||||
|         super.showLoading(); | ||||
|         if (itemsList != null) { | ||||
|             animateView(itemsList, false, 200); | ||||
|             animate(itemsList, false, 200); | ||||
|         } | ||||
|         if (headerRootBinding != null) { | ||||
|             animateView(headerRootBinding.getRoot(), false, 200); | ||||
|             animate(headerRootBinding.getRoot(), false, 200); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -196,10 +196,10 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I> | ||||
|     public void hideLoading() { | ||||
|         super.hideLoading(); | ||||
|         if (itemsList != null) { | ||||
|             animateView(itemsList, true, 200); | ||||
|             animate(itemsList, true, 200); | ||||
|         } | ||||
|         if (headerRootBinding != null) { | ||||
|             animateView(headerRootBinding.getRoot(), true, 200); | ||||
|             animate(headerRootBinding.getRoot(), true, 200); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -209,10 +209,10 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I> | ||||
|         showListFooter(false); | ||||
|  | ||||
|         if (itemsList != null) { | ||||
|             animateView(itemsList, false, 200); | ||||
|             animate(itemsList, false, 200); | ||||
|         } | ||||
|         if (headerRootBinding != null) { | ||||
|             animateView(headerRootBinding.getRoot(), false, 200); | ||||
|             animate(headerRootBinding.getRoot(), false, 200); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -42,9 +42,9 @@ import org.schabi.newpipe.database.feed.model.FeedGroupEntity | ||||
| import org.schabi.newpipe.databinding.ErrorRetryBinding | ||||
| import org.schabi.newpipe.databinding.FragmentFeedBinding | ||||
| import org.schabi.newpipe.fragments.list.BaseListFragment | ||||
| import org.schabi.newpipe.ktx.animate | ||||
| import org.schabi.newpipe.local.feed.service.FeedLoadService | ||||
| import org.schabi.newpipe.report.UserAction | ||||
| import org.schabi.newpipe.util.AnimationUtils.animateView | ||||
| import org.schabi.newpipe.util.Localization | ||||
| import java.util.Calendar | ||||
|  | ||||
| @@ -180,50 +180,50 @@ class FeedFragment : BaseListFragment<FeedState, Unit>() { | ||||
|     // ///////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
|     override fun showLoading() { | ||||
|         animateView(feedBinding.refreshRootView, false, 0) | ||||
|         animateView(feedBinding.itemsList, false, 0) | ||||
|         feedBinding.refreshRootView.animate(false, 0) | ||||
|         feedBinding.itemsList.animate(false, 0) | ||||
|  | ||||
|         animateView(feedBinding.loadingProgressBar, true, 200) | ||||
|         animateView(feedBinding.loadingProgressText, true, 200) | ||||
|         feedBinding.loadingProgressBar.animate(true, 200) | ||||
|         feedBinding.loadingProgressText.animate(true, 200) | ||||
|  | ||||
|         animateView(feedBinding.emptyStateView.root, false, 0) | ||||
|         animateView(errorBinding.root, false, 0) | ||||
|         feedBinding.emptyStateView.root.animate(false, 0) | ||||
|         errorBinding.root.animate(false, 0) | ||||
|     } | ||||
|  | ||||
|     override fun hideLoading() { | ||||
|         animateView(feedBinding.refreshRootView, true, 200) | ||||
|         animateView(feedBinding.itemsList, true, 300) | ||||
|         feedBinding.refreshRootView.animate(true, 200) | ||||
|         feedBinding.itemsList.animate(true, 300) | ||||
|  | ||||
|         animateView(feedBinding.loadingProgressBar, false, 0) | ||||
|         animateView(feedBinding.loadingProgressText, false, 0) | ||||
|         feedBinding.loadingProgressBar.animate(false, 0) | ||||
|         feedBinding.loadingProgressText.animate(false, 0) | ||||
|  | ||||
|         animateView(feedBinding.emptyStateView.root, false, 0) | ||||
|         animateView(errorBinding.root, false, 0) | ||||
|         feedBinding.emptyStateView.root.animate(false, 0) | ||||
|         errorBinding.root.animate(false, 0) | ||||
|         feedBinding.swiperefresh.isRefreshing = false | ||||
|     } | ||||
|  | ||||
|     override fun showEmptyState() { | ||||
|         animateView(feedBinding.refreshRootView, true, 200) | ||||
|         animateView(feedBinding.itemsList, false, 0) | ||||
|         feedBinding.refreshRootView.animate(true, 200) | ||||
|         feedBinding.itemsList.animate(false, 0) | ||||
|  | ||||
|         animateView(feedBinding.loadingProgressBar, false, 0) | ||||
|         animateView(feedBinding.loadingProgressText, false, 0) | ||||
|         feedBinding.loadingProgressBar.animate(false, 0) | ||||
|         feedBinding.loadingProgressText.animate(false, 0) | ||||
|  | ||||
|         animateView(feedBinding.emptyStateView.root, true, 800) | ||||
|         animateView(errorBinding.root, false, 0) | ||||
|         feedBinding.emptyStateView.root.animate(true, 800) | ||||
|         errorBinding.root.animate(false, 0) | ||||
|     } | ||||
|  | ||||
|     override fun showError(message: String, showRetryButton: Boolean) { | ||||
|         infoListAdapter.clearStreamItemList() | ||||
|         animateView(feedBinding.refreshRootView, false, 120) | ||||
|         animateView(feedBinding.itemsList, false, 120) | ||||
|         feedBinding.refreshRootView.animate(false, 120) | ||||
|         feedBinding.itemsList.animate(false, 120) | ||||
|  | ||||
|         animateView(feedBinding.loadingProgressBar, false, 120) | ||||
|         animateView(feedBinding.loadingProgressText, false, 120) | ||||
|         feedBinding.loadingProgressBar.animate(false, 120) | ||||
|         feedBinding.loadingProgressText.animate(false, 120) | ||||
|  | ||||
|         errorBinding.errorMessageView.text = message | ||||
|         animateView(errorBinding.errorButtonRetry, showRetryButton, if (showRetryButton) 600 else 0) | ||||
|         animateView(errorBinding.root, true, 300) | ||||
|         errorBinding.errorButtonRetry.animate(showRetryButton, if (showRetryButton) 600 else 0) | ||||
|         errorBinding.root.animate(true, 300) | ||||
|     } | ||||
|  | ||||
|     override fun handleResult(result: FeedState) { | ||||
|   | ||||
| @@ -12,9 +12,9 @@ import org.schabi.newpipe.R; | ||||
| import org.schabi.newpipe.database.LocalItem; | ||||
| import org.schabi.newpipe.database.playlist.PlaylistStreamEntry; | ||||
| import org.schabi.newpipe.extractor.NewPipe; | ||||
| import org.schabi.newpipe.ktx.ViewUtils; | ||||
| import org.schabi.newpipe.local.LocalItemBuilder; | ||||
| import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||
| import org.schabi.newpipe.util.AnimationUtils; | ||||
| import org.schabi.newpipe.util.ImageDisplayConstants; | ||||
| import org.schabi.newpipe.util.Localization; | ||||
| import org.schabi.newpipe.views.AnimatedProgressBar; | ||||
| @@ -117,10 +117,10 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder { | ||||
|             } else { | ||||
|                 itemProgressView.setProgress((int) TimeUnit.MILLISECONDS | ||||
|                         .toSeconds(item.getProgressTime())); | ||||
|                 AnimationUtils.animateView(itemProgressView, true, 500); | ||||
|                 ViewUtils.animate(itemProgressView, true, 500); | ||||
|             } | ||||
|         } else if (itemProgressView.getVisibility() == View.VISIBLE) { | ||||
|             AnimationUtils.animateView(itemProgressView, false, 500); | ||||
|             ViewUtils.animate(itemProgressView, false, 500); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -12,9 +12,9 @@ import org.schabi.newpipe.R; | ||||
| import org.schabi.newpipe.database.LocalItem; | ||||
| import org.schabi.newpipe.database.stream.StreamStatisticsEntry; | ||||
| import org.schabi.newpipe.extractor.NewPipe; | ||||
| import org.schabi.newpipe.ktx.ViewUtils; | ||||
| import org.schabi.newpipe.local.LocalItemBuilder; | ||||
| import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||
| import org.schabi.newpipe.util.AnimationUtils; | ||||
| import org.schabi.newpipe.util.ImageDisplayConstants; | ||||
| import org.schabi.newpipe.util.Localization; | ||||
| import org.schabi.newpipe.views.AnimatedProgressBar; | ||||
| @@ -148,10 +148,10 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder { | ||||
|             } else { | ||||
|                 itemProgressView.setProgress((int) TimeUnit.MILLISECONDS | ||||
|                         .toSeconds(item.getProgressTime())); | ||||
|                 AnimationUtils.animateView(itemProgressView, true, 500); | ||||
|                 ViewUtils.animate(itemProgressView, true, 500); | ||||
|             } | ||||
|         } else if (itemProgressView.getVisibility() == View.VISIBLE) { | ||||
|             AnimationUtils.animateView(itemProgressView, false, 500); | ||||
|             ViewUtils.animate(itemProgressView, false, 500); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -58,14 +58,14 @@ import java.util.concurrent.TimeUnit; | ||||
| import java.util.concurrent.atomic.AtomicBoolean; | ||||
|  | ||||
| import icepick.State; | ||||
| import io.reactivex.rxjava3.core.Flowable; | ||||
| import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; | ||||
| import io.reactivex.rxjava3.core.Flowable; | ||||
| import io.reactivex.rxjava3.disposables.CompositeDisposable; | ||||
| import io.reactivex.rxjava3.disposables.Disposable; | ||||
| import io.reactivex.rxjava3.schedulers.Schedulers; | ||||
| import io.reactivex.rxjava3.subjects.PublishSubject; | ||||
|  | ||||
| import static org.schabi.newpipe.util.AnimationUtils.animateView; | ||||
| import static org.schabi.newpipe.ktx.ViewUtils.animate; | ||||
|  | ||||
| public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistStreamEntry>, Void> { | ||||
|     // Save the list 10 seconds after the last change occurred | ||||
| @@ -201,8 +201,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt | ||||
|     public void showLoading() { | ||||
|         super.showLoading(); | ||||
|         if (headerBinding != null) { | ||||
|             animateView(headerBinding.getRoot(), false, 200); | ||||
|             animateView(playlistControlBinding.getRoot(), false, 200); | ||||
|             animate(headerBinding.getRoot(), false, 200); | ||||
|             animate(playlistControlBinding.getRoot(), false, 200); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -210,8 +210,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt | ||||
|     public void hideLoading() { | ||||
|         super.hideLoading(); | ||||
|         if (headerBinding != null) { | ||||
|             animateView(headerBinding.getRoot(), true, 200); | ||||
|             animateView(playlistControlBinding.getRoot(), true, 200); | ||||
|             animate(headerBinding.getRoot(), true, 200); | ||||
|             animate(playlistControlBinding.getRoot(), true, 200); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -36,6 +36,7 @@ import org.schabi.newpipe.databinding.DialogTitleBinding | ||||
| import org.schabi.newpipe.databinding.FragmentSubscriptionBinding | ||||
| import org.schabi.newpipe.extractor.channel.ChannelInfoItem | ||||
| import org.schabi.newpipe.fragments.BaseStateFragment | ||||
| import org.schabi.newpipe.ktx.animate | ||||
| import org.schabi.newpipe.local.subscription.SubscriptionViewModel.SubscriptionState | ||||
| import org.schabi.newpipe.local.subscription.dialog.FeedGroupDialog | ||||
| import org.schabi.newpipe.local.subscription.dialog.FeedGroupReorderDialog | ||||
| @@ -56,7 +57,6 @@ import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService | ||||
| import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_VALUE | ||||
| import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.PREVIOUS_EXPORT_MODE | ||||
| import org.schabi.newpipe.report.UserAction | ||||
| import org.schabi.newpipe.util.AnimationUtils.animateView | ||||
| import org.schabi.newpipe.util.FilePickerActivityHelper | ||||
| import org.schabi.newpipe.util.NavigationHelper | ||||
| import org.schabi.newpipe.util.OnClickGesture | ||||
| @@ -407,12 +407,12 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() { | ||||
|  | ||||
|     override fun showLoading() { | ||||
|         super.showLoading() | ||||
|         animateView(binding.itemsList, false, 100) | ||||
|         binding.itemsList.animate(false, 100) | ||||
|     } | ||||
|  | ||||
|     override fun hideLoading() { | ||||
|         super.hideLoading() | ||||
|         animateView(binding.itemsList, true, 200) | ||||
|         binding.itemsList.animate(true, 200) | ||||
|     } | ||||
|  | ||||
|     // ///////////////////////////////////////////////////////////////////////// | ||||
|   | ||||
| @@ -17,7 +17,7 @@ import kotlinx.android.synthetic.main.feed_import_export_group.import_from_optio | ||||
| import org.schabi.newpipe.R | ||||
| import org.schabi.newpipe.extractor.NewPipe | ||||
| import org.schabi.newpipe.extractor.exceptions.ExtractionException | ||||
| import org.schabi.newpipe.util.AnimationUtils | ||||
| import org.schabi.newpipe.ktx.animateRotation | ||||
| import org.schabi.newpipe.util.ServiceHelper | ||||
| import org.schabi.newpipe.util.ThemeHelper | ||||
| import org.schabi.newpipe.views.CollapsibleView | ||||
| @@ -49,8 +49,7 @@ class FeedImportExportItem( | ||||
|  | ||||
|         expandIconListener?.let { viewHolder.import_export_options.removeListener(it) } | ||||
|         expandIconListener = CollapsibleView.StateListener { newState -> | ||||
|             AnimationUtils.animateRotation( | ||||
|                 viewHolder.import_export_expand_icon, | ||||
|             viewHolder.import_export_expand_icon.animateRotation( | ||||
|                 250, if (newState == CollapsibleView.COLLAPSED) 0 else 180 | ||||
|             ) | ||||
|         } | ||||
|   | ||||
| @@ -9,8 +9,8 @@ import kotlinx.android.synthetic.main.picker_subscription_item.* | ||||
| import kotlinx.android.synthetic.main.picker_subscription_item.view.* | ||||
| import org.schabi.newpipe.R | ||||
| import org.schabi.newpipe.database.subscription.SubscriptionEntity | ||||
| import org.schabi.newpipe.util.AnimationUtils | ||||
| import org.schabi.newpipe.util.AnimationUtils.animateView | ||||
| import org.schabi.newpipe.ktx.AnimationType | ||||
| import org.schabi.newpipe.ktx.animate | ||||
| import org.schabi.newpipe.util.ImageDisplayConstants | ||||
|  | ||||
| data class PickerSubscriptionItem( | ||||
| @@ -41,9 +41,6 @@ data class PickerSubscriptionItem( | ||||
|  | ||||
|     fun updateSelected(containerView: View, isSelected: Boolean) { | ||||
|         this.isSelected = isSelected | ||||
|         animateView( | ||||
|             containerView.selected_highlight, | ||||
|             AnimationUtils.Type.LIGHT_SCALE_AND_ALPHA, isSelected, 150 | ||||
|         ) | ||||
|         containerView.selected_highlight.animate(isSelected, 150, AnimationType.LIGHT_SCALE_AND_ALPHA) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -92,6 +92,7 @@ import org.schabi.newpipe.extractor.stream.VideoStream; | ||||
| import org.schabi.newpipe.fragments.OnScrollBelowItemsListener; | ||||
| import org.schabi.newpipe.fragments.detail.VideoDetailFragment; | ||||
| import org.schabi.newpipe.info_list.StreamSegmentAdapter; | ||||
| import org.schabi.newpipe.ktx.AnimationType; | ||||
| import org.schabi.newpipe.local.history.HistoryRecordManager; | ||||
| import org.schabi.newpipe.player.MainPlayer.PlayerType; | ||||
| import org.schabi.newpipe.player.event.PlayerEventListener; | ||||
| @@ -116,7 +117,6 @@ import org.schabi.newpipe.player.playqueue.PlayQueueItemTouchCallback; | ||||
| import org.schabi.newpipe.player.resolver.AudioPlaybackResolver; | ||||
| import org.schabi.newpipe.player.resolver.MediaSourceTag; | ||||
| import org.schabi.newpipe.player.resolver.VideoPlaybackResolver; | ||||
| import org.schabi.newpipe.util.AnimationUtils; | ||||
| import org.schabi.newpipe.util.DeviceUtils; | ||||
| import org.schabi.newpipe.util.ImageDisplayConstants; | ||||
| import org.schabi.newpipe.util.KoreUtil; | ||||
| @@ -150,6 +150,8 @@ import static com.google.android.exoplayer2.Player.REPEAT_MODE_ONE; | ||||
| import static com.google.android.exoplayer2.Player.RepeatMode; | ||||
| import static java.util.concurrent.TimeUnit.MILLISECONDS; | ||||
| import static org.schabi.newpipe.extractor.ServiceList.YouTube; | ||||
| import static org.schabi.newpipe.ktx.ViewUtils.animate; | ||||
| import static org.schabi.newpipe.ktx.ViewUtils.animateRotation; | ||||
| import static org.schabi.newpipe.player.MainPlayer.ACTION_CLOSE; | ||||
| import static org.schabi.newpipe.player.MainPlayer.ACTION_FAST_FORWARD; | ||||
| import static org.schabi.newpipe.player.MainPlayer.ACTION_FAST_REWIND; | ||||
| @@ -176,9 +178,6 @@ import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePlayerTypeFr | ||||
| import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePopupLayoutParamsFromPrefs; | ||||
| import static org.schabi.newpipe.player.helper.PlayerHelper.retrieveSeekDurationFromPreferences; | ||||
| import static org.schabi.newpipe.player.helper.PlayerHelper.savePlaybackParametersToPrefs; | ||||
| import static org.schabi.newpipe.util.AnimationUtils.Type.SLIDE_AND_ALPHA; | ||||
| import static org.schabi.newpipe.util.AnimationUtils.animateRotation; | ||||
| import static org.schabi.newpipe.util.AnimationUtils.animateView; | ||||
| import static org.schabi.newpipe.util.ListHelper.getPopupResolutionIndex; | ||||
| import static org.schabi.newpipe.util.ListHelper.getResolutionIndex; | ||||
| import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; | ||||
| @@ -1560,8 +1559,8 @@ public final class Player implements | ||||
|         } | ||||
|  | ||||
|         showControls(0); | ||||
|         animateView(binding.currentDisplaySeek, AnimationUtils.Type.SCALE_AND_ALPHA, true, | ||||
|                 DEFAULT_CONTROLS_DURATION); | ||||
|         animate(binding.currentDisplaySeek, true, DEFAULT_CONTROLS_DURATION, | ||||
|                 AnimationType.SCALE_AND_ALPHA); | ||||
|     } | ||||
|  | ||||
|     @Override // seekbar listener | ||||
| @@ -1576,7 +1575,7 @@ public final class Player implements | ||||
|         } | ||||
|  | ||||
|         binding.playbackCurrentTime.setText(getTimeString(seekBar.getProgress())); | ||||
|         animateView(binding.currentDisplaySeek, AnimationUtils.Type.SCALE_AND_ALPHA, false, 200); | ||||
|         animate(binding.currentDisplaySeek, false, 200, AnimationType.SCALE_AND_ALPHA); | ||||
|  | ||||
|         if (currentState == STATE_PAUSED_SEEK) { | ||||
|             changeState(STATE_BUFFERING); | ||||
| @@ -1682,8 +1681,8 @@ public final class Player implements | ||||
|                 : DPAD_CONTROLS_HIDE_TIME; | ||||
|  | ||||
|         showHideShadow(true, DEFAULT_CONTROLS_DURATION); | ||||
|         animateView(binding.playbackControlRoot, true, DEFAULT_CONTROLS_DURATION, 0, | ||||
|                 () -> hideControls(DEFAULT_CONTROLS_DURATION, hideTime)); | ||||
|         animate(binding.playbackControlRoot, true, DEFAULT_CONTROLS_DURATION, | ||||
|                 AnimationType.ALPHA, 0, () -> hideControls(DEFAULT_CONTROLS_DURATION, hideTime)); | ||||
|     } | ||||
|  | ||||
|     public void showControls(final long duration) { | ||||
| @@ -1694,7 +1693,7 @@ public final class Player implements | ||||
|         showSystemUIPartially(); | ||||
|         controlsVisibilityHandler.removeCallbacksAndMessages(null); | ||||
|         showHideShadow(true, duration); | ||||
|         animateView(binding.playbackControlRoot, true, duration); | ||||
|         animate(binding.playbackControlRoot, true, duration); | ||||
|     } | ||||
|  | ||||
|     public void hideControls(final long duration, final long delay) { | ||||
| @@ -1708,14 +1707,14 @@ public final class Player implements | ||||
|         controlsVisibilityHandler.removeCallbacksAndMessages(null); | ||||
|         controlsVisibilityHandler.postDelayed(() -> { | ||||
|             showHideShadow(false, duration); | ||||
|             animateView(binding.playbackControlRoot, false, duration, 0, | ||||
|                     this::hideSystemUIIfNeeded); | ||||
|             animate(binding.playbackControlRoot, false, duration, AnimationType.ALPHA, | ||||
|                     0, this::hideSystemUIIfNeeded); | ||||
|         }, delay); | ||||
|     } | ||||
|  | ||||
|     private void showHideShadow(final boolean show, final long duration) { | ||||
|         animateView(binding.playerTopShadow, show, duration, 0, null); | ||||
|         animateView(binding.playerBottomShadow, show, duration, 0, null); | ||||
|         animate(binding.playerTopShadow, show, duration, AnimationType.ALPHA, 0, null); | ||||
|         animate(binding.playerBottomShadow, show, duration, AnimationType.ALPHA, 0, null); | ||||
|     } | ||||
|  | ||||
|     private void showOrHideButtons() { | ||||
| @@ -1913,15 +1912,15 @@ public final class Player implements | ||||
|         } | ||||
|  | ||||
|         controlsVisibilityHandler.removeCallbacksAndMessages(null); | ||||
|         animateView(binding.playbackControlRoot, false, DEFAULT_CONTROLS_DURATION); | ||||
|         animate(binding.playbackControlRoot, false, DEFAULT_CONTROLS_DURATION); | ||||
|  | ||||
|         binding.playbackSeekBar.setEnabled(false); | ||||
|         binding.playbackSeekBar.getThumb() | ||||
|                 .setColorFilter(new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_IN)); | ||||
|  | ||||
|         binding.loadingPanel.setBackgroundColor(Color.BLACK); | ||||
|         animateView(binding.loadingPanel, true, 0); | ||||
|         animateView(binding.surfaceForeground, true, 100); | ||||
|         animate(binding.loadingPanel, true, 0); | ||||
|         animate(binding.surfaceForeground, true, 100); | ||||
|  | ||||
|         binding.playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp); | ||||
|         animatePlayButtons(false, 100); | ||||
| @@ -1948,9 +1947,9 @@ public final class Player implements | ||||
|  | ||||
|         binding.loadingPanel.setVisibility(View.GONE); | ||||
|  | ||||
|         animateView(binding.currentDisplaySeek, AnimationUtils.Type.SCALE_AND_ALPHA, false, 200); | ||||
|         animate(binding.currentDisplaySeek, false, 200, AnimationType.SCALE_AND_ALPHA); | ||||
|  | ||||
|         animateView(binding.playPauseButton, AnimationUtils.Type.SCALE_AND_ALPHA, false, 80, 0, | ||||
|         animate(binding.playPauseButton, false, 80, AnimationType.SCALE_AND_ALPHA, 0, | ||||
|                 () -> { | ||||
|                     binding.playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp); | ||||
|                     animatePlayButtons(true, 200); | ||||
| @@ -1991,7 +1990,7 @@ public final class Player implements | ||||
|         showControls(400); | ||||
|         binding.loadingPanel.setVisibility(View.GONE); | ||||
|  | ||||
|         animateView(binding.playPauseButton, AnimationUtils.Type.SCALE_AND_ALPHA, false, 80, 0, | ||||
|         animate(binding.playPauseButton, false, 80, AnimationType.SCALE_AND_ALPHA, 0, | ||||
|                 () -> { | ||||
|                     binding.playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp); | ||||
|                     animatePlayButtons(true, 200); | ||||
| @@ -2029,7 +2028,7 @@ public final class Player implements | ||||
|             Log.d(TAG, "onCompleted() called"); | ||||
|         } | ||||
|  | ||||
|         animateView(binding.playPauseButton, AnimationUtils.Type.SCALE_AND_ALPHA, false, 0, 0, | ||||
|         animate(binding.playPauseButton, false, 0, AnimationType.SCALE_AND_ALPHA, 0, | ||||
|                 () -> { | ||||
|                     binding.playPauseButton.setImageResource(R.drawable.ic_replay_white_24dp); | ||||
|                     animatePlayButtons(true, DEFAULT_CONTROLS_DURATION); | ||||
| @@ -2051,13 +2050,13 @@ public final class Player implements | ||||
|         } | ||||
|  | ||||
|         showControls(500); | ||||
|         animateView(binding.currentDisplaySeek, AnimationUtils.Type.SCALE_AND_ALPHA, false, 200); | ||||
|         animate(binding.currentDisplaySeek, false, 200, AnimationType.SCALE_AND_ALPHA); | ||||
|         binding.loadingPanel.setVisibility(View.GONE); | ||||
|         animateView(binding.surfaceForeground, true, 100); | ||||
|         animate(binding.surfaceForeground, true, 100); | ||||
|     } | ||||
|  | ||||
|     private void animatePlayButtons(final boolean show, final int duration) { | ||||
|         animateView(binding.playPauseButton, AnimationUtils.Type.SCALE_AND_ALPHA, show, duration); | ||||
|         animate(binding.playPauseButton, show, duration, AnimationType.SCALE_AND_ALPHA); | ||||
|  | ||||
|         boolean showQueueButtons = show; | ||||
|         if (playQueue == null) { | ||||
| @@ -2065,18 +2064,18 @@ public final class Player implements | ||||
|         } | ||||
|  | ||||
|         if (!showQueueButtons || playQueue.getIndex() > 0) { | ||||
|             animateView( | ||||
|             animate( | ||||
|                     binding.playPreviousButton, | ||||
|                     AnimationUtils.Type.SCALE_AND_ALPHA, | ||||
|                     showQueueButtons, | ||||
|                     duration); | ||||
|                     duration, | ||||
|                     AnimationType.SCALE_AND_ALPHA); | ||||
|         } | ||||
|         if (!showQueueButtons || playQueue.getIndex() + 1 < playQueue.getStreams().size()) { | ||||
|             animateView( | ||||
|             animate( | ||||
|                     binding.playNextButton, | ||||
|                     AnimationUtils.Type.SCALE_AND_ALPHA, | ||||
|                     showQueueButtons, | ||||
|                     duration); | ||||
|                     duration, | ||||
|                     AnimationType.SCALE_AND_ALPHA); | ||||
|         } | ||||
|     } | ||||
|     //endregion | ||||
| @@ -2274,7 +2273,7 @@ public final class Player implements | ||||
|     @Override | ||||
|     public void onRenderedFirstFrame() { | ||||
|         //TODO check if this causes black screen when switching to fullscreen | ||||
|         animateView(binding.surfaceForeground, false, DEFAULT_CONTROLS_DURATION); | ||||
|         animate(binding.surfaceForeground, false, DEFAULT_CONTROLS_DURATION); | ||||
|     } | ||||
|     //endregion | ||||
|  | ||||
| @@ -2871,8 +2870,8 @@ public final class Player implements | ||||
|  | ||||
|         hideControls(0, 0); | ||||
|         binding.itemsListPanel.requestFocus(); | ||||
|         animateView(binding.itemsListPanel, SLIDE_AND_ALPHA, true, | ||||
|                 DEFAULT_CONTROLS_DURATION); | ||||
|         animate(binding.itemsListPanel, true, DEFAULT_CONTROLS_DURATION, | ||||
|                 AnimationType.SLIDE_AND_ALPHA); | ||||
|  | ||||
|         binding.itemsList.scrollToPosition(playQueue.getIndex()); | ||||
|     } | ||||
| @@ -2905,8 +2904,8 @@ public final class Player implements | ||||
|  | ||||
|         hideControls(0, 0); | ||||
|         binding.itemsListPanel.requestFocus(); | ||||
|         animateView(binding.itemsListPanel, SLIDE_AND_ALPHA, true, | ||||
|                 DEFAULT_CONTROLS_DURATION); | ||||
|         animate(binding.itemsListPanel, true, DEFAULT_CONTROLS_DURATION, | ||||
|                 AnimationType.SLIDE_AND_ALPHA); | ||||
|  | ||||
|         final int adapterPosition = getNearestStreamSegmentPosition(simpleExoPlayer | ||||
|                 .getCurrentPosition()); | ||||
| @@ -2942,8 +2941,8 @@ public final class Player implements | ||||
|                 itemTouchHelper.attachToRecyclerView(null); | ||||
|             } | ||||
|  | ||||
|             animateView(binding.itemsListPanel, SLIDE_AND_ALPHA, false, | ||||
|                     DEFAULT_CONTROLS_DURATION, 0, () -> { | ||||
|             animate(binding.itemsListPanel, false, DEFAULT_CONTROLS_DURATION, | ||||
|                     AnimationType.SLIDE_AND_ALPHA, 0, () -> { | ||||
|                         // Even when queueLayout is GONE it receives touch events | ||||
|                         // and ruins normal behavior of the app. This line fixes it | ||||
|                         binding.itemsListPanel.setTranslationY( | ||||
| @@ -3451,18 +3450,19 @@ public final class Player implements | ||||
|         if (currentState != STATE_COMPLETED) { | ||||
|             controlsVisibilityHandler.removeCallbacksAndMessages(null); | ||||
|             showHideShadow(true, DEFAULT_CONTROLS_DURATION); | ||||
|             animateView(binding.playbackControlRoot, true, DEFAULT_CONTROLS_DURATION, 0, () -> { | ||||
|                 if (currentState == STATE_PLAYING && !isSomePopupMenuVisible) { | ||||
|                     if (v.getId() == binding.playPauseButton.getId() | ||||
|                             // Hide controls in fullscreen immediately | ||||
|                             || (v.getId() == binding.screenRotationButton.getId() | ||||
|                             && isFullscreen)) { | ||||
|                         hideControls(0, 0); | ||||
|                     } else { | ||||
|                         hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME); | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|             animate(binding.playbackControlRoot, true, DEFAULT_CONTROLS_DURATION, | ||||
|                     AnimationType.ALPHA, 0, () -> { | ||||
|                         if (currentState == STATE_PLAYING && !isSomePopupMenuVisible) { | ||||
|                             if (v.getId() == binding.playPauseButton.getId() | ||||
|                                     // Hide controls in fullscreen immediately | ||||
|                                     || (v.getId() == binding.screenRotationButton.getId() | ||||
|                                     && isFullscreen)) { | ||||
|                                 hideControls(0, 0); | ||||
|                             } else { | ||||
|                                 hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME); | ||||
|                             } | ||||
|                         } | ||||
|                     }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -3531,9 +3531,8 @@ public final class Player implements | ||||
|  | ||||
|         animateRotation(binding.moreOptionsButton, DEFAULT_CONTROLS_DURATION, | ||||
|                 isMoreControlsVisible ? 0 : 180); | ||||
|         animateView(binding.secondaryControls, SLIDE_AND_ALPHA, !isMoreControlsVisible, | ||||
|                 DEFAULT_CONTROLS_DURATION, 0, | ||||
|                 () -> { | ||||
|         animate(binding.secondaryControls, !isMoreControlsVisible, DEFAULT_CONTROLS_DURATION, | ||||
|                 AnimationType.SLIDE_AND_ALPHA, 0, () -> { | ||||
|                     // Fix for a ripple effect on background drawable. | ||||
|                     // When view returns from GONE state it takes more milliseconds than returning | ||||
|                     // from INVISIBLE state. And the delay makes ripple background end to fast | ||||
|   | ||||
| @@ -7,11 +7,11 @@ import android.view.GestureDetector | ||||
| import android.view.MotionEvent | ||||
| import android.view.View | ||||
| import android.view.ViewConfiguration | ||||
| import org.schabi.newpipe.ktx.animate | ||||
| import org.schabi.newpipe.player.MainPlayer | ||||
| import org.schabi.newpipe.player.Player | ||||
| import org.schabi.newpipe.player.helper.PlayerHelper | ||||
| import org.schabi.newpipe.player.helper.PlayerHelper.savePopupPositionAndSizeToPrefs | ||||
| import org.schabi.newpipe.util.AnimationUtils | ||||
| import kotlin.math.abs | ||||
| import kotlin.math.hypot | ||||
| import kotlin.math.max | ||||
| @@ -364,7 +364,7 @@ abstract class BasePlayerGestureListener( | ||||
|         } | ||||
|  | ||||
|         if (!isMovingInPopup) { | ||||
|             AnimationUtils.animateView(player.closeOverlayButton, true, 200) | ||||
|             player.closeOverlayButton.animate(true, 200) | ||||
|         } | ||||
|  | ||||
|         isMovingInPopup = true | ||||
|   | ||||
| @@ -17,11 +17,12 @@ import org.schabi.newpipe.player.MainPlayer; | ||||
| import org.schabi.newpipe.player.Player; | ||||
| import org.schabi.newpipe.player.helper.PlayerHelper; | ||||
|  | ||||
| import static org.schabi.newpipe.player.Player.STATE_PLAYING; | ||||
| import static org.schabi.newpipe.ktx.AnimationType.ALPHA; | ||||
| import static org.schabi.newpipe.ktx.AnimationType.SCALE_AND_ALPHA; | ||||
| import static org.schabi.newpipe.ktx.ViewUtils.animate; | ||||
| import static org.schabi.newpipe.player.Player.DEFAULT_CONTROLS_DURATION; | ||||
| import static org.schabi.newpipe.player.Player.DEFAULT_CONTROLS_HIDE_TIME; | ||||
| import static org.schabi.newpipe.util.AnimationUtils.Type.SCALE_AND_ALPHA; | ||||
| import static org.schabi.newpipe.util.AnimationUtils.animateView; | ||||
| import static org.schabi.newpipe.player.Player.STATE_PLAYING; | ||||
|  | ||||
| /** | ||||
|  * GestureListener for the player | ||||
| @@ -123,11 +124,11 @@ public class PlayerGestureListener | ||||
|             final View closingOverlayView = player.getClosingOverlayView(); | ||||
|             if (player.isInsideClosingRadius(movingEvent)) { | ||||
|                 if (closingOverlayView.getVisibility() == View.GONE) { | ||||
|                     animateView(closingOverlayView, true, 250); | ||||
|                     animate(closingOverlayView, true, 250); | ||||
|                 } | ||||
|             } else { | ||||
|                 if (closingOverlayView.getVisibility() == View.VISIBLE) { | ||||
|                     animateView(closingOverlayView, false, 0); | ||||
|                     animate(closingOverlayView, false, 0); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -153,7 +154,7 @@ public class PlayerGestureListener | ||||
|         ); | ||||
|  | ||||
|         if (player.getVolumeRelativeLayout().getVisibility() != View.VISIBLE) { | ||||
|             animateView(player.getVolumeRelativeLayout(), SCALE_AND_ALPHA, true, 200); | ||||
|             animate(player.getVolumeRelativeLayout(), true, 200, SCALE_AND_ALPHA); | ||||
|         } | ||||
|         if (player.getBrightnessRelativeLayout().getVisibility() == View.VISIBLE) { | ||||
|             player.getBrightnessRelativeLayout().setVisibility(View.GONE); | ||||
| @@ -195,7 +196,7 @@ public class PlayerGestureListener | ||||
|         ); | ||||
|  | ||||
|         if (player.getBrightnessRelativeLayout().getVisibility() != View.VISIBLE) { | ||||
|             animateView(player.getBrightnessRelativeLayout(), SCALE_AND_ALPHA, true, 200); | ||||
|             animate(player.getBrightnessRelativeLayout(), true, 200, SCALE_AND_ALPHA); | ||||
|         } | ||||
|         if (player.getVolumeRelativeLayout().getVisibility() == View.VISIBLE) { | ||||
|             player.getVolumeRelativeLayout().setVisibility(View.GONE); | ||||
| @@ -215,21 +216,18 @@ public class PlayerGestureListener | ||||
|             } | ||||
|  | ||||
|             if (player.getVolumeRelativeLayout().getVisibility() == View.VISIBLE) { | ||||
|                 animateView(player.getVolumeRelativeLayout(), SCALE_AND_ALPHA, | ||||
|                         false, 200, 200); | ||||
|                 animate(player.getVolumeRelativeLayout(), false, 200, SCALE_AND_ALPHA, | ||||
|                         200); | ||||
|             } | ||||
|             if (player.getBrightnessRelativeLayout().getVisibility() == View.VISIBLE) { | ||||
|                 animateView(player.getBrightnessRelativeLayout(), SCALE_AND_ALPHA, | ||||
|                         false, 200, 200); | ||||
|                 animate(player.getBrightnessRelativeLayout(), false, 200, SCALE_AND_ALPHA, | ||||
|                         200); | ||||
|             } | ||||
|  | ||||
|             if (player.isControlsVisible() && player.getCurrentState() == STATE_PLAYING) { | ||||
|                 player.hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME); | ||||
|             } | ||||
|         } else { | ||||
|             if (player == null) { | ||||
|                 return; | ||||
|             } | ||||
|             if (player.isControlsVisible() && player.getCurrentState() == STATE_PLAYING) { | ||||
|                 player.hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME); | ||||
|             } | ||||
| @@ -237,10 +235,10 @@ public class PlayerGestureListener | ||||
|             if (player.isInsideClosingRadius(event)) { | ||||
|                 player.closePopup(); | ||||
|             } else { | ||||
|                 animateView(player.getClosingOverlayView(), false, 0); | ||||
|                 animate(player.getClosingOverlayView(), false, 0); | ||||
|  | ||||
|                 if (!player.isPopupClosing()) { | ||||
|                     animateView(player.getCloseOverlayButton(), false, 200); | ||||
|                     animate(player.getCloseOverlayButton(), false, 200); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -255,8 +253,8 @@ public class PlayerGestureListener | ||||
|         player.getLoadingPanel().setVisibility(View.GONE); | ||||
|  | ||||
|         player.hideControls(0, 0); | ||||
|         animateView(player.getCurrentDisplaySeek(), false, 0, 0); | ||||
|         animateView(player.getResizingIndicator(), true, 200, 0); | ||||
|         animate(player.getCurrentDisplaySeek(), false, 0, ALPHA, 0); | ||||
|         animate(player.getResizingIndicator(), true, 200, ALPHA, 0); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -264,7 +262,7 @@ public class PlayerGestureListener | ||||
|         if (DEBUG) { | ||||
|             Log.d(TAG, "onPopupResizingEnd called"); | ||||
|         } | ||||
|         animateView(player.getResizingIndicator(), false, 100, 0); | ||||
|         animate(player.getResizingIndicator(), false, 100, ALPHA, 0); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,478 +0,0 @@ | ||||
| /* | ||||
|  * Copyright 2018 Mauricio Colli <mauriciocolli@outlook.com> | ||||
|  * AnimationUtils.java is part of NewPipe | ||||
|  * | ||||
|  * License: GPL-3.0+ | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| package org.schabi.newpipe.util; | ||||
|  | ||||
| import android.animation.Animator; | ||||
| import android.animation.AnimatorListenerAdapter; | ||||
| import android.animation.ArgbEvaluator; | ||||
| import android.animation.ValueAnimator; | ||||
| import android.content.res.ColorStateList; | ||||
| import android.util.Log; | ||||
| import android.view.View; | ||||
| import android.widget.TextView; | ||||
|  | ||||
| import androidx.annotation.ColorInt; | ||||
| import androidx.annotation.FloatRange; | ||||
| import androidx.core.view.ViewCompat; | ||||
| import androidx.interpolator.view.animation.FastOutSlowInInterpolator; | ||||
|  | ||||
| import org.schabi.newpipe.MainActivity; | ||||
|  | ||||
| public final class AnimationUtils { | ||||
|     private static final String TAG = "AnimationUtils"; | ||||
|     private static final boolean DEBUG = MainActivity.DEBUG; | ||||
|  | ||||
|     private AnimationUtils() { } | ||||
|  | ||||
|     public static void animateView(final View view, final boolean enterOrExit, | ||||
|                                    final long duration) { | ||||
|         animateView(view, Type.ALPHA, enterOrExit, duration, 0, null); | ||||
|     } | ||||
|  | ||||
|     public static void animateView(final View view, final boolean enterOrExit, | ||||
|                                    final long duration, final long delay) { | ||||
|         animateView(view, Type.ALPHA, enterOrExit, duration, delay, null); | ||||
|     } | ||||
|  | ||||
|     public static void animateView(final View view, final boolean enterOrExit, final long duration, | ||||
|                                    final long delay, final Runnable execOnEnd) { | ||||
|         animateView(view, Type.ALPHA, enterOrExit, duration, delay, execOnEnd); | ||||
|     } | ||||
|  | ||||
|     public static void animateView(final View view, final Type animationType, | ||||
|                                    final boolean enterOrExit, final long duration) { | ||||
|         animateView(view, animationType, enterOrExit, duration, 0, null); | ||||
|     } | ||||
|  | ||||
|     public static void animateView(final View view, final Type animationType, | ||||
|                                    final boolean enterOrExit, final long duration, | ||||
|                                    final long delay) { | ||||
|         animateView(view, animationType, enterOrExit, duration, delay, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Animate the view. | ||||
|      * | ||||
|      * @param view          view that will be animated | ||||
|      * @param animationType {@link Type} of the animation | ||||
|      * @param enterOrExit   true to enter, false to exit | ||||
|      * @param duration      how long the animation will take, in milliseconds | ||||
|      * @param delay         how long the animation will wait to start, in milliseconds | ||||
|      * @param execOnEnd     runnable that will be executed when the animation ends | ||||
|      */ | ||||
|     public static void animateView(final View view, final Type animationType, | ||||
|                                    final boolean enterOrExit, final long duration, | ||||
|                                    final long delay, final Runnable execOnEnd) { | ||||
|         if (DEBUG) { | ||||
|             String id; | ||||
|             try { | ||||
|                 id = view.getResources().getResourceEntryName(view.getId()); | ||||
|             } catch (final Exception e) { | ||||
|                 id = view.getId() + ""; | ||||
|             } | ||||
|  | ||||
|             final String msg = String.format("%8s →  [%s:%s] [%s %s:%s] execOnEnd=%s", enterOrExit, | ||||
|                     view.getClass().getSimpleName(), id, animationType, duration, delay, execOnEnd); | ||||
|             Log.d(TAG, "animateView()" + msg); | ||||
|         } | ||||
|  | ||||
|         if (view.getVisibility() == View.VISIBLE && enterOrExit) { | ||||
|             if (DEBUG) { | ||||
|                 Log.d(TAG, "animateView() view was already visible > view = [" + view + "]"); | ||||
|             } | ||||
|             view.animate().setListener(null).cancel(); | ||||
|             view.setVisibility(View.VISIBLE); | ||||
|             view.setAlpha(1f); | ||||
|             if (execOnEnd != null) { | ||||
|                 execOnEnd.run(); | ||||
|             } | ||||
|             return; | ||||
|         } else if ((view.getVisibility() == View.GONE || view.getVisibility() == View.INVISIBLE) | ||||
|                 && !enterOrExit) { | ||||
|             if (DEBUG) { | ||||
|                 Log.d(TAG, "animateView() view was already gone > view = [" + view + "]"); | ||||
|             } | ||||
|             view.animate().setListener(null).cancel(); | ||||
|             view.setVisibility(View.GONE); | ||||
|             view.setAlpha(0f); | ||||
|             if (execOnEnd != null) { | ||||
|                 execOnEnd.run(); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         view.animate().setListener(null).cancel(); | ||||
|         view.setVisibility(View.VISIBLE); | ||||
|  | ||||
|         switch (animationType) { | ||||
|             case ALPHA: | ||||
|                 animateAlpha(view, enterOrExit, duration, delay, execOnEnd); | ||||
|                 break; | ||||
|             case SCALE_AND_ALPHA: | ||||
|                 animateScaleAndAlpha(view, enterOrExit, duration, delay, execOnEnd); | ||||
|                 break; | ||||
|             case LIGHT_SCALE_AND_ALPHA: | ||||
|                 animateLightScaleAndAlpha(view, enterOrExit, duration, delay, execOnEnd); | ||||
|                 break; | ||||
|             case SLIDE_AND_ALPHA: | ||||
|                 animateSlideAndAlpha(view, enterOrExit, duration, delay, execOnEnd); | ||||
|                 break; | ||||
|             case LIGHT_SLIDE_AND_ALPHA: | ||||
|                 animateLightSlideAndAlpha(view, enterOrExit, duration, delay, execOnEnd); | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Animate the background color of a view. | ||||
|      * | ||||
|      * @param view       the view to animate | ||||
|      * @param duration   the duration of the animation | ||||
|      * @param colorStart the background color to start with | ||||
|      * @param colorEnd   the background color to end with | ||||
|      */ | ||||
|     public static void animateBackgroundColor(final View view, final long duration, | ||||
|                                               @ColorInt final int colorStart, | ||||
|                                               @ColorInt final int colorEnd) { | ||||
|         if (DEBUG) { | ||||
|             Log.d(TAG, "animateBackgroundColor() called with: " | ||||
|                     + "view = [" + view + "], duration = [" + duration + "], " | ||||
|                     + "colorStart = [" + colorStart + "], colorEnd = [" + colorEnd + "]"); | ||||
|         } | ||||
|  | ||||
|         final int[][] empty = {new int[0]}; | ||||
|         final ValueAnimator viewPropertyAnimator = ValueAnimator | ||||
|                 .ofObject(new ArgbEvaluator(), colorStart, colorEnd); | ||||
|         viewPropertyAnimator.setInterpolator(new FastOutSlowInInterpolator()); | ||||
|         viewPropertyAnimator.setDuration(duration); | ||||
|         viewPropertyAnimator.addUpdateListener(animation -> | ||||
|                 ViewCompat.setBackgroundTintList(view, | ||||
|                         new ColorStateList(empty, new int[]{(int) animation.getAnimatedValue()}))); | ||||
|         viewPropertyAnimator.addListener(new AnimatorListenerAdapter() { | ||||
|             @Override | ||||
|             public void onAnimationEnd(final Animator animation) { | ||||
|                 ViewCompat.setBackgroundTintList(view, | ||||
|                         new ColorStateList(empty, new int[]{colorEnd})); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void onAnimationCancel(final Animator animation) { | ||||
|                 onAnimationEnd(animation); | ||||
|             } | ||||
|         }); | ||||
|         viewPropertyAnimator.start(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Animate the text color of any view that extends {@link TextView} (Buttons, EditText...). | ||||
|      * | ||||
|      * @param view       the text view to animate | ||||
|      * @param duration   the duration of the animation | ||||
|      * @param colorStart the text color to start with | ||||
|      * @param colorEnd   the text color to end with | ||||
|      */ | ||||
|     public static void animateTextColor(final TextView view, final long duration, | ||||
|                                         @ColorInt final int colorStart, | ||||
|                                         @ColorInt final int colorEnd) { | ||||
|         if (DEBUG) { | ||||
|             Log.d(TAG, "animateTextColor() called with: " | ||||
|                     + "view = [" + view + "], duration = [" + duration + "], " | ||||
|                     + "colorStart = [" + colorStart + "], colorEnd = [" + colorEnd + "]"); | ||||
|         } | ||||
|  | ||||
|         final ValueAnimator viewPropertyAnimator = ValueAnimator | ||||
|                 .ofObject(new ArgbEvaluator(), colorStart, colorEnd); | ||||
|         viewPropertyAnimator.setInterpolator(new FastOutSlowInInterpolator()); | ||||
|         viewPropertyAnimator.setDuration(duration); | ||||
|         viewPropertyAnimator.addUpdateListener(animation -> | ||||
|                 view.setTextColor((int) animation.getAnimatedValue())); | ||||
|         viewPropertyAnimator.addListener(new AnimatorListenerAdapter() { | ||||
|             @Override | ||||
|             public void onAnimationEnd(final Animator animation) { | ||||
|                 view.setTextColor(colorEnd); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void onAnimationCancel(final Animator animation) { | ||||
|                 view.setTextColor(colorEnd); | ||||
|             } | ||||
|         }); | ||||
|         viewPropertyAnimator.start(); | ||||
|     } | ||||
|  | ||||
|     public static ValueAnimator animateHeight(final View view, final long duration, | ||||
|                                               final int targetHeight) { | ||||
|         final int height = view.getHeight(); | ||||
|         if (DEBUG) { | ||||
|             Log.d(TAG, "animateHeight: duration = [" + duration + "], " | ||||
|                     + "from " + height + " to → " + targetHeight + " in: " + view); | ||||
|         } | ||||
|  | ||||
|         final ValueAnimator animator = ValueAnimator.ofFloat(height, targetHeight); | ||||
|         animator.setInterpolator(new FastOutSlowInInterpolator()); | ||||
|         animator.setDuration(duration); | ||||
|         animator.addUpdateListener(animation -> { | ||||
|             final float value = (float) animation.getAnimatedValue(); | ||||
|             view.getLayoutParams().height = (int) value; | ||||
|             view.requestLayout(); | ||||
|         }); | ||||
|         animator.addListener(new AnimatorListenerAdapter() { | ||||
|             @Override | ||||
|             public void onAnimationEnd(final Animator animation) { | ||||
|                 view.getLayoutParams().height = targetHeight; | ||||
|                 view.requestLayout(); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void onAnimationCancel(final Animator animation) { | ||||
|                 view.getLayoutParams().height = targetHeight; | ||||
|                 view.requestLayout(); | ||||
|             } | ||||
|         }); | ||||
|         animator.start(); | ||||
|  | ||||
|         return animator; | ||||
|     } | ||||
|  | ||||
|     public static void animateRotation(final View view, final long duration, | ||||
|                                        final int targetRotation) { | ||||
|         if (DEBUG) { | ||||
|             Log.d(TAG, "animateRotation: duration = [" + duration + "], " | ||||
|                     + "from " + view.getRotation() + " to → " + targetRotation + " in: " + view); | ||||
|         } | ||||
|         view.animate().setListener(null).cancel(); | ||||
|  | ||||
|         view.animate() | ||||
|                 .rotation(targetRotation).setDuration(duration) | ||||
|                 .setInterpolator(new FastOutSlowInInterpolator()) | ||||
|                 .setListener(new AnimatorListenerAdapter() { | ||||
|                     @Override | ||||
|                     public void onAnimationCancel(final Animator animation) { | ||||
|                         view.setRotation(targetRotation); | ||||
|                     } | ||||
|  | ||||
|                     @Override | ||||
|                     public void onAnimationEnd(final Animator animation) { | ||||
|                         view.setRotation(targetRotation); | ||||
|                     } | ||||
|                 }).start(); | ||||
|     } | ||||
|  | ||||
|     private static void animateAlpha(final View view, final boolean enterOrExit, | ||||
|                                      final long duration, final long delay, | ||||
|                                      final Runnable execOnEnd) { | ||||
|         if (enterOrExit) { | ||||
|             view.animate().setInterpolator(new FastOutSlowInInterpolator()).alpha(1f) | ||||
|                     .setDuration(duration).setStartDelay(delay) | ||||
|                     .setListener(new AnimatorListenerAdapter() { | ||||
|                 @Override | ||||
|                 public void onAnimationEnd(final Animator animation) { | ||||
|                     if (execOnEnd != null) { | ||||
|                         execOnEnd.run(); | ||||
|                     } | ||||
|                 } | ||||
|             }).start(); | ||||
|         } else { | ||||
|             view.animate().setInterpolator(new FastOutSlowInInterpolator()).alpha(0f) | ||||
|                     .setDuration(duration).setStartDelay(delay) | ||||
|                     .setListener(new AnimatorListenerAdapter() { | ||||
|                 @Override | ||||
|                 public void onAnimationEnd(final Animator animation) { | ||||
|                     view.setVisibility(View.GONE); | ||||
|                     if (execOnEnd != null) { | ||||
|                         execOnEnd.run(); | ||||
|                     } | ||||
|                 } | ||||
|             }).start(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /*////////////////////////////////////////////////////////////////////////// | ||||
|     // Internals | ||||
|     //////////////////////////////////////////////////////////////////////////*/ | ||||
|  | ||||
|     private static void animateScaleAndAlpha(final View view, final boolean enterOrExit, | ||||
|                                              final long duration, final long delay, | ||||
|                                              final Runnable execOnEnd) { | ||||
|         if (enterOrExit) { | ||||
|             view.setScaleX(.8f); | ||||
|             view.setScaleY(.8f); | ||||
|             view.animate() | ||||
|                     .setInterpolator(new FastOutSlowInInterpolator()) | ||||
|                     .alpha(1f).scaleX(1f).scaleY(1f) | ||||
|                     .setDuration(duration).setStartDelay(delay) | ||||
|                     .setListener(new AnimatorListenerAdapter() { | ||||
|                 @Override | ||||
|                 public void onAnimationEnd(final Animator animation) { | ||||
|                     if (execOnEnd != null) { | ||||
|                         execOnEnd.run(); | ||||
|                     } | ||||
|                 } | ||||
|             }).start(); | ||||
|         } else { | ||||
|             view.setScaleX(1f); | ||||
|             view.setScaleY(1f); | ||||
|             view.animate() | ||||
|                     .setInterpolator(new FastOutSlowInInterpolator()) | ||||
|                     .alpha(0f).scaleX(.8f).scaleY(.8f) | ||||
|                     .setDuration(duration).setStartDelay(delay) | ||||
|                     .setListener(new AnimatorListenerAdapter() { | ||||
|                 @Override | ||||
|                 public void onAnimationEnd(final Animator animation) { | ||||
|                     view.setVisibility(View.GONE); | ||||
|                     if (execOnEnd != null) { | ||||
|                         execOnEnd.run(); | ||||
|                     } | ||||
|                 } | ||||
|             }).start(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static void animateLightScaleAndAlpha(final View view, final boolean enterOrExit, | ||||
|                                                   final long duration, final long delay, | ||||
|                                                   final Runnable execOnEnd) { | ||||
|         if (enterOrExit) { | ||||
|             view.setAlpha(.5f); | ||||
|             view.setScaleX(.95f); | ||||
|             view.setScaleY(.95f); | ||||
|             view.animate() | ||||
|                     .setInterpolator(new FastOutSlowInInterpolator()) | ||||
|                     .alpha(1f).scaleX(1f).scaleY(1f) | ||||
|                     .setDuration(duration).setStartDelay(delay) | ||||
|                     .setListener(new AnimatorListenerAdapter() { | ||||
|                 @Override | ||||
|                 public void onAnimationEnd(final Animator animation) { | ||||
|                     if (execOnEnd != null) { | ||||
|                         execOnEnd.run(); | ||||
|                     } | ||||
|                 } | ||||
|             }).start(); | ||||
|         } else { | ||||
|             view.setAlpha(1f); | ||||
|             view.setScaleX(1f); | ||||
|             view.setScaleY(1f); | ||||
|             view.animate() | ||||
|                     .setInterpolator(new FastOutSlowInInterpolator()) | ||||
|                     .alpha(0f).scaleX(.95f).scaleY(.95f) | ||||
|                     .setDuration(duration).setStartDelay(delay) | ||||
|                     .setListener(new AnimatorListenerAdapter() { | ||||
|                 @Override | ||||
|                 public void onAnimationEnd(final Animator animation) { | ||||
|                     view.setVisibility(View.GONE); | ||||
|                     if (execOnEnd != null) { | ||||
|                         execOnEnd.run(); | ||||
|                     } | ||||
|                 } | ||||
|             }).start(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static void animateSlideAndAlpha(final View view, final boolean enterOrExit, | ||||
|                                              final long duration, final long delay, | ||||
|                                              final Runnable execOnEnd) { | ||||
|         if (enterOrExit) { | ||||
|             view.setTranslationY(-view.getHeight()); | ||||
|             view.setAlpha(0f); | ||||
|             view.animate() | ||||
|                     .setInterpolator(new FastOutSlowInInterpolator()).alpha(1f).translationY(0) | ||||
|                     .setDuration(duration).setStartDelay(delay) | ||||
|                     .setListener(new AnimatorListenerAdapter() { | ||||
|                 @Override | ||||
|                 public void onAnimationEnd(final Animator animation) { | ||||
|                     if (execOnEnd != null) { | ||||
|                         execOnEnd.run(); | ||||
|                     } | ||||
|                 } | ||||
|             }).start(); | ||||
|         } else { | ||||
|             view.animate() | ||||
|                     .setInterpolator(new FastOutSlowInInterpolator()) | ||||
|                     .alpha(0f).translationY(-view.getHeight()) | ||||
|                     .setDuration(duration).setStartDelay(delay) | ||||
|                     .setListener(new AnimatorListenerAdapter() { | ||||
|                 @Override | ||||
|                 public void onAnimationEnd(final Animator animation) { | ||||
|                     view.setVisibility(View.GONE); | ||||
|                     if (execOnEnd != null) { | ||||
|                         execOnEnd.run(); | ||||
|                     } | ||||
|                 } | ||||
|             }).start(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static void animateLightSlideAndAlpha(final View view, final boolean enterOrExit, | ||||
|                                                   final long duration, final long delay, | ||||
|                                                   final Runnable execOnEnd) { | ||||
|         if (enterOrExit) { | ||||
|             view.setTranslationY(-view.getHeight() / 2.0f); | ||||
|             view.setAlpha(0f); | ||||
|             view.animate() | ||||
|                     .setInterpolator(new FastOutSlowInInterpolator()).alpha(1f).translationY(0) | ||||
|                     .setDuration(duration).setStartDelay(delay) | ||||
|                     .setListener(new AnimatorListenerAdapter() { | ||||
|                 @Override | ||||
|                 public void onAnimationEnd(final Animator animation) { | ||||
|                     if (execOnEnd != null) { | ||||
|                         execOnEnd.run(); | ||||
|                     } | ||||
|                 } | ||||
|             }).start(); | ||||
|         } else { | ||||
|             view.animate().setInterpolator(new FastOutSlowInInterpolator()) | ||||
|                     .alpha(0f).translationY(-view.getHeight() / 2.0f) | ||||
|                     .setDuration(duration).setStartDelay(delay) | ||||
|                     .setListener(new AnimatorListenerAdapter() { | ||||
|                 @Override | ||||
|                 public void onAnimationEnd(final Animator animation) { | ||||
|                     view.setVisibility(View.GONE); | ||||
|                     if (execOnEnd != null) { | ||||
|                         execOnEnd.run(); | ||||
|                     } | ||||
|                 } | ||||
|             }).start(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static void slideUp(final View view, final long duration, final long delay, | ||||
|                                @FloatRange(from = 0.0f, to = 1.0f) | ||||
|                                final float translationPercent) { | ||||
|         final int translationY = (int) (view.getResources().getDisplayMetrics().heightPixels | ||||
|                 * (translationPercent)); | ||||
|  | ||||
|         view.animate().setListener(null).cancel(); | ||||
|         view.setAlpha(0f); | ||||
|         view.setTranslationY(translationY); | ||||
|         view.setVisibility(View.VISIBLE); | ||||
|         view.animate() | ||||
|                 .alpha(1f) | ||||
|                 .translationY(0) | ||||
|                 .setStartDelay(delay) | ||||
|                 .setDuration(duration) | ||||
|                 .setInterpolator(new FastOutSlowInInterpolator()) | ||||
|                 .start(); | ||||
|     } | ||||
|  | ||||
|     public enum Type { | ||||
|         ALPHA, | ||||
|         SCALE_AND_ALPHA, LIGHT_SCALE_AND_ALPHA, | ||||
|         SLIDE_AND_ALPHA, LIGHT_SLIDE_AND_ALPHA | ||||
|     } | ||||
| } | ||||
| @@ -31,7 +31,7 @@ import androidx.annotation.IntDef; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.annotation.RequiresApi; | ||||
|  | ||||
| import org.schabi.newpipe.util.AnimationUtils; | ||||
| import org.schabi.newpipe.ktx.ViewUtils; | ||||
|  | ||||
| import java.lang.annotation.Retention; | ||||
| import java.util.ArrayList; | ||||
| @@ -128,7 +128,7 @@ public class CollapsibleView extends LinearLayout { | ||||
|         if (currentAnimator != null && currentAnimator.isRunning()) { | ||||
|             currentAnimator.cancel(); | ||||
|         } | ||||
|         currentAnimator = AnimationUtils.animateHeight(this, ANIMATION_DURATION, 0); | ||||
|         currentAnimator = ViewUtils.animateHeight(this, ANIMATION_DURATION, 0); | ||||
|  | ||||
|         setCurrentState(COLLAPSED); | ||||
|     } | ||||
| @@ -151,7 +151,7 @@ public class CollapsibleView extends LinearLayout { | ||||
|         if (currentAnimator != null && currentAnimator.isRunning()) { | ||||
|             currentAnimator.cancel(); | ||||
|         } | ||||
|         currentAnimator = AnimationUtils.animateHeight(this, ANIMATION_DURATION, this.targetHeight); | ||||
|         currentAnimator = ViewUtils.animateHeight(this, ANIMATION_DURATION, this.targetHeight); | ||||
|         setCurrentState(EXPANDED); | ||||
|     } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Stypox
					Stypox