mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2024-12-23 16:40:32 +00:00
Merge pull request #5333 from Isira-Seneviratne/Convert_AnimationUtils_to_extensions
Convert AnimationUtils functions to extension functions.
This commit is contained in:
commit
b73eb9438d
@ -37,7 +37,7 @@ import icepick.State;
|
|||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.rxjava3.disposables.Disposable;
|
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> {
|
public abstract class BaseStateFragment<I> extends BaseFragment implements ViewContract<I> {
|
||||||
@State
|
@State
|
||||||
@ -131,35 +131,35 @@ public abstract class BaseStateFragment<I> extends BaseFragment implements ViewC
|
|||||||
@Override
|
@Override
|
||||||
public void showLoading() {
|
public void showLoading() {
|
||||||
if (emptyStateView != null) {
|
if (emptyStateView != null) {
|
||||||
animateView(emptyStateView, false, 150);
|
animate(emptyStateView, false, 150);
|
||||||
}
|
}
|
||||||
if (loadingProgressBar != null) {
|
if (loadingProgressBar != null) {
|
||||||
animateView(loadingProgressBar, true, 400);
|
animate(loadingProgressBar, true, 400);
|
||||||
}
|
}
|
||||||
animateView(errorPanelRoot, false, 150);
|
animate(errorPanelRoot, false, 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hideLoading() {
|
public void hideLoading() {
|
||||||
if (emptyStateView != null) {
|
if (emptyStateView != null) {
|
||||||
animateView(emptyStateView, false, 150);
|
animate(emptyStateView, false, 150);
|
||||||
}
|
}
|
||||||
if (loadingProgressBar != null) {
|
if (loadingProgressBar != null) {
|
||||||
animateView(loadingProgressBar, false, 0);
|
animate(loadingProgressBar, false, 0);
|
||||||
}
|
}
|
||||||
animateView(errorPanelRoot, false, 150);
|
animate(errorPanelRoot, false, 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showEmptyState() {
|
public void showEmptyState() {
|
||||||
isLoading.set(false);
|
isLoading.set(false);
|
||||||
if (emptyStateView != null) {
|
if (emptyStateView != null) {
|
||||||
animateView(emptyStateView, true, 200);
|
animate(emptyStateView, true, 200);
|
||||||
}
|
}
|
||||||
if (loadingProgressBar != null) {
|
if (loadingProgressBar != null) {
|
||||||
animateView(loadingProgressBar, false, 0);
|
animate(loadingProgressBar, false, 0);
|
||||||
}
|
}
|
||||||
animateView(errorPanelRoot, false, 150);
|
animate(errorPanelRoot, false, 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -174,11 +174,11 @@ public abstract class BaseStateFragment<I> extends BaseFragment implements ViewC
|
|||||||
|
|
||||||
errorTextView.setText(message);
|
errorTextView.setText(message);
|
||||||
if (showRetryButton) {
|
if (showRetryButton) {
|
||||||
animateView(errorButtonRetry, true, 600);
|
animate(errorButtonRetry, true, 600);
|
||||||
} else {
|
} else {
|
||||||
animateView(errorButtonRetry, false, 0);
|
animate(errorButtonRetry, false, 0);
|
||||||
}
|
}
|
||||||
animateView(errorPanelRoot, true, 300);
|
animate(errorPanelRoot, true, 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -76,11 +76,12 @@ import org.schabi.newpipe.fragments.BaseStateFragment;
|
|||||||
import org.schabi.newpipe.fragments.EmptyFragment;
|
import org.schabi.newpipe.fragments.EmptyFragment;
|
||||||
import org.schabi.newpipe.fragments.list.comments.CommentsFragment;
|
import org.schabi.newpipe.fragments.list.comments.CommentsFragment;
|
||||||
import org.schabi.newpipe.fragments.list.videos.RelatedVideosFragment;
|
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.PlaylistAppendDialog;
|
||||||
import org.schabi.newpipe.local.dialog.PlaylistCreationDialog;
|
import org.schabi.newpipe.local.dialog.PlaylistCreationDialog;
|
||||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||||
import org.schabi.newpipe.player.Player;
|
|
||||||
import org.schabi.newpipe.player.MainPlayer;
|
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.OnKeyDownListener;
|
||||||
import org.schabi.newpipe.player.event.PlayerServiceExtendedEventListener;
|
import org.schabi.newpipe.player.event.PlayerServiceExtendedEventListener;
|
||||||
import org.schabi.newpipe.player.helper.PlayerHelper;
|
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.globalScreenOrientationLocked;
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.isClearingQueueConfirmationRequired;
|
import static org.schabi.newpipe.player.helper.PlayerHelper.isClearingQueueConfirmationRequired;
|
||||||
import static org.schabi.newpipe.player.playqueue.PlayQueueItem.RECOVERY_UNSET;
|
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;
|
import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView;
|
||||||
|
|
||||||
public final class VideoDetailFragment
|
public final class VideoDetailFragment
|
||||||
@ -745,8 +746,10 @@ public final class VideoDetailFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
|
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
|
||||||
animateView(appendControlsDetail, true, 250, 0, () ->
|
animate(appendControlsDetail, true, 250, AnimationType.ALPHA,
|
||||||
animateView(appendControlsDetail, false, 1500, 1000));
|
0, () ->
|
||||||
|
animate(appendControlsDetail, false, 1500,
|
||||||
|
AnimationType.ALPHA, 1000));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
@ -1334,8 +1337,8 @@ public final class VideoDetailFragment
|
|||||||
|
|
||||||
thumbnailImageView.setImageDrawable(
|
thumbnailImageView.setImageDrawable(
|
||||||
AppCompatResources.getDrawable(requireContext(), imageResource));
|
AppCompatResources.getDrawable(requireContext(), imageResource));
|
||||||
animateView(thumbnailImageView, false, 0, 0,
|
animate(thumbnailImageView, false, 0, AnimationType.ALPHA, 0,
|
||||||
() -> animateView(thumbnailImageView, true, 500));
|
() -> animate(thumbnailImageView, true, 500));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1417,14 +1420,14 @@ public final class VideoDetailFragment
|
|||||||
contentRootLayoutHiding.setVisibility(View.INVISIBLE);
|
contentRootLayoutHiding.setVisibility(View.INVISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
animateView(thumbnailPlayButton, false, 50);
|
animate(thumbnailPlayButton, false, 50);
|
||||||
animateView(detailDurationView, false, 100);
|
animate(detailDurationView, false, 100);
|
||||||
animateView(detailPositionView, false, 100);
|
animate(detailPositionView, false, 100);
|
||||||
animateView(positionView, false, 50);
|
animate(positionView, false, 50);
|
||||||
|
|
||||||
videoTitleTextView.setText(title);
|
videoTitleTextView.setText(title);
|
||||||
videoTitleTextView.setMaxLines(1);
|
videoTitleTextView.setMaxLines(1);
|
||||||
animateView(videoTitleTextView, true, 0);
|
animate(videoTitleTextView, true, 0);
|
||||||
|
|
||||||
videoDescriptionRootLayout.setVisibility(View.GONE);
|
videoDescriptionRootLayout.setVisibility(View.GONE);
|
||||||
videoTitleToggleArrow.setVisibility(View.GONE);
|
videoTitleToggleArrow.setVisibility(View.GONE);
|
||||||
@ -1466,7 +1469,7 @@ public final class VideoDetailFragment
|
|||||||
player != null && player.isFullscreen() ? View.GONE : View.VISIBLE);
|
player != null && player.isFullscreen() ? View.GONE : View.VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
animateView(thumbnailPlayButton, true, 200);
|
animate(thumbnailPlayButton, true, 200);
|
||||||
videoTitleTextView.setText(title);
|
videoTitleTextView.setText(title);
|
||||||
|
|
||||||
if (!isEmpty(info.getSubChannelName())) {
|
if (!isEmpty(info.getSubChannelName())) {
|
||||||
@ -1530,12 +1533,12 @@ public final class VideoDetailFragment
|
|||||||
detailDurationView.setText(Localization.getDurationString(info.getDuration()));
|
detailDurationView.setText(Localization.getDurationString(info.getDuration()));
|
||||||
detailDurationView.setBackgroundColor(
|
detailDurationView.setBackgroundColor(
|
||||||
ContextCompat.getColor(activity, R.color.duration_background_color));
|
ContextCompat.getColor(activity, R.color.duration_background_color));
|
||||||
animateView(detailDurationView, true, 100);
|
animate(detailDurationView, true, 100);
|
||||||
} else if (info.getStreamType() == StreamType.LIVE_STREAM) {
|
} else if (info.getStreamType() == StreamType.LIVE_STREAM) {
|
||||||
detailDurationView.setText(R.string.duration_live);
|
detailDurationView.setText(R.string.duration_live);
|
||||||
detailDurationView.setBackgroundColor(
|
detailDurationView.setBackgroundColor(
|
||||||
ContextCompat.getColor(activity, R.color.live_duration_background_color));
|
ContextCompat.getColor(activity, R.color.live_duration_background_color));
|
||||||
animateView(detailDurationView, true, 100);
|
animate(detailDurationView, true, 100);
|
||||||
} else {
|
} else {
|
||||||
detailDurationView.setVisibility(View.GONE);
|
detailDurationView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
@ -1703,8 +1706,8 @@ public final class VideoDetailFragment
|
|||||||
// Show saved position from backStack if user allows it
|
// Show saved position from backStack if user allows it
|
||||||
showPlaybackProgress(playQueue.getItem().getRecoveryPosition(),
|
showPlaybackProgress(playQueue.getItem().getRecoveryPosition(),
|
||||||
playQueue.getItem().getDuration() * 1000);
|
playQueue.getItem().getDuration() * 1000);
|
||||||
animateView(positionView, true, 500);
|
animate(positionView, true, 500);
|
||||||
animateView(detailPositionView, true, 500);
|
animate(detailPositionView, true, 500);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1718,8 +1721,8 @@ public final class VideoDetailFragment
|
|||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(state -> {
|
.subscribe(state -> {
|
||||||
showPlaybackProgress(state.getProgressTime(), info.getDuration() * 1000);
|
showPlaybackProgress(state.getProgressTime(), info.getDuration() * 1000);
|
||||||
animateView(positionView, true, 500);
|
animate(positionView, true, 500);
|
||||||
animateView(detailPositionView, true, 500);
|
animate(detailPositionView, true, 500);
|
||||||
}, e -> {
|
}, e -> {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -1747,8 +1750,8 @@ public final class VideoDetailFragment
|
|||||||
detailPositionView.setText(position);
|
detailPositionView.setText(position);
|
||||||
}
|
}
|
||||||
if (positionView.getVisibility() != View.VISIBLE) {
|
if (positionView.getVisibility() != View.VISIBLE) {
|
||||||
animateView(positionView, true, 100);
|
animate(positionView, true, 100);
|
||||||
animateView(detailPositionView, true, 100);
|
animate(detailPositionView, true, 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1802,8 +1805,8 @@ public final class VideoDetailFragment
|
|||||||
&& player.getPlayQueue() != null
|
&& player.getPlayQueue() != null
|
||||||
&& player.getPlayQueue().getItem() != null
|
&& player.getPlayQueue().getItem() != null
|
||||||
&& player.getPlayQueue().getItem().getUrl().equals(url)) {
|
&& player.getPlayQueue().getItem().getUrl().equals(url)) {
|
||||||
animateView(positionView, true, 100);
|
animate(positionView, true, 100);
|
||||||
animateView(detailPositionView, true, 100);
|
animate(detailPositionView, true, 100);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Queue;
|
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>
|
public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
||||||
implements ListViewContract<I, N>, StateSaver.WriteRead,
|
implements ListViewContract<I, N>, StateSaver.WriteRead,
|
||||||
@ -406,23 +406,17 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
|||||||
// Contract
|
// Contract
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showLoading() {
|
|
||||||
super.showLoading();
|
|
||||||
// animateView(itemsList, false, 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hideLoading() {
|
public void hideLoading() {
|
||||||
super.hideLoading();
|
super.hideLoading();
|
||||||
animateView(itemsList, true, 300);
|
animate(itemsList, true, 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showError(final String message, final boolean showRetryButton) {
|
public void showError(final String message, final boolean showRetryButton) {
|
||||||
super.showError(message, showRetryButton);
|
super.showError(message, showRetryButton);
|
||||||
showListFooter(false);
|
showListFooter(false);
|
||||||
animateView(itemsList, false, 200);
|
animate(itemsList, false, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -37,12 +37,12 @@ import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException;
|
|||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||||
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
||||||
|
import org.schabi.newpipe.ktx.AnimationType;
|
||||||
import org.schabi.newpipe.local.subscription.SubscriptionManager;
|
import org.schabi.newpipe.local.subscription.SubscriptionManager;
|
||||||
import org.schabi.newpipe.player.playqueue.ChannelPlayQueue;
|
import org.schabi.newpipe.player.playqueue.ChannelPlayQueue;
|
||||||
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
||||||
import org.schabi.newpipe.report.ErrorActivity;
|
import org.schabi.newpipe.report.ErrorActivity;
|
||||||
import org.schabi.newpipe.report.UserAction;
|
import org.schabi.newpipe.report.UserAction;
|
||||||
import org.schabi.newpipe.util.AnimationUtils;
|
|
||||||
import org.schabi.newpipe.util.ExtractorHelper;
|
import org.schabi.newpipe.util.ExtractorHelper;
|
||||||
import org.schabi.newpipe.util.ImageDisplayConstants;
|
import org.schabi.newpipe.util.ImageDisplayConstants;
|
||||||
import org.schabi.newpipe.util.Localization;
|
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.functions.Function;
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||||
|
|
||||||
import static org.schabi.newpipe.util.AnimationUtils.animateBackgroundColor;
|
import static org.schabi.newpipe.ktx.TextViewUtils.animateTextColor;
|
||||||
import static org.schabi.newpipe.util.AnimationUtils.animateTextColor;
|
import static org.schabi.newpipe.ktx.ViewUtils.animate;
|
||||||
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
import static org.schabi.newpipe.ktx.ViewUtils.animateBackgroundColor;
|
||||||
|
|
||||||
public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
||||||
implements View.OnClickListener {
|
implements View.OnClickListener {
|
||||||
@ -224,7 +224,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
|||||||
|
|
||||||
private void monitorSubscription(final ChannelInfo info) {
|
private void monitorSubscription(final ChannelInfo info) {
|
||||||
final Consumer<Throwable> onError = (Throwable throwable) -> {
|
final Consumer<Throwable> onError = (Throwable throwable) -> {
|
||||||
animateView(headerBinding.channelSubscribeButton, false, 100);
|
animate(headerBinding.channelSubscribeButton, false, 100);
|
||||||
showSnackBarError(throwable, UserAction.SUBSCRIPTION,
|
showSnackBarError(throwable, UserAction.SUBSCRIPTION,
|
||||||
NewPipe.getNameOfService(currentInfo.getServiceId()),
|
NewPipe.getNameOfService(currentInfo.getServiceId()),
|
||||||
"Get subscription status", 0);
|
"Get subscription status", 0);
|
||||||
@ -379,8 +379,8 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
|||||||
subscribedText);
|
subscribedText);
|
||||||
}
|
}
|
||||||
|
|
||||||
animateView(headerBinding.channelSubscribeButton, AnimationUtils.Type.LIGHT_SCALE_AND_ALPHA,
|
animate(headerBinding.channelSubscribeButton, true, 100,
|
||||||
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.channelBannerImage);
|
||||||
IMAGE_LOADER.cancelDisplayTask(headerBinding.channelAvatarView);
|
IMAGE_LOADER.cancelDisplayTask(headerBinding.channelAvatarView);
|
||||||
IMAGE_LOADER.cancelDisplayTask(headerBinding.subChannelAvatarView);
|
IMAGE_LOADER.cancelDisplayTask(headerBinding.subChannelAvatarView);
|
||||||
animateView(headerBinding.channelSubscribeButton, false, 100);
|
animate(headerBinding.channelSubscribeButton, false, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -16,8 +16,8 @@ import org.schabi.newpipe.extractor.ListExtractor;
|
|||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
import org.schabi.newpipe.extractor.comments.CommentsInfo;
|
import org.schabi.newpipe.extractor.comments.CommentsInfo;
|
||||||
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
||||||
|
import org.schabi.newpipe.ktx.ViewUtils;
|
||||||
import org.schabi.newpipe.report.UserAction;
|
import org.schabi.newpipe.report.UserAction;
|
||||||
import org.schabi.newpipe.util.AnimationUtils;
|
|
||||||
import org.schabi.newpipe.util.ExtractorHelper;
|
import org.schabi.newpipe.util.ExtractorHelper;
|
||||||
|
|
||||||
import io.reactivex.rxjava3.core.Single;
|
import io.reactivex.rxjava3.core.Single;
|
||||||
@ -84,16 +84,14 @@ public class CommentsFragment extends BaseListInfoFragment<CommentsInfo> {
|
|||||||
public void handleResult(@NonNull final CommentsInfo result) {
|
public void handleResult(@NonNull final CommentsInfo result) {
|
||||||
super.handleResult(result);
|
super.handleResult(result);
|
||||||
|
|
||||||
AnimationUtils.slideUp(requireView(), 120, 150, 0.06f);
|
ViewUtils.slideUp(requireView(), 120, 150, 0.06f);
|
||||||
|
|
||||||
if (!result.getErrors().isEmpty()) {
|
if (!result.getErrors().isEmpty()) {
|
||||||
showSnackBarError(result.getErrors(), UserAction.REQUESTED_COMMENTS,
|
showSnackBarError(result.getErrors(), UserAction.REQUESTED_COMMENTS,
|
||||||
NewPipe.getNameOfService(result.getServiceId()), result.getUrl(), 0);
|
NewPipe.getNameOfService(result.getServiceId()), result.getUrl(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disposables != null) {
|
disposables.clear();
|
||||||
disposables.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -28,7 +28,7 @@ import org.schabi.newpipe.util.Localization;
|
|||||||
import icepick.State;
|
import icepick.State;
|
||||||
import io.reactivex.rxjava3.core.Single;
|
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.
|
* Created by Christian Schabesberger on 23.09.17.
|
||||||
@ -160,7 +160,7 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
|
|||||||
@Override
|
@Override
|
||||||
public void showLoading() {
|
public void showLoading() {
|
||||||
super.showLoading();
|
super.showLoading();
|
||||||
animateView(itemsList, false, 100);
|
animate(itemsList, false, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -61,7 +61,7 @@ import io.reactivex.rxjava3.core.Single;
|
|||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||||
import io.reactivex.rxjava3.disposables.Disposable;
|
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;
|
import static org.schabi.newpipe.util.ThemeHelper.resolveResourceIdFromAttr;
|
||||||
|
|
||||||
public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
||||||
@ -261,19 +261,19 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
|||||||
@Override
|
@Override
|
||||||
public void showLoading() {
|
public void showLoading() {
|
||||||
super.showLoading();
|
super.showLoading();
|
||||||
animateView(headerBinding.getRoot(), false, 200);
|
animate(headerBinding.getRoot(), false, 200);
|
||||||
animateView(itemsList, false, 100);
|
animate(itemsList, false, 100);
|
||||||
|
|
||||||
IMAGE_LOADER.cancelDisplayTask(headerBinding.uploaderAvatarView);
|
IMAGE_LOADER.cancelDisplayTask(headerBinding.uploaderAvatarView);
|
||||||
animateView(headerBinding.uploaderLayout, false, 200);
|
animate(headerBinding.uploaderLayout, false, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleResult(@NonNull final PlaylistInfo result) {
|
public void handleResult(@NonNull final PlaylistInfo result) {
|
||||||
super.handleResult(result);
|
super.handleResult(result);
|
||||||
|
|
||||||
animateView(headerBinding.getRoot(), true, 100);
|
animate(headerBinding.getRoot(), true, 100);
|
||||||
animateView(headerBinding.uploaderLayout, true, 300);
|
animate(headerBinding.uploaderLayout, true, 300);
|
||||||
headerBinding.uploaderLayout.setOnClickListener(null);
|
headerBinding.uploaderLayout.setOnClickListener(null);
|
||||||
// If we have an uploader put them into the UI
|
// If we have an uploader put them into the UI
|
||||||
if (!TextUtils.isEmpty(result.getUploaderName())) {
|
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.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory;
|
||||||
import org.schabi.newpipe.fragments.BackPressable;
|
import org.schabi.newpipe.fragments.BackPressable;
|
||||||
import org.schabi.newpipe.fragments.list.BaseListFragment;
|
import org.schabi.newpipe.fragments.list.BaseListFragment;
|
||||||
|
import org.schabi.newpipe.ktx.AnimationType;
|
||||||
import org.schabi.newpipe.ktx.ExceptionUtils;
|
import org.schabi.newpipe.ktx.ExceptionUtils;
|
||||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||||
import org.schabi.newpipe.report.ErrorActivity;
|
import org.schabi.newpipe.report.ErrorActivity;
|
||||||
import org.schabi.newpipe.report.ErrorInfo;
|
import org.schabi.newpipe.report.ErrorInfo;
|
||||||
import org.schabi.newpipe.report.UserAction;
|
import org.schabi.newpipe.report.UserAction;
|
||||||
import org.schabi.newpipe.util.AnimationUtils;
|
|
||||||
import org.schabi.newpipe.util.Constants;
|
import org.schabi.newpipe.util.Constants;
|
||||||
import org.schabi.newpipe.util.DeviceUtils;
|
import org.schabi.newpipe.util.DeviceUtils;
|
||||||
import org.schabi.newpipe.util.ExtractorHelper;
|
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 androidx.recyclerview.widget.ItemTouchHelper.Callback.makeMovementFlags;
|
||||||
import static java.util.Arrays.asList;
|
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;
|
import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView;
|
||||||
|
|
||||||
public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.InfoItemsPage<?>>
|
public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.InfoItemsPage<?>>
|
||||||
@ -413,7 +413,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||||||
searchEditText.setText("");
|
searchEditText.setText("");
|
||||||
showKeyboardSearch();
|
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");
|
Log.d(TAG, "showSuggestionsPanel() called");
|
||||||
}
|
}
|
||||||
suggestionsPanelVisible = true;
|
suggestionsPanelVisible = true;
|
||||||
animateView(searchBinding.suggestionsPanel, AnimationUtils.Type.LIGHT_SLIDE_AND_ALPHA,
|
animate(searchBinding.suggestionsPanel, true, 200,
|
||||||
true, 200);
|
AnimationType.LIGHT_SLIDE_AND_ALPHA);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void hideSuggestionsPanel() {
|
private void hideSuggestionsPanel() {
|
||||||
@ -653,8 +653,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||||||
Log.d(TAG, "hideSuggestionsPanel() called");
|
Log.d(TAG, "hideSuggestionsPanel() called");
|
||||||
}
|
}
|
||||||
suggestionsPanelVisible = false;
|
suggestionsPanelVisible = false;
|
||||||
animateView(searchBinding.suggestionsPanel, AnimationUtils.Type.LIGHT_SLIDE_AND_ALPHA,
|
animate(searchBinding.suggestionsPanel, false, 200,
|
||||||
false, 200);
|
AnimationType.LIGHT_SLIDE_AND_ALPHA);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showKeyboardSearch() {
|
private void showKeyboardSearch() {
|
||||||
|
@ -20,8 +20,8 @@ import org.schabi.newpipe.extractor.ListExtractor;
|
|||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||||
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
||||||
|
import org.schabi.newpipe.ktx.ViewUtils;
|
||||||
import org.schabi.newpipe.report.UserAction;
|
import org.schabi.newpipe.report.UserAction;
|
||||||
import org.schabi.newpipe.util.AnimationUtils;
|
|
||||||
import org.schabi.newpipe.util.RelatedStreamInfo;
|
import org.schabi.newpipe.util.RelatedStreamInfo;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@ -123,7 +123,7 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf
|
|||||||
if (headerBinding != null) {
|
if (headerBinding != null) {
|
||||||
headerBinding.getRoot().setVisibility(View.VISIBLE);
|
headerBinding.getRoot().setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
AnimationUtils.slideUp(getView(), 120, 96, 0.06f);
|
ViewUtils.slideUp(requireView(), 120, 96, 0.06f);
|
||||||
|
|
||||||
if (!result.getErrors().isEmpty()) {
|
if (!result.getErrors().isEmpty()) {
|
||||||
showSnackBarError(result.getErrors(), UserAction.REQUESTED_STREAM,
|
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.StreamInfoItem;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
||||||
|
import org.schabi.newpipe.ktx.ViewUtils;
|
||||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||||
import org.schabi.newpipe.util.AnimationUtils;
|
|
||||||
import org.schabi.newpipe.util.ImageDisplayConstants;
|
import org.schabi.newpipe.util.ImageDisplayConstants;
|
||||||
import org.schabi.newpipe.util.Localization;
|
import org.schabi.newpipe.util.Localization;
|
||||||
import org.schabi.newpipe.views.AnimatedProgressBar;
|
import org.schabi.newpipe.views.AnimatedProgressBar;
|
||||||
@ -125,10 +125,10 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder {
|
|||||||
} else {
|
} else {
|
||||||
itemProgressView.setProgress((int) TimeUnit.MILLISECONDS
|
itemProgressView.setProgress((int) TimeUnit.MILLISECONDS
|
||||||
.toSeconds(state.getProgressTime()));
|
.toSeconds(state.getProgressTime()));
|
||||||
AnimationUtils.animateView(itemProgressView, true, 500);
|
ViewUtils.animate(itemProgressView, true, 500);
|
||||||
}
|
}
|
||||||
} else if (itemProgressView.getVisibility() == View.VISIBLE) {
|
} 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.BaseStateFragment;
|
||||||
import org.schabi.newpipe.fragments.list.ListViewContract;
|
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
|
* 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() {
|
public void showLoading() {
|
||||||
super.showLoading();
|
super.showLoading();
|
||||||
if (itemsList != null) {
|
if (itemsList != null) {
|
||||||
animateView(itemsList, false, 200);
|
animate(itemsList, false, 200);
|
||||||
}
|
}
|
||||||
if (headerRootBinding != null) {
|
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() {
|
public void hideLoading() {
|
||||||
super.hideLoading();
|
super.hideLoading();
|
||||||
if (itemsList != null) {
|
if (itemsList != null) {
|
||||||
animateView(itemsList, true, 200);
|
animate(itemsList, true, 200);
|
||||||
}
|
}
|
||||||
if (headerRootBinding != null) {
|
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);
|
showListFooter(false);
|
||||||
|
|
||||||
if (itemsList != null) {
|
if (itemsList != null) {
|
||||||
animateView(itemsList, false, 200);
|
animate(itemsList, false, 200);
|
||||||
}
|
}
|
||||||
if (headerRootBinding != null) {
|
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.ErrorRetryBinding
|
||||||
import org.schabi.newpipe.databinding.FragmentFeedBinding
|
import org.schabi.newpipe.databinding.FragmentFeedBinding
|
||||||
import org.schabi.newpipe.fragments.list.BaseListFragment
|
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.local.feed.service.FeedLoadService
|
||||||
import org.schabi.newpipe.report.UserAction
|
import org.schabi.newpipe.report.UserAction
|
||||||
import org.schabi.newpipe.util.AnimationUtils.animateView
|
|
||||||
import org.schabi.newpipe.util.Localization
|
import org.schabi.newpipe.util.Localization
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
|
|
||||||
@ -180,50 +180,50 @@ class FeedFragment : BaseListFragment<FeedState, Unit>() {
|
|||||||
// /////////////////////////////////////////////////////////////////////////
|
// /////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
override fun showLoading() {
|
override fun showLoading() {
|
||||||
animateView(feedBinding.refreshRootView, false, 0)
|
feedBinding.refreshRootView.animate(false, 0)
|
||||||
animateView(feedBinding.itemsList, false, 0)
|
feedBinding.itemsList.animate(false, 0)
|
||||||
|
|
||||||
animateView(feedBinding.loadingProgressBar, true, 200)
|
feedBinding.loadingProgressBar.animate(true, 200)
|
||||||
animateView(feedBinding.loadingProgressText, true, 200)
|
feedBinding.loadingProgressText.animate(true, 200)
|
||||||
|
|
||||||
animateView(feedBinding.emptyStateView.root, false, 0)
|
feedBinding.emptyStateView.root.animate(false, 0)
|
||||||
animateView(errorBinding.root, false, 0)
|
errorBinding.root.animate(false, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hideLoading() {
|
override fun hideLoading() {
|
||||||
animateView(feedBinding.refreshRootView, true, 200)
|
feedBinding.refreshRootView.animate(true, 200)
|
||||||
animateView(feedBinding.itemsList, true, 300)
|
feedBinding.itemsList.animate(true, 300)
|
||||||
|
|
||||||
animateView(feedBinding.loadingProgressBar, false, 0)
|
feedBinding.loadingProgressBar.animate(false, 0)
|
||||||
animateView(feedBinding.loadingProgressText, false, 0)
|
feedBinding.loadingProgressText.animate(false, 0)
|
||||||
|
|
||||||
animateView(feedBinding.emptyStateView.root, false, 0)
|
feedBinding.emptyStateView.root.animate(false, 0)
|
||||||
animateView(errorBinding.root, false, 0)
|
errorBinding.root.animate(false, 0)
|
||||||
feedBinding.swiperefresh.isRefreshing = false
|
feedBinding.swiperefresh.isRefreshing = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showEmptyState() {
|
override fun showEmptyState() {
|
||||||
animateView(feedBinding.refreshRootView, true, 200)
|
feedBinding.refreshRootView.animate(true, 200)
|
||||||
animateView(feedBinding.itemsList, false, 0)
|
feedBinding.itemsList.animate(false, 0)
|
||||||
|
|
||||||
animateView(feedBinding.loadingProgressBar, false, 0)
|
feedBinding.loadingProgressBar.animate(false, 0)
|
||||||
animateView(feedBinding.loadingProgressText, false, 0)
|
feedBinding.loadingProgressText.animate(false, 0)
|
||||||
|
|
||||||
animateView(feedBinding.emptyStateView.root, true, 800)
|
feedBinding.emptyStateView.root.animate(true, 800)
|
||||||
animateView(errorBinding.root, false, 0)
|
errorBinding.root.animate(false, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showError(message: String, showRetryButton: Boolean) {
|
override fun showError(message: String, showRetryButton: Boolean) {
|
||||||
infoListAdapter.clearStreamItemList()
|
infoListAdapter.clearStreamItemList()
|
||||||
animateView(feedBinding.refreshRootView, false, 120)
|
feedBinding.refreshRootView.animate(false, 120)
|
||||||
animateView(feedBinding.itemsList, false, 120)
|
feedBinding.itemsList.animate(false, 120)
|
||||||
|
|
||||||
animateView(feedBinding.loadingProgressBar, false, 120)
|
feedBinding.loadingProgressBar.animate(false, 120)
|
||||||
animateView(feedBinding.loadingProgressText, false, 120)
|
feedBinding.loadingProgressText.animate(false, 120)
|
||||||
|
|
||||||
errorBinding.errorMessageView.text = message
|
errorBinding.errorMessageView.text = message
|
||||||
animateView(errorBinding.errorButtonRetry, showRetryButton, if (showRetryButton) 600 else 0)
|
errorBinding.errorButtonRetry.animate(showRetryButton, if (showRetryButton) 600 else 0)
|
||||||
animateView(errorBinding.root, true, 300)
|
errorBinding.root.animate(true, 300)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleResult(result: FeedState) {
|
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.LocalItem;
|
||||||
import org.schabi.newpipe.database.playlist.PlaylistStreamEntry;
|
import org.schabi.newpipe.database.playlist.PlaylistStreamEntry;
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
|
import org.schabi.newpipe.ktx.ViewUtils;
|
||||||
import org.schabi.newpipe.local.LocalItemBuilder;
|
import org.schabi.newpipe.local.LocalItemBuilder;
|
||||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||||
import org.schabi.newpipe.util.AnimationUtils;
|
|
||||||
import org.schabi.newpipe.util.ImageDisplayConstants;
|
import org.schabi.newpipe.util.ImageDisplayConstants;
|
||||||
import org.schabi.newpipe.util.Localization;
|
import org.schabi.newpipe.util.Localization;
|
||||||
import org.schabi.newpipe.views.AnimatedProgressBar;
|
import org.schabi.newpipe.views.AnimatedProgressBar;
|
||||||
@ -117,10 +117,10 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder {
|
|||||||
} else {
|
} else {
|
||||||
itemProgressView.setProgress((int) TimeUnit.MILLISECONDS
|
itemProgressView.setProgress((int) TimeUnit.MILLISECONDS
|
||||||
.toSeconds(item.getProgressTime()));
|
.toSeconds(item.getProgressTime()));
|
||||||
AnimationUtils.animateView(itemProgressView, true, 500);
|
ViewUtils.animate(itemProgressView, true, 500);
|
||||||
}
|
}
|
||||||
} else if (itemProgressView.getVisibility() == View.VISIBLE) {
|
} 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.LocalItem;
|
||||||
import org.schabi.newpipe.database.stream.StreamStatisticsEntry;
|
import org.schabi.newpipe.database.stream.StreamStatisticsEntry;
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
|
import org.schabi.newpipe.ktx.ViewUtils;
|
||||||
import org.schabi.newpipe.local.LocalItemBuilder;
|
import org.schabi.newpipe.local.LocalItemBuilder;
|
||||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||||
import org.schabi.newpipe.util.AnimationUtils;
|
|
||||||
import org.schabi.newpipe.util.ImageDisplayConstants;
|
import org.schabi.newpipe.util.ImageDisplayConstants;
|
||||||
import org.schabi.newpipe.util.Localization;
|
import org.schabi.newpipe.util.Localization;
|
||||||
import org.schabi.newpipe.views.AnimatedProgressBar;
|
import org.schabi.newpipe.views.AnimatedProgressBar;
|
||||||
@ -148,10 +148,10 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
|
|||||||
} else {
|
} else {
|
||||||
itemProgressView.setProgress((int) TimeUnit.MILLISECONDS
|
itemProgressView.setProgress((int) TimeUnit.MILLISECONDS
|
||||||
.toSeconds(item.getProgressTime()));
|
.toSeconds(item.getProgressTime()));
|
||||||
AnimationUtils.animateView(itemProgressView, true, 500);
|
ViewUtils.animate(itemProgressView, true, 500);
|
||||||
}
|
}
|
||||||
} else if (itemProgressView.getVisibility() == View.VISIBLE) {
|
} 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 java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import icepick.State;
|
import icepick.State;
|
||||||
import io.reactivex.rxjava3.core.Flowable;
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.rxjava3.core.Flowable;
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||||
import io.reactivex.rxjava3.disposables.Disposable;
|
import io.reactivex.rxjava3.disposables.Disposable;
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||||
import io.reactivex.rxjava3.subjects.PublishSubject;
|
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> {
|
public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistStreamEntry>, Void> {
|
||||||
// Save the list 10 seconds after the last change occurred
|
// Save the list 10 seconds after the last change occurred
|
||||||
@ -201,8 +201,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||||||
public void showLoading() {
|
public void showLoading() {
|
||||||
super.showLoading();
|
super.showLoading();
|
||||||
if (headerBinding != null) {
|
if (headerBinding != null) {
|
||||||
animateView(headerBinding.getRoot(), false, 200);
|
animate(headerBinding.getRoot(), false, 200);
|
||||||
animateView(playlistControlBinding.getRoot(), false, 200);
|
animate(playlistControlBinding.getRoot(), false, 200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,8 +210,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||||||
public void hideLoading() {
|
public void hideLoading() {
|
||||||
super.hideLoading();
|
super.hideLoading();
|
||||||
if (headerBinding != null) {
|
if (headerBinding != null) {
|
||||||
animateView(headerBinding.getRoot(), true, 200);
|
animate(headerBinding.getRoot(), true, 200);
|
||||||
animateView(playlistControlBinding.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.databinding.FragmentSubscriptionBinding
|
||||||
import org.schabi.newpipe.extractor.channel.ChannelInfoItem
|
import org.schabi.newpipe.extractor.channel.ChannelInfoItem
|
||||||
import org.schabi.newpipe.fragments.BaseStateFragment
|
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.SubscriptionViewModel.SubscriptionState
|
||||||
import org.schabi.newpipe.local.subscription.dialog.FeedGroupDialog
|
import org.schabi.newpipe.local.subscription.dialog.FeedGroupDialog
|
||||||
import org.schabi.newpipe.local.subscription.dialog.FeedGroupReorderDialog
|
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.KEY_VALUE
|
||||||
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.PREVIOUS_EXPORT_MODE
|
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.PREVIOUS_EXPORT_MODE
|
||||||
import org.schabi.newpipe.report.UserAction
|
import org.schabi.newpipe.report.UserAction
|
||||||
import org.schabi.newpipe.util.AnimationUtils.animateView
|
|
||||||
import org.schabi.newpipe.util.FilePickerActivityHelper
|
import org.schabi.newpipe.util.FilePickerActivityHelper
|
||||||
import org.schabi.newpipe.util.NavigationHelper
|
import org.schabi.newpipe.util.NavigationHelper
|
||||||
import org.schabi.newpipe.util.OnClickGesture
|
import org.schabi.newpipe.util.OnClickGesture
|
||||||
@ -407,12 +407,12 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
|||||||
|
|
||||||
override fun showLoading() {
|
override fun showLoading() {
|
||||||
super.showLoading()
|
super.showLoading()
|
||||||
animateView(binding.itemsList, false, 100)
|
binding.itemsList.animate(false, 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hideLoading() {
|
override fun hideLoading() {
|
||||||
super.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.R
|
||||||
import org.schabi.newpipe.extractor.NewPipe
|
import org.schabi.newpipe.extractor.NewPipe
|
||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException
|
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.ServiceHelper
|
||||||
import org.schabi.newpipe.util.ThemeHelper
|
import org.schabi.newpipe.util.ThemeHelper
|
||||||
import org.schabi.newpipe.views.CollapsibleView
|
import org.schabi.newpipe.views.CollapsibleView
|
||||||
@ -49,8 +49,7 @@ class FeedImportExportItem(
|
|||||||
|
|
||||||
expandIconListener?.let { viewHolder.import_export_options.removeListener(it) }
|
expandIconListener?.let { viewHolder.import_export_options.removeListener(it) }
|
||||||
expandIconListener = CollapsibleView.StateListener { newState ->
|
expandIconListener = CollapsibleView.StateListener { newState ->
|
||||||
AnimationUtils.animateRotation(
|
viewHolder.import_export_expand_icon.animateRotation(
|
||||||
viewHolder.import_export_expand_icon,
|
|
||||||
250, if (newState == CollapsibleView.COLLAPSED) 0 else 180
|
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 kotlinx.android.synthetic.main.picker_subscription_item.view.*
|
||||||
import org.schabi.newpipe.R
|
import org.schabi.newpipe.R
|
||||||
import org.schabi.newpipe.database.subscription.SubscriptionEntity
|
import org.schabi.newpipe.database.subscription.SubscriptionEntity
|
||||||
import org.schabi.newpipe.util.AnimationUtils
|
import org.schabi.newpipe.ktx.AnimationType
|
||||||
import org.schabi.newpipe.util.AnimationUtils.animateView
|
import org.schabi.newpipe.ktx.animate
|
||||||
import org.schabi.newpipe.util.ImageDisplayConstants
|
import org.schabi.newpipe.util.ImageDisplayConstants
|
||||||
|
|
||||||
data class PickerSubscriptionItem(
|
data class PickerSubscriptionItem(
|
||||||
@ -41,9 +41,6 @@ data class PickerSubscriptionItem(
|
|||||||
|
|
||||||
fun updateSelected(containerView: View, isSelected: Boolean) {
|
fun updateSelected(containerView: View, isSelected: Boolean) {
|
||||||
this.isSelected = isSelected
|
this.isSelected = isSelected
|
||||||
animateView(
|
containerView.selected_highlight.animate(isSelected, 150, AnimationType.LIGHT_SCALE_AND_ALPHA)
|
||||||
containerView.selected_highlight,
|
|
||||||
AnimationUtils.Type.LIGHT_SCALE_AND_ALPHA, isSelected, 150
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,7 @@ import org.schabi.newpipe.extractor.stream.VideoStream;
|
|||||||
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
|
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
|
||||||
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
|
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
|
||||||
import org.schabi.newpipe.info_list.StreamSegmentAdapter;
|
import org.schabi.newpipe.info_list.StreamSegmentAdapter;
|
||||||
|
import org.schabi.newpipe.ktx.AnimationType;
|
||||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||||
import org.schabi.newpipe.player.MainPlayer.PlayerType;
|
import org.schabi.newpipe.player.MainPlayer.PlayerType;
|
||||||
import org.schabi.newpipe.player.event.PlayerEventListener;
|
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.AudioPlaybackResolver;
|
||||||
import org.schabi.newpipe.player.resolver.MediaSourceTag;
|
import org.schabi.newpipe.player.resolver.MediaSourceTag;
|
||||||
import org.schabi.newpipe.player.resolver.VideoPlaybackResolver;
|
import org.schabi.newpipe.player.resolver.VideoPlaybackResolver;
|
||||||
import org.schabi.newpipe.util.AnimationUtils;
|
|
||||||
import org.schabi.newpipe.util.DeviceUtils;
|
import org.schabi.newpipe.util.DeviceUtils;
|
||||||
import org.schabi.newpipe.util.ImageDisplayConstants;
|
import org.schabi.newpipe.util.ImageDisplayConstants;
|
||||||
import org.schabi.newpipe.util.KoreUtil;
|
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 com.google.android.exoplayer2.Player.RepeatMode;
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
|
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_CLOSE;
|
||||||
import static org.schabi.newpipe.player.MainPlayer.ACTION_FAST_FORWARD;
|
import static org.schabi.newpipe.player.MainPlayer.ACTION_FAST_FORWARD;
|
||||||
import static org.schabi.newpipe.player.MainPlayer.ACTION_FAST_REWIND;
|
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.retrievePopupLayoutParamsFromPrefs;
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.retrieveSeekDurationFromPreferences;
|
import static org.schabi.newpipe.player.helper.PlayerHelper.retrieveSeekDurationFromPreferences;
|
||||||
import static org.schabi.newpipe.player.helper.PlayerHelper.savePlaybackParametersToPrefs;
|
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.getPopupResolutionIndex;
|
||||||
import static org.schabi.newpipe.util.ListHelper.getResolutionIndex;
|
import static org.schabi.newpipe.util.ListHelper.getResolutionIndex;
|
||||||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
||||||
@ -1560,8 +1559,8 @@ public final class Player implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
showControls(0);
|
showControls(0);
|
||||||
animateView(binding.currentDisplaySeek, AnimationUtils.Type.SCALE_AND_ALPHA, true,
|
animate(binding.currentDisplaySeek, true, DEFAULT_CONTROLS_DURATION,
|
||||||
DEFAULT_CONTROLS_DURATION);
|
AnimationType.SCALE_AND_ALPHA);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // seekbar listener
|
@Override // seekbar listener
|
||||||
@ -1576,7 +1575,7 @@ public final class Player implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.playbackCurrentTime.setText(getTimeString(seekBar.getProgress()));
|
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) {
|
if (currentState == STATE_PAUSED_SEEK) {
|
||||||
changeState(STATE_BUFFERING);
|
changeState(STATE_BUFFERING);
|
||||||
@ -1682,8 +1681,8 @@ public final class Player implements
|
|||||||
: DPAD_CONTROLS_HIDE_TIME;
|
: DPAD_CONTROLS_HIDE_TIME;
|
||||||
|
|
||||||
showHideShadow(true, DEFAULT_CONTROLS_DURATION);
|
showHideShadow(true, DEFAULT_CONTROLS_DURATION);
|
||||||
animateView(binding.playbackControlRoot, true, DEFAULT_CONTROLS_DURATION, 0,
|
animate(binding.playbackControlRoot, true, DEFAULT_CONTROLS_DURATION,
|
||||||
() -> hideControls(DEFAULT_CONTROLS_DURATION, hideTime));
|
AnimationType.ALPHA, 0, () -> hideControls(DEFAULT_CONTROLS_DURATION, hideTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showControls(final long duration) {
|
public void showControls(final long duration) {
|
||||||
@ -1694,7 +1693,7 @@ public final class Player implements
|
|||||||
showSystemUIPartially();
|
showSystemUIPartially();
|
||||||
controlsVisibilityHandler.removeCallbacksAndMessages(null);
|
controlsVisibilityHandler.removeCallbacksAndMessages(null);
|
||||||
showHideShadow(true, duration);
|
showHideShadow(true, duration);
|
||||||
animateView(binding.playbackControlRoot, true, duration);
|
animate(binding.playbackControlRoot, true, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void hideControls(final long duration, final long delay) {
|
public void hideControls(final long duration, final long delay) {
|
||||||
@ -1708,14 +1707,14 @@ public final class Player implements
|
|||||||
controlsVisibilityHandler.removeCallbacksAndMessages(null);
|
controlsVisibilityHandler.removeCallbacksAndMessages(null);
|
||||||
controlsVisibilityHandler.postDelayed(() -> {
|
controlsVisibilityHandler.postDelayed(() -> {
|
||||||
showHideShadow(false, duration);
|
showHideShadow(false, duration);
|
||||||
animateView(binding.playbackControlRoot, false, duration, 0,
|
animate(binding.playbackControlRoot, false, duration, AnimationType.ALPHA,
|
||||||
this::hideSystemUIIfNeeded);
|
0, this::hideSystemUIIfNeeded);
|
||||||
}, delay);
|
}, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showHideShadow(final boolean show, final long duration) {
|
private void showHideShadow(final boolean show, final long duration) {
|
||||||
animateView(binding.playerTopShadow, show, duration, 0, null);
|
animate(binding.playerTopShadow, show, duration, AnimationType.ALPHA, 0, null);
|
||||||
animateView(binding.playerBottomShadow, show, duration, 0, null);
|
animate(binding.playerBottomShadow, show, duration, AnimationType.ALPHA, 0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showOrHideButtons() {
|
private void showOrHideButtons() {
|
||||||
@ -1913,15 +1912,15 @@ public final class Player implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
controlsVisibilityHandler.removeCallbacksAndMessages(null);
|
controlsVisibilityHandler.removeCallbacksAndMessages(null);
|
||||||
animateView(binding.playbackControlRoot, false, DEFAULT_CONTROLS_DURATION);
|
animate(binding.playbackControlRoot, false, DEFAULT_CONTROLS_DURATION);
|
||||||
|
|
||||||
binding.playbackSeekBar.setEnabled(false);
|
binding.playbackSeekBar.setEnabled(false);
|
||||||
binding.playbackSeekBar.getThumb()
|
binding.playbackSeekBar.getThumb()
|
||||||
.setColorFilter(new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_IN));
|
.setColorFilter(new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_IN));
|
||||||
|
|
||||||
binding.loadingPanel.setBackgroundColor(Color.BLACK);
|
binding.loadingPanel.setBackgroundColor(Color.BLACK);
|
||||||
animateView(binding.loadingPanel, true, 0);
|
animate(binding.loadingPanel, true, 0);
|
||||||
animateView(binding.surfaceForeground, true, 100);
|
animate(binding.surfaceForeground, true, 100);
|
||||||
|
|
||||||
binding.playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp);
|
binding.playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp);
|
||||||
animatePlayButtons(false, 100);
|
animatePlayButtons(false, 100);
|
||||||
@ -1948,9 +1947,9 @@ public final class Player implements
|
|||||||
|
|
||||||
binding.loadingPanel.setVisibility(View.GONE);
|
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);
|
binding.playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp);
|
||||||
animatePlayButtons(true, 200);
|
animatePlayButtons(true, 200);
|
||||||
@ -1991,7 +1990,7 @@ public final class Player implements
|
|||||||
showControls(400);
|
showControls(400);
|
||||||
binding.loadingPanel.setVisibility(View.GONE);
|
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);
|
binding.playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp);
|
||||||
animatePlayButtons(true, 200);
|
animatePlayButtons(true, 200);
|
||||||
@ -2029,7 +2028,7 @@ public final class Player implements
|
|||||||
Log.d(TAG, "onCompleted() called");
|
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);
|
binding.playPauseButton.setImageResource(R.drawable.ic_replay_white_24dp);
|
||||||
animatePlayButtons(true, DEFAULT_CONTROLS_DURATION);
|
animatePlayButtons(true, DEFAULT_CONTROLS_DURATION);
|
||||||
@ -2051,13 +2050,13 @@ public final class Player implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
showControls(500);
|
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);
|
binding.loadingPanel.setVisibility(View.GONE);
|
||||||
animateView(binding.surfaceForeground, true, 100);
|
animate(binding.surfaceForeground, true, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void animatePlayButtons(final boolean show, final int duration) {
|
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;
|
boolean showQueueButtons = show;
|
||||||
if (playQueue == null) {
|
if (playQueue == null) {
|
||||||
@ -2065,18 +2064,18 @@ public final class Player implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!showQueueButtons || playQueue.getIndex() > 0) {
|
if (!showQueueButtons || playQueue.getIndex() > 0) {
|
||||||
animateView(
|
animate(
|
||||||
binding.playPreviousButton,
|
binding.playPreviousButton,
|
||||||
AnimationUtils.Type.SCALE_AND_ALPHA,
|
|
||||||
showQueueButtons,
|
showQueueButtons,
|
||||||
duration);
|
duration,
|
||||||
|
AnimationType.SCALE_AND_ALPHA);
|
||||||
}
|
}
|
||||||
if (!showQueueButtons || playQueue.getIndex() + 1 < playQueue.getStreams().size()) {
|
if (!showQueueButtons || playQueue.getIndex() + 1 < playQueue.getStreams().size()) {
|
||||||
animateView(
|
animate(
|
||||||
binding.playNextButton,
|
binding.playNextButton,
|
||||||
AnimationUtils.Type.SCALE_AND_ALPHA,
|
|
||||||
showQueueButtons,
|
showQueueButtons,
|
||||||
duration);
|
duration,
|
||||||
|
AnimationType.SCALE_AND_ALPHA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//endregion
|
//endregion
|
||||||
@ -2274,7 +2273,7 @@ public final class Player implements
|
|||||||
@Override
|
@Override
|
||||||
public void onRenderedFirstFrame() {
|
public void onRenderedFirstFrame() {
|
||||||
//TODO check if this causes black screen when switching to fullscreen
|
//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
|
//endregion
|
||||||
|
|
||||||
@ -2871,8 +2870,8 @@ public final class Player implements
|
|||||||
|
|
||||||
hideControls(0, 0);
|
hideControls(0, 0);
|
||||||
binding.itemsListPanel.requestFocus();
|
binding.itemsListPanel.requestFocus();
|
||||||
animateView(binding.itemsListPanel, SLIDE_AND_ALPHA, true,
|
animate(binding.itemsListPanel, true, DEFAULT_CONTROLS_DURATION,
|
||||||
DEFAULT_CONTROLS_DURATION);
|
AnimationType.SLIDE_AND_ALPHA);
|
||||||
|
|
||||||
binding.itemsList.scrollToPosition(playQueue.getIndex());
|
binding.itemsList.scrollToPosition(playQueue.getIndex());
|
||||||
}
|
}
|
||||||
@ -2905,8 +2904,8 @@ public final class Player implements
|
|||||||
|
|
||||||
hideControls(0, 0);
|
hideControls(0, 0);
|
||||||
binding.itemsListPanel.requestFocus();
|
binding.itemsListPanel.requestFocus();
|
||||||
animateView(binding.itemsListPanel, SLIDE_AND_ALPHA, true,
|
animate(binding.itemsListPanel, true, DEFAULT_CONTROLS_DURATION,
|
||||||
DEFAULT_CONTROLS_DURATION);
|
AnimationType.SLIDE_AND_ALPHA);
|
||||||
|
|
||||||
final int adapterPosition = getNearestStreamSegmentPosition(simpleExoPlayer
|
final int adapterPosition = getNearestStreamSegmentPosition(simpleExoPlayer
|
||||||
.getCurrentPosition());
|
.getCurrentPosition());
|
||||||
@ -2942,8 +2941,8 @@ public final class Player implements
|
|||||||
itemTouchHelper.attachToRecyclerView(null);
|
itemTouchHelper.attachToRecyclerView(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
animateView(binding.itemsListPanel, SLIDE_AND_ALPHA, false,
|
animate(binding.itemsListPanel, false, DEFAULT_CONTROLS_DURATION,
|
||||||
DEFAULT_CONTROLS_DURATION, 0, () -> {
|
AnimationType.SLIDE_AND_ALPHA, 0, () -> {
|
||||||
// Even when queueLayout is GONE it receives touch events
|
// Even when queueLayout is GONE it receives touch events
|
||||||
// and ruins normal behavior of the app. This line fixes it
|
// and ruins normal behavior of the app. This line fixes it
|
||||||
binding.itemsListPanel.setTranslationY(
|
binding.itemsListPanel.setTranslationY(
|
||||||
@ -3451,18 +3450,19 @@ public final class Player implements
|
|||||||
if (currentState != STATE_COMPLETED) {
|
if (currentState != STATE_COMPLETED) {
|
||||||
controlsVisibilityHandler.removeCallbacksAndMessages(null);
|
controlsVisibilityHandler.removeCallbacksAndMessages(null);
|
||||||
showHideShadow(true, DEFAULT_CONTROLS_DURATION);
|
showHideShadow(true, DEFAULT_CONTROLS_DURATION);
|
||||||
animateView(binding.playbackControlRoot, true, DEFAULT_CONTROLS_DURATION, 0, () -> {
|
animate(binding.playbackControlRoot, true, DEFAULT_CONTROLS_DURATION,
|
||||||
if (currentState == STATE_PLAYING && !isSomePopupMenuVisible) {
|
AnimationType.ALPHA, 0, () -> {
|
||||||
if (v.getId() == binding.playPauseButton.getId()
|
if (currentState == STATE_PLAYING && !isSomePopupMenuVisible) {
|
||||||
// Hide controls in fullscreen immediately
|
if (v.getId() == binding.playPauseButton.getId()
|
||||||
|| (v.getId() == binding.screenRotationButton.getId()
|
// Hide controls in fullscreen immediately
|
||||||
&& isFullscreen)) {
|
|| (v.getId() == binding.screenRotationButton.getId()
|
||||||
hideControls(0, 0);
|
&& isFullscreen)) {
|
||||||
} else {
|
hideControls(0, 0);
|
||||||
hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
|
} else {
|
||||||
}
|
hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3531,9 +3531,8 @@ public final class Player implements
|
|||||||
|
|
||||||
animateRotation(binding.moreOptionsButton, DEFAULT_CONTROLS_DURATION,
|
animateRotation(binding.moreOptionsButton, DEFAULT_CONTROLS_DURATION,
|
||||||
isMoreControlsVisible ? 0 : 180);
|
isMoreControlsVisible ? 0 : 180);
|
||||||
animateView(binding.secondaryControls, SLIDE_AND_ALPHA, !isMoreControlsVisible,
|
animate(binding.secondaryControls, !isMoreControlsVisible, DEFAULT_CONTROLS_DURATION,
|
||||||
DEFAULT_CONTROLS_DURATION, 0,
|
AnimationType.SLIDE_AND_ALPHA, 0, () -> {
|
||||||
() -> {
|
|
||||||
// Fix for a ripple effect on background drawable.
|
// Fix for a ripple effect on background drawable.
|
||||||
// When view returns from GONE state it takes more milliseconds than returning
|
// When view returns from GONE state it takes more milliseconds than returning
|
||||||
// from INVISIBLE state. And the delay makes ripple background end to fast
|
// 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.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewConfiguration
|
import android.view.ViewConfiguration
|
||||||
|
import org.schabi.newpipe.ktx.animate
|
||||||
import org.schabi.newpipe.player.MainPlayer
|
import org.schabi.newpipe.player.MainPlayer
|
||||||
import org.schabi.newpipe.player.Player
|
import org.schabi.newpipe.player.Player
|
||||||
import org.schabi.newpipe.player.helper.PlayerHelper
|
import org.schabi.newpipe.player.helper.PlayerHelper
|
||||||
import org.schabi.newpipe.player.helper.PlayerHelper.savePopupPositionAndSizeToPrefs
|
import org.schabi.newpipe.player.helper.PlayerHelper.savePopupPositionAndSizeToPrefs
|
||||||
import org.schabi.newpipe.util.AnimationUtils
|
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.hypot
|
import kotlin.math.hypot
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
@ -364,7 +364,7 @@ abstract class BasePlayerGestureListener(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isMovingInPopup) {
|
if (!isMovingInPopup) {
|
||||||
AnimationUtils.animateView(player.closeOverlayButton, true, 200)
|
player.closeOverlayButton.animate(true, 200)
|
||||||
}
|
}
|
||||||
|
|
||||||
isMovingInPopup = true
|
isMovingInPopup = true
|
||||||
|
@ -17,11 +17,12 @@ import org.schabi.newpipe.player.MainPlayer;
|
|||||||
import org.schabi.newpipe.player.Player;
|
import org.schabi.newpipe.player.Player;
|
||||||
import org.schabi.newpipe.player.helper.PlayerHelper;
|
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_DURATION;
|
||||||
import static org.schabi.newpipe.player.Player.DEFAULT_CONTROLS_HIDE_TIME;
|
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.player.Player.STATE_PLAYING;
|
||||||
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GestureListener for the player
|
* GestureListener for the player
|
||||||
@ -123,11 +124,11 @@ public class PlayerGestureListener
|
|||||||
final View closingOverlayView = player.getClosingOverlayView();
|
final View closingOverlayView = player.getClosingOverlayView();
|
||||||
if (player.isInsideClosingRadius(movingEvent)) {
|
if (player.isInsideClosingRadius(movingEvent)) {
|
||||||
if (closingOverlayView.getVisibility() == View.GONE) {
|
if (closingOverlayView.getVisibility() == View.GONE) {
|
||||||
animateView(closingOverlayView, true, 250);
|
animate(closingOverlayView, true, 250);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (closingOverlayView.getVisibility() == View.VISIBLE) {
|
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) {
|
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) {
|
if (player.getBrightnessRelativeLayout().getVisibility() == View.VISIBLE) {
|
||||||
player.getBrightnessRelativeLayout().setVisibility(View.GONE);
|
player.getBrightnessRelativeLayout().setVisibility(View.GONE);
|
||||||
@ -195,7 +196,7 @@ public class PlayerGestureListener
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (player.getBrightnessRelativeLayout().getVisibility() != View.VISIBLE) {
|
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) {
|
if (player.getVolumeRelativeLayout().getVisibility() == View.VISIBLE) {
|
||||||
player.getVolumeRelativeLayout().setVisibility(View.GONE);
|
player.getVolumeRelativeLayout().setVisibility(View.GONE);
|
||||||
@ -215,21 +216,18 @@ public class PlayerGestureListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (player.getVolumeRelativeLayout().getVisibility() == View.VISIBLE) {
|
if (player.getVolumeRelativeLayout().getVisibility() == View.VISIBLE) {
|
||||||
animateView(player.getVolumeRelativeLayout(), SCALE_AND_ALPHA,
|
animate(player.getVolumeRelativeLayout(), false, 200, SCALE_AND_ALPHA,
|
||||||
false, 200, 200);
|
200);
|
||||||
}
|
}
|
||||||
if (player.getBrightnessRelativeLayout().getVisibility() == View.VISIBLE) {
|
if (player.getBrightnessRelativeLayout().getVisibility() == View.VISIBLE) {
|
||||||
animateView(player.getBrightnessRelativeLayout(), SCALE_AND_ALPHA,
|
animate(player.getBrightnessRelativeLayout(), false, 200, SCALE_AND_ALPHA,
|
||||||
false, 200, 200);
|
200);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.isControlsVisible() && player.getCurrentState() == STATE_PLAYING) {
|
if (player.isControlsVisible() && player.getCurrentState() == STATE_PLAYING) {
|
||||||
player.hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
|
player.hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (player == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (player.isControlsVisible() && player.getCurrentState() == STATE_PLAYING) {
|
if (player.isControlsVisible() && player.getCurrentState() == STATE_PLAYING) {
|
||||||
player.hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
|
player.hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
|
||||||
}
|
}
|
||||||
@ -237,10 +235,10 @@ public class PlayerGestureListener
|
|||||||
if (player.isInsideClosingRadius(event)) {
|
if (player.isInsideClosingRadius(event)) {
|
||||||
player.closePopup();
|
player.closePopup();
|
||||||
} else {
|
} else {
|
||||||
animateView(player.getClosingOverlayView(), false, 0);
|
animate(player.getClosingOverlayView(), false, 0);
|
||||||
|
|
||||||
if (!player.isPopupClosing()) {
|
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.getLoadingPanel().setVisibility(View.GONE);
|
||||||
|
|
||||||
player.hideControls(0, 0);
|
player.hideControls(0, 0);
|
||||||
animateView(player.getCurrentDisplaySeek(), false, 0, 0);
|
animate(player.getCurrentDisplaySeek(), false, 0, ALPHA, 0);
|
||||||
animateView(player.getResizingIndicator(), true, 200, 0);
|
animate(player.getResizingIndicator(), true, 200, ALPHA, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -264,7 +262,7 @@ public class PlayerGestureListener
|
|||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "onPopupResizingEnd called");
|
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.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
import org.schabi.newpipe.util.AnimationUtils;
|
import org.schabi.newpipe.ktx.ViewUtils;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -128,7 +128,7 @@ public class CollapsibleView extends LinearLayout {
|
|||||||
if (currentAnimator != null && currentAnimator.isRunning()) {
|
if (currentAnimator != null && currentAnimator.isRunning()) {
|
||||||
currentAnimator.cancel();
|
currentAnimator.cancel();
|
||||||
}
|
}
|
||||||
currentAnimator = AnimationUtils.animateHeight(this, ANIMATION_DURATION, 0);
|
currentAnimator = ViewUtils.animateHeight(this, ANIMATION_DURATION, 0);
|
||||||
|
|
||||||
setCurrentState(COLLAPSED);
|
setCurrentState(COLLAPSED);
|
||||||
}
|
}
|
||||||
@ -151,7 +151,7 @@ public class CollapsibleView extends LinearLayout {
|
|||||||
if (currentAnimator != null && currentAnimator.isRunning()) {
|
if (currentAnimator != null && currentAnimator.isRunning()) {
|
||||||
currentAnimator.cancel();
|
currentAnimator.cancel();
|
||||||
}
|
}
|
||||||
currentAnimator = AnimationUtils.animateHeight(this, ANIMATION_DURATION, this.targetHeight);
|
currentAnimator = ViewUtils.animateHeight(this, ANIMATION_DURATION, this.targetHeight);
|
||||||
setCurrentState(EXPANDED);
|
setCurrentState(EXPANDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user