Merge pull request #4814 from Isira-Seneviratne/Use_view_binding_in_fragments

Use view binding in fragments.
This commit is contained in:
Stypox 2021-01-14 14:40:19 +01:00 committed by GitHub
commit afa6b5c572
19 changed files with 545 additions and 533 deletions

View file

@ -19,12 +19,12 @@ import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapterMenuWorkaround;
import androidx.preference.PreferenceManager;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
import org.schabi.newpipe.BaseFragment;
import org.schabi.newpipe.R;
import org.schabi.newpipe.databinding.FragmentMainBinding;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.ErrorInfo;
@ -34,15 +34,13 @@ import org.schabi.newpipe.settings.tabs.TabsManager;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ServiceHelper;
import org.schabi.newpipe.util.ThemeHelper;
import org.schabi.newpipe.views.ScrollableTabLayout;
import java.util.ArrayList;
import java.util.List;
public class MainFragment extends BaseFragment implements TabLayout.OnTabSelectedListener {
private ViewPager viewPager;
private FragmentMainBinding binding;
private SelectedTabsPagerAdapter pagerAdapter;
private ScrollableTabLayout tabLayout;
private final List<Tab> tabsList = new ArrayList<>();
private TabsManager tabsManager;
@ -90,13 +88,12 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
protected void initViews(final View rootView, final Bundle savedInstanceState) {
super.initViews(rootView, savedInstanceState);
tabLayout = rootView.findViewById(R.id.main_tab_layout);
viewPager = rootView.findViewById(R.id.pager);
binding = FragmentMainBinding.bind(rootView);
tabLayout.setTabIconTint(ColorStateList.valueOf(
binding.mainTabLayout.setTabIconTint(ColorStateList.valueOf(
ThemeHelper.resolveColorFromAttr(requireContext(), R.attr.colorAccent)));
tabLayout.setupWithViewPager(viewPager);
tabLayout.addOnTabSelectedListener(this);
binding.mainTabLayout.setupWithViewPager(binding.pager);
binding.mainTabLayout.addOnTabSelectedListener(this);
setupTabs();
}
@ -120,8 +117,14 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
public void onDestroy() {
super.onDestroy();
tabsManager.unsetSavedTabsListener();
if (viewPager != null) {
viewPager.setAdapter(null);
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (binding != null) {
binding.pager.setAdapter(null);
binding = null;
}
}
@ -172,19 +175,19 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
getChildFragmentManager(), tabsList);
}
viewPager.setAdapter(null);
viewPager.setOffscreenPageLimit(tabsList.size());
viewPager.setAdapter(pagerAdapter);
binding.pager.setAdapter(null);
binding.pager.setOffscreenPageLimit(tabsList.size());
binding.pager.setAdapter(pagerAdapter);
updateTabsIconAndDescription();
updateTitleForTab(viewPager.getCurrentItem());
updateTitleForTab(binding.pager.getCurrentItem());
hasTabsChanged = false;
}
private void updateTabsIconAndDescription() {
for (int i = 0; i < tabsList.size(); i++) {
final TabLayout.Tab tabToSet = tabLayout.getTabAt(i);
final TabLayout.Tab tabToSet = binding.mainTabLayout.getTabAt(i);
if (tabToSet != null) {
final Tab tab = tabsList.get(i);
tabToSet.setIcon(tab.getTabIconRes(requireContext()));

View file

@ -12,13 +12,16 @@ import android.view.MenuInflater;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewbinding.ViewBinding;
import org.schabi.newpipe.R;
import org.schabi.newpipe.databinding.PignateFooterBinding;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
import org.schabi.newpipe.extractor.comments.CommentsInfoItem;
@ -215,12 +218,13 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
// Init
//////////////////////////////////////////////////////////////////////////*/
protected View getListHeader() {
@Nullable
protected ViewBinding getListHeader() {
return null;
}
protected View getListFooter() {
return activity.getLayoutInflater().inflate(R.layout.pignate_footer, itemsList, false);
protected ViewBinding getListFooter() {
return PignateFooterBinding.inflate(activity.getLayoutInflater(), itemsList, false);
}
protected RecyclerView.LayoutManager getListLayoutManager() {
@ -247,8 +251,12 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
itemsList.setLayoutManager(useGrid ? getGridLayoutManager() : getListLayoutManager());
infoListAdapter.setUseGridVariant(useGrid);
infoListAdapter.setFooter(getListFooter());
infoListAdapter.setHeader(getListHeader());
infoListAdapter.setFooter(getListFooter().getRoot());
final ViewBinding listHeader = getListHeader();
if (listHeader != null) {
infoListAdapter.setHeader(listHeader.getRoot());
}
itemsList.setAdapter(infoListAdapter);
}

View file

@ -14,20 +14,21 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.viewbinding.ViewBinding;
import com.jakewharton.rxbinding4.view.RxView;
import org.schabi.newpipe.R;
import org.schabi.newpipe.database.subscription.SubscriptionEntity;
import org.schabi.newpipe.databinding.ChannelHeaderBinding;
import org.schabi.newpipe.databinding.FragmentChannelBinding;
import org.schabi.newpipe.databinding.PlaylistControlBinding;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.NewPipe;
@ -78,22 +79,12 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
//////////////////////////////////////////////////////////////////////////*/
private SubscriptionManager subscriptionManager;
private View headerRootLayout;
private ImageView headerChannelBanner;
private ImageView headerAvatarView;
private TextView headerTitleView;
private ImageView headerSubChannelAvatarView;
private TextView headerSubChannelTitleView;
private TextView headerSubscribersTextView;
private Button headerSubscribeButton;
private View playlistCtrl;
private LinearLayout headerPlayAllButton;
private LinearLayout headerPopupButton;
private LinearLayout headerBackgroundButton;
private FragmentChannelBinding channelBinding;
private ChannelHeaderBinding headerBinding;
private PlaylistControlBinding playlistControlBinding;
private MenuItem menuRssButton;
private TextView contentNotSupportedTextView;
private TextView kaomojiTextView;
private TextView noVideosTextView;
public static ChannelFragment getInstance(final int serviceId, final String url,
final String name) {
@ -132,53 +123,45 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
@Override
public void onViewCreated(final View rootView, final Bundle savedInstanceState) {
super.onViewCreated(rootView, savedInstanceState);
contentNotSupportedTextView = rootView.findViewById(R.id.error_content_not_supported);
kaomojiTextView = rootView.findViewById(R.id.channel_kaomoji);
noVideosTextView = rootView.findViewById(R.id.channel_no_videos);
channelBinding = FragmentChannelBinding.bind(rootView);
}
@Override
public void onDestroy() {
super.onDestroy();
if (disposables != null) {
disposables.clear();
}
disposables.clear();
if (subscribeButtonMonitor != null) {
subscribeButtonMonitor.dispose();
}
}
@Override
public void onDestroyView() {
channelBinding = null;
headerBinding = null;
playlistControlBinding = null;
super.onDestroyView();
}
/*//////////////////////////////////////////////////////////////////////////
// Init
//////////////////////////////////////////////////////////////////////////*/
protected View getListHeader() {
headerRootLayout = activity.getLayoutInflater()
.inflate(R.layout.channel_header, itemsList, false);
headerChannelBanner = headerRootLayout.findViewById(R.id.channel_banner_image);
headerAvatarView = headerRootLayout.findViewById(R.id.channel_avatar_view);
headerTitleView = headerRootLayout.findViewById(R.id.channel_title_view);
headerSubscribersTextView = headerRootLayout.findViewById(R.id.channel_subscriber_view);
headerSubscribeButton = headerRootLayout.findViewById(R.id.channel_subscribe_button);
playlistCtrl = headerRootLayout.findViewById(R.id.playlist_control);
headerSubChannelAvatarView =
headerRootLayout.findViewById(R.id.sub_channel_avatar_view);
headerSubChannelTitleView =
headerRootLayout.findViewById(R.id.sub_channel_title_view);
@Override
protected ViewBinding getListHeader() {
headerBinding = ChannelHeaderBinding
.inflate(activity.getLayoutInflater(), itemsList, false);
playlistControlBinding = headerBinding.playlistControl;
headerPlayAllButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_all_button);
headerPopupButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_popup_button);
headerBackgroundButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_bg_button);
return headerRootLayout;
return headerBinding;
}
@Override
protected void initListeners() {
super.initListeners();
headerSubChannelTitleView.setOnClickListener(this);
headerSubChannelAvatarView.setOnClickListener(this);
headerBinding.subChannelTitleView.setOnClickListener(this);
headerBinding.subChannelAvatarView.setOnClickListener(this);
}
/*//////////////////////////////////////////////////////////////////////////
@ -241,7 +224,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
private void monitorSubscription(final ChannelInfo info) {
final Consumer<Throwable> onError = (Throwable throwable) -> {
animateView(headerSubscribeButton, false, 100);
animateView(headerBinding.channelSubscribeButton, false, 100);
showSnackBarError(throwable, UserAction.SUBSCRIPTION,
NewPipe.getNameOfService(currentInfo.getServiceId()),
"Get subscription status", 0);
@ -351,15 +334,15 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
info.getAvatarUrl(),
info.getDescription(),
info.getSubscriberCount());
subscribeButtonMonitor = monitorSubscribeButton(headerSubscribeButton,
mapOnSubscribe(channel, info));
subscribeButtonMonitor = monitorSubscribeButton(
headerBinding.channelSubscribeButton, mapOnSubscribe(channel, info));
} else {
if (DEBUG) {
Log.d(TAG, "Found subscription to this channel!");
}
final SubscriptionEntity subscription = subscriptionEntities.get(0);
subscribeButtonMonitor = monitorSubscribeButton(headerSubscribeButton,
mapOnUnsubscribe(subscription));
subscribeButtonMonitor = monitorSubscribeButton(
headerBinding.channelSubscribeButton, mapOnUnsubscribe(subscription));
}
};
}
@ -370,7 +353,8 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
+ "isSubscribed = [" + isSubscribed + "]");
}
final boolean isButtonVisible = headerSubscribeButton.getVisibility() == View.VISIBLE;
final boolean isButtonVisible = headerBinding.channelSubscribeButton.getVisibility()
== View.VISIBLE;
final int backgroundDuration = isButtonVisible ? 300 : 0;
final int textDuration = isButtonVisible ? 200 : 0;
@ -382,18 +366,21 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
final int subscribedText = ContextCompat.getColor(activity, R.color.subscribed_text_color);
if (!isSubscribed) {
headerSubscribeButton.setText(R.string.subscribe_button_title);
animateBackgroundColor(headerSubscribeButton, backgroundDuration, subscribedBackground,
subscribeBackground);
animateTextColor(headerSubscribeButton, textDuration, subscribedText, subscribeText);
headerBinding.channelSubscribeButton.setText(R.string.subscribe_button_title);
animateBackgroundColor(headerBinding.channelSubscribeButton, backgroundDuration,
subscribedBackground, subscribeBackground);
animateTextColor(headerBinding.channelSubscribeButton, textDuration, subscribedText,
subscribeText);
} else {
headerSubscribeButton.setText(R.string.subscribed_button_title);
animateBackgroundColor(headerSubscribeButton, backgroundDuration, subscribeBackground,
subscribedBackground);
animateTextColor(headerSubscribeButton, textDuration, subscribeText, subscribedText);
headerBinding.channelSubscribeButton.setText(R.string.subscribed_button_title);
animateBackgroundColor(headerBinding.channelSubscribeButton, backgroundDuration,
subscribeBackground, subscribedBackground);
animateTextColor(headerBinding.channelSubscribeButton, textDuration, subscribeText,
subscribedText);
}
animateView(headerSubscribeButton, AnimationUtils.Type.LIGHT_SCALE_AND_ALPHA, true, 100);
animateView(headerBinding.channelSubscribeButton, AnimationUtils.Type.LIGHT_SCALE_AND_ALPHA,
true, 100);
}
/*//////////////////////////////////////////////////////////////////////////
@ -446,48 +433,49 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
public void showLoading() {
super.showLoading();
IMAGE_LOADER.cancelDisplayTask(headerChannelBanner);
IMAGE_LOADER.cancelDisplayTask(headerAvatarView);
IMAGE_LOADER.cancelDisplayTask(headerSubChannelAvatarView);
animateView(headerSubscribeButton, false, 100);
IMAGE_LOADER.cancelDisplayTask(headerBinding.channelBannerImage);
IMAGE_LOADER.cancelDisplayTask(headerBinding.channelAvatarView);
IMAGE_LOADER.cancelDisplayTask(headerBinding.subChannelAvatarView);
animateView(headerBinding.channelSubscribeButton, false, 100);
}
@Override
public void handleResult(@NonNull final ChannelInfo result) {
super.handleResult(result);
headerRootLayout.setVisibility(View.VISIBLE);
IMAGE_LOADER.displayImage(result.getBannerUrl(), headerChannelBanner,
headerBinding.getRoot().setVisibility(View.VISIBLE);
IMAGE_LOADER.displayImage(result.getBannerUrl(), headerBinding.channelBannerImage,
ImageDisplayConstants.DISPLAY_BANNER_OPTIONS);
IMAGE_LOADER.displayImage(result.getAvatarUrl(), headerAvatarView,
IMAGE_LOADER.displayImage(result.getAvatarUrl(), headerBinding.channelAvatarView,
ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS);
IMAGE_LOADER.displayImage(result.getParentChannelAvatarUrl(), headerSubChannelAvatarView,
IMAGE_LOADER.displayImage(result.getParentChannelAvatarUrl(),
headerBinding.subChannelAvatarView,
ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS);
headerSubscribersTextView.setVisibility(View.VISIBLE);
headerBinding.channelSubscriberView.setVisibility(View.VISIBLE);
if (result.getSubscriberCount() >= 0) {
headerSubscribersTextView.setText(Localization
headerBinding.channelSubscriberView.setText(Localization
.shortSubscriberCount(activity, result.getSubscriberCount()));
} else {
headerSubscribersTextView.setText(R.string.subscribers_count_not_available);
headerBinding.channelSubscriberView.setText(R.string.subscribers_count_not_available);
}
if (!TextUtils.isEmpty(currentInfo.getParentChannelName())) {
headerSubChannelTitleView.setText(String.format(
headerBinding.subChannelTitleView.setText(String.format(
getString(R.string.channel_created_by),
currentInfo.getParentChannelName())
);
headerSubChannelTitleView.setVisibility(View.VISIBLE);
headerSubChannelAvatarView.setVisibility(View.VISIBLE);
headerBinding.subChannelTitleView.setVisibility(View.VISIBLE);
headerBinding.subChannelAvatarView.setVisibility(View.VISIBLE);
} else {
headerSubChannelTitleView.setVisibility(View.GONE);
headerBinding.subChannelTitleView.setVisibility(View.GONE);
}
if (menuRssButton != null) {
menuRssButton.setVisible(!TextUtils.isEmpty(result.getFeedUrl()));
}
playlistCtrl.setVisibility(View.VISIBLE);
playlistControlBinding.getRoot().setVisibility(View.VISIBLE);
final List<Throwable> errors = new ArrayList<>(result.getErrors());
if (!errors.isEmpty()) {
@ -516,29 +504,32 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
updateSubscription(result);
monitorSubscription(result);
headerPlayAllButton.setOnClickListener(view -> NavigationHelper
.playOnMainPlayer(activity, getPlayQueue()));
headerPopupButton.setOnClickListener(view -> NavigationHelper
.playOnPopupPlayer(activity, getPlayQueue(), false));
headerBackgroundButton.setOnClickListener(view -> NavigationHelper
.playOnBackgroundPlayer(activity, getPlayQueue(), false));
playlistControlBinding.playlistCtrlPlayAllButton
.setOnClickListener(view -> NavigationHelper
.playOnMainPlayer(activity, getPlayQueue()));
playlistControlBinding.playlistCtrlPlayPopupButton
.setOnClickListener(view -> NavigationHelper
.playOnPopupPlayer(activity, getPlayQueue(), false));
playlistControlBinding.playlistCtrlPlayBgButton
.setOnClickListener(view -> NavigationHelper
.playOnBackgroundPlayer(activity, getPlayQueue(), false));
headerPopupButton.setOnLongClickListener(view -> {
playlistControlBinding.playlistCtrlPlayPopupButton.setOnLongClickListener(view -> {
NavigationHelper.enqueueOnPopupPlayer(activity, getPlayQueue(), true);
return true;
});
headerBackgroundButton.setOnLongClickListener(view -> {
playlistControlBinding.playlistCtrlPlayBgButton.setOnLongClickListener(view -> {
NavigationHelper.enqueueOnBackgroundPlayer(activity, getPlayQueue(), true);
return true;
});
}
private void showContentNotSupported() {
contentNotSupportedTextView.setVisibility(View.VISIBLE);
kaomojiTextView.setText("(︶︹︺)");
kaomojiTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 45f);
noVideosTextView.setVisibility(View.GONE);
channelBinding.errorContentNotSupported.setVisibility(View.VISIBLE);
channelBinding.channelKaomoji.setText("(︶︹︺)");
channelBinding.channelKaomoji.setTextSize(TypedValue.COMPLEX_UNIT_SP, 45f);
channelBinding.channelNoVideos.setVisibility(View.GONE);
}
private PlayQueue getPlayQueue() {
@ -596,7 +587,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
public void setTitle(final String title) {
super.setTitle(title);
if (!useAsFrontPage) {
headerTitleView.setText(title);
headerBinding.channelTitleView.setText(title);
}
}
}

View file

@ -11,18 +11,20 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.viewbinding.ViewBinding;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import org.schabi.newpipe.NewPipeDatabase;
import org.schabi.newpipe.R;
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
import org.schabi.newpipe.databinding.PlaylistControlBinding;
import org.schabi.newpipe.databinding.PlaylistHeaderBinding;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.NewPipe;
@ -53,7 +55,6 @@ import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import de.hdodenhof.circleimageview.CircleImageView;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.core.Single;
@ -74,17 +75,8 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
// Views
//////////////////////////////////////////////////////////////////////////*/
private View headerRootLayout;
private TextView headerTitleView;
private View headerUploaderLayout;
private TextView headerUploaderName;
private CircleImageView headerUploaderAvatar;
private TextView headerStreamCount;
private View playlistCtrl;
private View headerPlayAllButton;
private View headerPopupButton;
private View headerBackgroundButton;
private PlaylistHeaderBinding headerBinding;
private PlaylistControlBinding playlistControlBinding;
private MenuItem playlistBookmarkButton;
@ -119,22 +111,13 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
// Init
//////////////////////////////////////////////////////////////////////////*/
protected View getListHeader() {
headerRootLayout = activity.getLayoutInflater()
.inflate(R.layout.playlist_header, itemsList, false);
headerTitleView = headerRootLayout.findViewById(R.id.playlist_title_view);
headerUploaderLayout = headerRootLayout.findViewById(R.id.uploader_layout);
headerUploaderName = headerRootLayout.findViewById(R.id.uploader_name);
headerUploaderAvatar = headerRootLayout.findViewById(R.id.uploader_avatar_view);
headerStreamCount = headerRootLayout.findViewById(R.id.playlist_stream_count);
playlistCtrl = headerRootLayout.findViewById(R.id.playlist_control);
@Override
protected ViewBinding getListHeader() {
headerBinding = PlaylistHeaderBinding
.inflate(activity.getLayoutInflater(), itemsList, false);
playlistControlBinding = headerBinding.playlistControl;
headerPlayAllButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_all_button);
headerPopupButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_popup_button);
headerBackgroundButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_bg_button);
return headerRootLayout;
return headerBinding;
}
@Override
@ -203,6 +186,9 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
@Override
public void onDestroyView() {
headerBinding = null;
playlistControlBinding = null;
super.onDestroyView();
if (isBookmarkButtonReady != null) {
isBookmarkButtonReady.set(false);
@ -275,25 +261,25 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
@Override
public void showLoading() {
super.showLoading();
animateView(headerRootLayout, false, 200);
animateView(headerBinding.getRoot(), false, 200);
animateView(itemsList, false, 100);
IMAGE_LOADER.cancelDisplayTask(headerUploaderAvatar);
animateView(headerUploaderLayout, false, 200);
IMAGE_LOADER.cancelDisplayTask(headerBinding.uploaderAvatarView);
animateView(headerBinding.uploaderLayout, false, 200);
}
@Override
public void handleResult(@NonNull final PlaylistInfo result) {
super.handleResult(result);
animateView(headerRootLayout, true, 100);
animateView(headerUploaderLayout, true, 300);
headerUploaderLayout.setOnClickListener(null);
animateView(headerBinding.getRoot(), true, 100);
animateView(headerBinding.uploaderLayout, true, 300);
headerBinding.uploaderLayout.setOnClickListener(null);
// If we have an uploader put them into the UI
if (!TextUtils.isEmpty(result.getUploaderName())) {
headerUploaderName.setText(result.getUploaderName());
headerBinding.uploaderName.setText(result.getUploaderName());
if (!TextUtils.isEmpty(result.getUploaderUrl())) {
headerUploaderLayout.setOnClickListener(v -> {
headerBinding.uploaderLayout.setOnClickListener(v -> {
try {
NavigationHelper.openChannelFragment(getFM(), result.getServiceId(),
result.getUploaderUrl(), result.getUploaderName());
@ -303,28 +289,29 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
});
}
} else { // Otherwise say we have no uploader
headerUploaderName.setText(R.string.playlist_no_uploader);
headerBinding.uploaderName.setText(R.string.playlist_no_uploader);
}
playlistCtrl.setVisibility(View.VISIBLE);
playlistControlBinding.getRoot().setVisibility(View.VISIBLE);
final String avatarUrl = result.getUploaderAvatarUrl();
if (result.getServiceId() == ServiceList.YouTube.getServiceId()
&& (YoutubeParsingHelper.isYoutubeMixId(result.getId())
|| YoutubeParsingHelper.isYoutubeMusicMixId(result.getId()))) {
// this is an auto-generated playlist (e.g. Youtube mix), so a radio is shown
headerUploaderAvatar.setDisableCircularTransformation(true);
headerUploaderAvatar.setBorderColor(
headerBinding.uploaderAvatarView.setDisableCircularTransformation(true);
headerBinding.uploaderAvatarView.setBorderColor(
getResources().getColor(R.color.transparent_background_color));
headerUploaderAvatar.setImageDrawable(AppCompatResources.getDrawable(requireContext(),
resolveResourceIdFromAttr(requireContext(), R.attr.ic_radio)));
headerBinding.uploaderAvatarView.setImageDrawable(
AppCompatResources.getDrawable(requireContext(),
resolveResourceIdFromAttr(requireContext(), R.attr.ic_radio))
);
} else {
IMAGE_LOADER.displayImage(avatarUrl, headerUploaderAvatar,
IMAGE_LOADER.displayImage(avatarUrl, headerBinding.uploaderAvatarView,
ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS);
}
headerStreamCount.setText(Localization
headerBinding.playlistStreamCount.setText(Localization
.localizeStreamCount(getContext(), result.getStreamCount()));
if (!result.getErrors().isEmpty()) {
@ -338,19 +325,19 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
.observeOn(AndroidSchedulers.mainThread())
.subscribe(getPlaylistBookmarkSubscriber());
headerPlayAllButton.setOnClickListener(view ->
playlistControlBinding.playlistCtrlPlayAllButton.setOnClickListener(view ->
NavigationHelper.playOnMainPlayer(activity, getPlayQueue()));
headerPopupButton.setOnClickListener(view ->
playlistControlBinding.playlistCtrlPlayPopupButton.setOnClickListener(view ->
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(), false));
headerBackgroundButton.setOnClickListener(view ->
playlistControlBinding.playlistCtrlPlayBgButton.setOnClickListener(view ->
NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue(), false));
headerPopupButton.setOnLongClickListener(view -> {
playlistControlBinding.playlistCtrlPlayPopupButton.setOnLongClickListener(view -> {
NavigationHelper.enqueueOnPopupPlayer(activity, getPlayQueue(), true);
return true;
});
headerBackgroundButton.setOnLongClickListener(view -> {
playlistControlBinding.playlistCtrlPlayBgButton.setOnLongClickListener(view -> {
NavigationHelper.enqueueOnBackgroundPlayer(activity, getPlayQueue(), true);
return true;
});
@ -459,7 +446,7 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
@Override
public void setTitle(final String title) {
super.setTitle(title);
headerTitleView.setText(title);
headerBinding.playlistTitleView.setText(title);
}
private void onBookmarkClicked() {

View file

@ -37,6 +37,7 @@ import androidx.recyclerview.widget.RecyclerView;
import org.schabi.newpipe.R;
import org.schabi.newpipe.ReCaptchaActivity;
import org.schabi.newpipe.database.history.model.SearchHistoryEntry;
import org.schabi.newpipe.databinding.FragmentSearchBinding;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.MetaInfo;
@ -155,6 +156,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
// Views
//////////////////////////////////////////////////////////////////////////*/
private FragmentSearchBinding searchBinding;
private View searchToolbarContainer;
private EditText searchEditText;
private View searchClear;
@ -165,7 +168,6 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
private View suggestionsPanel;
private boolean suggestionsPanelVisible = false;
private RecyclerView suggestionsRecyclerView;
/*////////////////////////////////////////////////////////////////////////*/
@ -301,6 +303,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
Log.d(TAG, "onDestroyView() called");
}
unsetSearchListeners();
searchBinding = null;
super.onDestroyView();
}
@ -337,9 +341,9 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
@Override
protected void initViews(final View rootView, final Bundle savedInstanceState) {
super.initViews(rootView, savedInstanceState);
suggestionsPanel = rootView.findViewById(R.id.suggestions_panel);
suggestionsRecyclerView = rootView.findViewById(R.id.suggestions_list);
suggestionsRecyclerView.setAdapter(suggestionListAdapter);
searchBinding = FragmentSearchBinding.bind(rootView);
searchBinding.suggestionsList.setAdapter(suggestionListAdapter);
new ItemTouchHelper(new ItemTouchHelper.Callback() {
@Override
public int getMovementFlags(@NonNull final RecyclerView recyclerView,
@ -358,7 +362,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
public void onSwiped(@NonNull final RecyclerView.ViewHolder viewHolder, final int i) {
onSuggestionItemSwiped(viewHolder);
}
}).attachToRecyclerView(suggestionsRecyclerView);
}).attachToRecyclerView(searchBinding.suggestionsList);
searchToolbarContainer = activity.findViewById(R.id.toolbar_search_container);
searchEditText = searchToolbarContainer.findViewById(R.id.toolbar_search_edit_text);
@ -523,7 +527,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
return;
}
correctSuggestion.setVisibility(View.GONE);
searchBinding.correctSuggestion.setVisibility(View.GONE);
searchEditText.setText("");
suggestionListAdapter.setItems(new ArrayList<>());
@ -640,7 +644,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
Log.d(TAG, "showSuggestionsPanel() called");
}
suggestionsPanelVisible = true;
animateView(suggestionsPanel, AnimationUtils.Type.LIGHT_SLIDE_AND_ALPHA, true, 200);
animateView(searchBinding.suggestionsPanel, AnimationUtils.Type.LIGHT_SLIDE_AND_ALPHA,
true, 200);
}
private void hideSuggestionsPanel() {
@ -648,7 +653,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
Log.d(TAG, "hideSuggestionsPanel() called");
}
suggestionsPanelVisible = false;
animateView(suggestionsPanel, AnimationUtils.Type.LIGHT_SLIDE_AND_ALPHA, false, 200);
animateView(searchBinding.suggestionsPanel, AnimationUtils.Type.LIGHT_SLIDE_AND_ALPHA,
false, 200);
}
private void showKeyboardSearch() {
@ -936,8 +942,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
if (DEBUG) {
Log.d(TAG, "handleSuggestions() called with: suggestions = [" + suggestions + "]");
}
suggestionsRecyclerView.smoothScrollToPosition(0);
suggestionsRecyclerView.post(() -> suggestionListAdapter.setItems(suggestions));
searchBinding.suggestionsList.smoothScrollToPosition(0);
searchBinding.suggestionsList.post(() -> suggestionListAdapter.setItems(suggestions));
if (suggestionsPanelVisible && errorPanelRoot.getVisibility() == View.VISIBLE) {
hideLoading();
@ -1019,7 +1025,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
private void handleSearchSuggestion() {
if (TextUtils.isEmpty(searchSuggestion)) {
correctSuggestion.setVisibility(View.GONE);
searchBinding.correctSuggestion.setVisibility(View.GONE);
} else {
final String helperText = getString(isCorrectedSearch
? R.string.search_showing_result_for
@ -1028,22 +1034,23 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
final String highlightedSearchSuggestion =
"<b><i>" + Html.escapeHtml(searchSuggestion) + "</i></b>";
final String text = String.format(helperText, highlightedSearchSuggestion);
correctSuggestion.setText(HtmlCompat.fromHtml(text, HtmlCompat.FROM_HTML_MODE_LEGACY));
searchBinding.correctSuggestion.setText(HtmlCompat.fromHtml(text,
HtmlCompat.FROM_HTML_MODE_LEGACY));
correctSuggestion.setOnClickListener(v -> {
correctSuggestion.setVisibility(View.GONE);
searchBinding.correctSuggestion.setOnClickListener(v -> {
searchBinding.correctSuggestion.setVisibility(View.GONE);
search(searchSuggestion, contentFilter, sortFilter);
searchEditText.setText(searchSuggestion);
});
correctSuggestion.setOnLongClickListener(v -> {
searchBinding.correctSuggestion.setOnLongClickListener(v -> {
searchEditText.setText(searchSuggestion);
searchEditText.setSelection(searchSuggestion.length());
showKeyboardSearch();
return true;
});
correctSuggestion.setVisibility(View.VISIBLE);
searchBinding.correctSuggestion.setVisibility(View.VISIBLE);
}
}

View file

@ -8,13 +8,14 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Switch;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.PreferenceManager;
import androidx.viewbinding.ViewBinding;
import org.schabi.newpipe.R;
import org.schabi.newpipe.databinding.RelatedStreamsHeaderBinding;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.stream.StreamInfo;
@ -38,8 +39,7 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf
// Views
//////////////////////////////////////////////////////////////////////////*/
private View headerRootLayout;
private Switch autoplaySwitch;
private RelatedStreamsHeaderBinding headerBinding;
public static RelatedVideosFragment getInstance(final StreamInfo info) {
final RelatedVideosFragment instance = new RelatedVideosFragment();
@ -66,25 +66,29 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf
@Override
public void onDestroy() {
super.onDestroy();
if (disposables != null) {
disposables.clear();
}
disposables.clear();
}
protected View getListHeader() {
@Override
public void onDestroyView() {
headerBinding = null;
super.onDestroyView();
}
@Override
protected ViewBinding getListHeader() {
if (relatedStreamInfo != null && relatedStreamInfo.getRelatedItems() != null) {
headerRootLayout = activity.getLayoutInflater()
.inflate(R.layout.related_streams_header, itemsList, false);
autoplaySwitch = headerRootLayout.findViewById(R.id.autoplay_switch);
headerBinding = RelatedStreamsHeaderBinding
.inflate(activity.getLayoutInflater(), itemsList, false);
final SharedPreferences pref = PreferenceManager
.getDefaultSharedPreferences(requireContext());
final boolean autoplay = pref.getBoolean(getString(R.string.auto_queue_key), false);
autoplaySwitch.setChecked(autoplay);
autoplaySwitch.setOnCheckedChangeListener((compoundButton, b) ->
headerBinding.autoplaySwitch.setChecked(autoplay);
headerBinding.autoplaySwitch.setOnCheckedChangeListener((compoundButton, b) ->
PreferenceManager.getDefaultSharedPreferences(requireContext()).edit()
.putBoolean(getString(R.string.auto_queue_key), b).apply());
return headerRootLayout;
return headerBinding;
} else {
return null;
}
@ -107,8 +111,8 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf
@Override
public void showLoading() {
super.showLoading();
if (headerRootLayout != null) {
headerRootLayout.setVisibility(View.INVISIBLE);
if (headerBinding != null) {
headerBinding.getRoot().setVisibility(View.INVISIBLE);
}
}
@ -116,8 +120,8 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf
public void handleResult(@NonNull final RelatedStreamInfo result) {
super.handleResult(result);
if (headerRootLayout != null) {
headerRootLayout.setVisibility(View.VISIBLE);
if (headerBinding != null) {
headerBinding.getRoot().setVisibility(View.VISIBLE);
}
AnimationUtils.slideUp(getView(), 120, 96, 0.06f);
@ -126,9 +130,7 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf
NewPipe.getNameOfService(result.getServiceId()), result.getUrl(), 0);
}
if (disposables != null) {
disposables.clear();
}
disposables.clear();
}
@Override
@ -202,8 +204,8 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf
final SharedPreferences pref =
PreferenceManager.getDefaultSharedPreferences(requireContext());
final boolean autoplay = pref.getBoolean(getString(R.string.auto_queue_key), false);
if (autoplaySwitch != null) {
autoplaySwitch.setChecked(autoplay);
if (headerBinding != null) {
headerBinding.autoplaySwitch.setChecked(autoplay);
}
}