From 98be89a20ac833bf9ec7af55e8d71ea8c0477766 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Tue, 3 Nov 2020 09:47:27 +0530 Subject: [PATCH 01/11] Return ViewBinding instead of View in BaseLocalListFragment's getListHeader() and getListFooter() methods. --- .../newpipe/local/BaseLocalListFragment.java | 37 ++++---- .../history/StatisticsPlaylistFragment.java | 66 +++++++-------- .../local/playlist/LocalPlaylistFragment.java | 84 ++++++++----------- .../main/res/layout/local_playlist_header.xml | 5 +- .../res/layout/statistic_playlist_control.xml | 4 +- 5 files changed, 93 insertions(+), 103 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java b/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java index 8e88ceaed..38ecc1c63 100644 --- a/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java @@ -4,6 +4,8 @@ import android.content.SharedPreferences; import android.content.res.Configuration; import android.content.res.Resources; import android.os.Bundle; + +import androidx.annotation.Nullable; import androidx.preference.PreferenceManager; import android.util.Log; import android.view.Menu; @@ -15,8 +17,10 @@ import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import androidx.viewbinding.ViewBinding; import org.schabi.newpipe.R; +import org.schabi.newpipe.databinding.PignateFooterBinding; import org.schabi.newpipe.fragments.BaseStateFragment; import org.schabi.newpipe.fragments.list.ListViewContract; @@ -42,8 +46,8 @@ public abstract class BaseLocalListFragment extends BaseStateFragment //////////////////////////////////////////////////////////////////////////*/ private static final int LIST_MODE_UPDATE_FLAG = 0x32; - private View headerRootView; - private View footerRootView; + private ViewBinding headerRootBinding; + private ViewBinding footerRootBinding; protected LocalItemListAdapter itemListAdapter; protected RecyclerView itemsList; private int updateFlags = 0; @@ -86,12 +90,13 @@ public abstract class BaseLocalListFragment extends BaseStateFragment // Lifecycle - View //////////////////////////////////////////////////////////////////////////*/ - 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 getGridLayoutManager() { @@ -120,10 +125,12 @@ public abstract class BaseLocalListFragment extends BaseStateFragment itemsList.setLayoutManager(useGrid ? getGridLayoutManager() : getListLayoutManager()); itemListAdapter.setUseGridVariant(useGrid); - headerRootView = getListHeader(); - itemListAdapter.setHeader(headerRootView); - footerRootView = getListFooter(); - itemListAdapter.setFooter(footerRootView); + headerRootBinding = getListHeader(); + if (headerRootBinding != null) { + itemListAdapter.setHeader(headerRootBinding.getRoot()); + } + footerRootBinding = getListFooter(); + itemListAdapter.setFooter(footerRootBinding.getRoot()); itemsList.setAdapter(itemListAdapter); } @@ -180,8 +187,8 @@ public abstract class BaseLocalListFragment extends BaseStateFragment if (itemsList != null) { animateView(itemsList, false, 200); } - if (headerRootView != null) { - animateView(headerRootView, false, 200); + if (headerRootBinding != null) { + animateView(headerRootBinding.getRoot(), false, 200); } } @@ -191,8 +198,8 @@ public abstract class BaseLocalListFragment extends BaseStateFragment if (itemsList != null) { animateView(itemsList, true, 200); } - if (headerRootView != null) { - animateView(headerRootView, true, 200); + if (headerRootBinding != null) { + animateView(headerRootBinding.getRoot(), true, 200); } } @@ -204,8 +211,8 @@ public abstract class BaseLocalListFragment extends BaseStateFragment if (itemsList != null) { animateView(itemsList, false, 200); } - if (headerRootView != null) { - animateView(headerRootView, false, 200); + if (headerRootBinding != null) { + animateView(headerRootBinding.getRoot(), false, 200); } } diff --git a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java index 0d549ecf9..f9aa38054 100644 --- a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java @@ -10,13 +10,12 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; +import androidx.viewbinding.ViewBinding; import com.google.android.material.snackbar.Snackbar; @@ -26,6 +25,8 @@ import org.schabi.newpipe.R; import org.schabi.newpipe.database.LocalItem; import org.schabi.newpipe.database.stream.StreamStatisticsEntry; import org.schabi.newpipe.database.stream.model.StreamEntity; +import org.schabi.newpipe.databinding.PlaylistControlBinding; +import org.schabi.newpipe.databinding.StatisticPlaylistControlBinding; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.info_list.InfoItemDialog; @@ -60,13 +61,10 @@ public class StatisticsPlaylistFragment @State Parcelable itemsListState; private StatisticSortMode sortMode = StatisticSortMode.LAST_PLAYED; - private View headerPlayAllButton; - private View headerPopupButton; - private View headerBackgroundButton; - private View playlistCtrl; - private View sortButton; - private ImageView sortButtonIcon; - private TextView sortButtonText; + + private StatisticPlaylistControlBinding headerBinding; + private PlaylistControlBinding playlistControlBinding; + /* Used for independent events */ private Subscription databaseSubscription; private HistoryRecordManager recordManager; @@ -131,17 +129,12 @@ public class StatisticsPlaylistFragment } @Override - protected View getListHeader() { - final View headerRootLayout = activity.getLayoutInflater() - .inflate(R.layout.statistic_playlist_control, itemsList, false); - playlistCtrl = headerRootLayout.findViewById(R.id.playlist_control); - 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); - sortButton = headerRootLayout.findViewById(R.id.sortButton); - sortButtonIcon = headerRootLayout.findViewById(R.id.sortButtonIcon); - sortButtonText = headerRootLayout.findViewById(R.id.sortButtonText); - return headerRootLayout; + protected ViewBinding getListHeader() { + headerBinding = StatisticPlaylistControlBinding.inflate(activity.getLayoutInflater(), + itemsList, false); + playlistControlBinding = headerBinding.playlistControl; + + return headerBinding; } @Override @@ -245,14 +238,13 @@ public class StatisticsPlaylistFragment if (itemListAdapter != null) { itemListAdapter.unsetSelectedListener(); } - if (headerBackgroundButton != null) { - headerBackgroundButton.setOnClickListener(null); - } - if (headerPlayAllButton != null) { - headerPlayAllButton.setOnClickListener(null); - } - if (headerPopupButton != null) { - headerPopupButton.setOnClickListener(null); + if (playlistControlBinding != null) { + playlistControlBinding.playlistCtrlPlayBgButton.setOnClickListener(null); + playlistControlBinding.playlistCtrlPlayAllButton.setOnClickListener(null); + playlistControlBinding.playlistCtrlPlayPopupButton.setOnClickListener(null); + + headerBinding = null; + playlistControlBinding = null; } if (databaseSubscription != null) { @@ -311,7 +303,7 @@ public class StatisticsPlaylistFragment return; } - playlistCtrl.setVisibility(View.VISIBLE); + playlistControlBinding.getRoot().setVisibility(View.VISIBLE); itemListAdapter.clearStreamItemList(); @@ -326,13 +318,13 @@ public class StatisticsPlaylistFragment itemsListState = null; } - 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)); - sortButton.setOnClickListener(view -> toggleSortMode()); + headerBinding.sortButton.setOnClickListener(view -> toggleSortMode()); hideLoading(); } @@ -368,15 +360,15 @@ public class StatisticsPlaylistFragment if (sortMode == StatisticSortMode.LAST_PLAYED) { sortMode = StatisticSortMode.MOST_PLAYED; setTitle(getString(R.string.title_most_played)); - sortButtonIcon.setImageResource( + headerBinding.sortButtonIcon.setImageResource( ThemeHelper.resolveResourceIdFromAttr(requireContext(), R.attr.ic_history)); - sortButtonText.setText(R.string.title_last_played); + headerBinding.sortButtonText.setText(R.string.title_last_played); } else { sortMode = StatisticSortMode.LAST_PLAYED; setTitle(getString(R.string.title_last_played)); - sortButtonIcon.setImageResource( + headerBinding.sortButtonIcon.setImageResource( ThemeHelper.resolveResourceIdFromAttr(requireContext(), R.attr.ic_filter_list)); - sortButtonText.setText(R.string.title_most_played); + headerBinding.sortButtonText.setText(R.string.title_most_played); } startLoading(true); } diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index 17f7a4ff9..08b7101e6 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -14,7 +14,6 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; -import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; @@ -22,6 +21,7 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; +import androidx.viewbinding.ViewBinding; import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; @@ -32,6 +32,8 @@ import org.schabi.newpipe.database.history.model.StreamHistoryEntry; import org.schabi.newpipe.database.playlist.PlaylistStreamEntry; import org.schabi.newpipe.database.stream.model.StreamEntity; import org.schabi.newpipe.database.stream.model.StreamStateEntity; +import org.schabi.newpipe.databinding.LocalPlaylistHeaderBinding; +import org.schabi.newpipe.databinding.PlaylistControlBinding; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.info_list.InfoItemDialog; @@ -77,13 +79,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment createRenameDialog()); + headerBinding.playlistTitleView.setOnClickListener(view -> createRenameDialog()); itemTouchHelper = new ItemTouchHelper(getItemTouchCallback()); itemTouchHelper.attachToRecyclerView(itemsList); @@ -210,22 +200,18 @@ public class LocalPlaylistFragment extends BaseLocalListFragment + 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; }); @@ -806,8 +791,9 @@ public class LocalPlaylistFragment extends BaseLocalListFragment - + + diff --git a/app/src/main/res/layout/statistic_playlist_control.xml b/app/src/main/res/layout/statistic_playlist_control.xml index ef090807c..c8eff8fd3 100644 --- a/app/src/main/res/layout/statistic_playlist_control.xml +++ b/app/src/main/res/layout/statistic_playlist_control.xml @@ -38,6 +38,8 @@ tools:ignore="RtlHardcoded" /> - + From 979102a2d932cd17ce58d367244c6c906dcc81a8 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Tue, 3 Nov 2020 10:49:19 +0530 Subject: [PATCH 02/11] Return ViewBinding instead of View in BaseListFragment's getListHeader() and getListFooter() methods. --- .../fragments/list/BaseListFragment.java | 18 ++- .../list/channel/ChannelFragment.java | 148 +++++++++--------- .../list/playlist/PlaylistFragment.java | 89 +++++------ .../list/videos/RelatedVideosFragment.java | 46 +++--- app/src/main/res/layout/channel_header.xml | 5 +- app/src/main/res/layout/playlist_header.xml | 4 +- 6 files changed, 153 insertions(+), 157 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java index a40ff1bf3..02c7a4818 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java @@ -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 extends BaseStateFragment // 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 extends BaseStateFragment 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); } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java index 0342bb99c..b97ef9acc 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java @@ -14,8 +14,6 @@ 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; @@ -23,11 +21,14 @@ 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.PlaylistControlBinding; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.NewPipe; @@ -78,18 +79,10 @@ public class ChannelFragment extends BaseListInfoFragment //////////////////////////////////////////////////////////////////////////*/ 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 ChannelHeaderBinding headerBinding; + private PlaylistControlBinding playlistControlBinding; + private MenuItem menuRssButton; private TextView contentNotSupportedTextView; private TextView kaomojiTextView; @@ -140,45 +133,38 @@ public class ChannelFragment extends BaseListInfoFragment @Override public void onDestroy() { super.onDestroy(); - if (disposables != null) { - disposables.clear(); - } + disposables.clear(); if (subscribeButtonMonitor != null) { subscribeButtonMonitor.dispose(); } } + @Override + public void onDestroyView() { + 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 +227,7 @@ public class ChannelFragment extends BaseListInfoFragment private void monitorSubscription(final ChannelInfo info) { final Consumer 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 +337,15 @@ public class ChannelFragment extends BaseListInfoFragment 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 +356,8 @@ public class ChannelFragment extends BaseListInfoFragment + "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 +369,21 @@ public class ChannelFragment extends BaseListInfoFragment 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 +436,49 @@ public class ChannelFragment extends BaseListInfoFragment 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 errors = new ArrayList<>(result.getErrors()); if (!errors.isEmpty()) { @@ -516,19 +507,22 @@ public class ChannelFragment extends BaseListInfoFragment 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; }); @@ -596,7 +590,7 @@ public class ChannelFragment extends BaseListInfoFragment public void setTitle(final String title) { super.setTitle(title); if (!useAsFrontPage) { - headerTitleView.setText(title); + headerBinding.channelTitleView.setText(title); } } } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java index 8f7d6128b..6e723a686 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java @@ -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 { // 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 { // 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 { @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 { @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 { }); } } 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 { .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 { @Override public void setTitle(final String title) { super.setTitle(title); - headerTitleView.setText(title); + headerBinding.playlistTitleView.setText(title); } private void onBookmarkClicked() { diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/videos/RelatedVideosFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/videos/RelatedVideosFragment.java index 907615b45..7fb41f0e5 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/videos/RelatedVideosFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/videos/RelatedVideosFragment.java @@ -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 + 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 - + + diff --git a/app/src/main/res/layout/playlist_header.xml b/app/src/main/res/layout/playlist_header.xml index d27c86872..a5960472f 100644 --- a/app/src/main/res/layout/playlist_header.xml +++ b/app/src/main/res/layout/playlist_header.xml @@ -83,7 +83,9 @@ android:layout_height="wrap_content" android:layout_below="@id/playlist_meta"> - + From 910d22daa6dcccdb6b21213ab02da1eed1842047 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Tue, 3 Nov 2020 09:24:07 +0530 Subject: [PATCH 03/11] Use view binding in MainFragment. --- .../newpipe/fragments/MainFragment.java | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java index a77109f86..9487fa385 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java @@ -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 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())); From 7c581ec108e84fa4c15b720520a0004dd3ed88b7 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Tue, 3 Nov 2020 09:52:51 +0530 Subject: [PATCH 04/11] Use view binding in LicenseFragment. --- .../schabi/newpipe/about/LicenseFragment.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/about/LicenseFragment.java b/app/src/main/java/org/schabi/newpipe/about/LicenseFragment.java index 6e48a0e14..f5bf4df19 100644 --- a/app/src/main/java/org/schabi/newpipe/about/LicenseFragment.java +++ b/app/src/main/java/org/schabi/newpipe/about/LicenseFragment.java @@ -7,13 +7,14 @@ 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.fragment.app.Fragment; import org.schabi.newpipe.R; +import org.schabi.newpipe.databinding.FragmentLicensesBinding; +import org.schabi.newpipe.databinding.ItemSoftwareComponentBinding; import org.schabi.newpipe.util.ShareUtils; import java.io.Serializable; @@ -67,43 +68,42 @@ public class LicenseFragment extends Fragment { @Nullable @Override - public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container, + public View onCreateView(@NonNull final LayoutInflater inflater, + @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) { - final View rootView = inflater.inflate(R.layout.fragment_licenses, container, false); - final ViewGroup softwareComponentsView = rootView.findViewById(R.id.software_components); + final FragmentLicensesBinding binding = FragmentLicensesBinding + .inflate(inflater, container, false); - final View licenseLink = rootView.findViewById(R.id.app_read_license); - licenseLink.setOnClickListener(v -> { + binding.appReadLicense.setOnClickListener(v -> { activeLicense = StandardLicenses.GPL3; compositeDisposable.add(LicenseFragmentHelper.showLicense(getActivity(), StandardLicenses.GPL3)); }); for (final SoftwareComponent component : softwareComponents) { - final View componentView = inflater - .inflate(R.layout.item_software_component, container, false); - final TextView softwareName = componentView.findViewById(R.id.name); - final TextView copyright = componentView.findViewById(R.id.copyright); - softwareName.setText(component.getName()); - copyright.setText(getString(R.string.copyright, + final ItemSoftwareComponentBinding componentBinding = ItemSoftwareComponentBinding + .inflate(inflater, container, false); + componentBinding.name.setText(component.getName()); + componentBinding.copyright.setText(getString(R.string.copyright, component.getYears(), component.getCopyrightOwner(), component.getLicense().getAbbreviation())); - componentView.setTag(component); - componentView.setOnClickListener(v -> { + final View root = componentBinding.getRoot(); + root.setTag(component); + root.setOnClickListener(v -> { activeLicense = component.getLicense(); compositeDisposable.add(LicenseFragmentHelper.showLicense(getActivity(), component.getLicense())); }); - softwareComponentsView.addView(componentView); - registerForContextMenu(componentView); + binding.softwareComponents.addView(root); + registerForContextMenu(root); } if (activeLicense != null) { compositeDisposable.add(LicenseFragmentHelper.showLicense(getActivity(), activeLicense)); } - return rootView; + return binding.getRoot(); } @Override From 7682ebd245a55261e2c5737f305d35b2ab37d441 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Tue, 3 Nov 2020 10:00:12 +0530 Subject: [PATCH 05/11] Use view binding in DownloadDialog. --- .../newpipe/download/DownloadDialog.java | 102 +++++++++--------- 1 file changed, 48 insertions(+), 54 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java index e80a0ab21..68bcf3cc1 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java @@ -16,12 +16,8 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; -import android.widget.EditText; -import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.SeekBar; -import android.widget.Spinner; -import android.widget.TextView; import android.widget.Toast; import androidx.annotation.IdRes; @@ -40,6 +36,7 @@ import com.nononsenseapps.filepicker.Utils; import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; import org.schabi.newpipe.RouterActivity; +import org.schabi.newpipe.databinding.DownloadDialogBinding; import org.schabi.newpipe.extractor.MediaFormat; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.localization.Localization; @@ -116,11 +113,7 @@ public class DownloadDialog extends DialogFragment private final CompositeDisposable disposables = new CompositeDisposable(); - private EditText nameEditText; - private Spinner streamsSpinner; - private RadioGroup radioStreamsGroup; - private TextView threadsCountTextView; - private SeekBar threadsSeekBar; + private DownloadDialogBinding dialogBinding; private SharedPreferences prefs; @@ -277,38 +270,35 @@ public class DownloadDialog extends DialogFragment @Override public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - nameEditText = view.findViewById(R.id.file_name); - nameEditText.setText(FilenameUtils.createFilename(getContext(), currentInfo.getName())); + dialogBinding = DownloadDialogBinding.bind(view); + + dialogBinding.fileName.setText(FilenameUtils.createFilename(getContext(), + currentInfo.getName())); selectedAudioIndex = ListHelper .getDefaultAudioFormat(getContext(), currentInfo.getAudioStreams()); selectedSubtitleIndex = getSubtitleIndexBy(subtitleStreamsAdapter.getAll()); - streamsSpinner = view.findViewById(R.id.quality_spinner); - streamsSpinner.setOnItemSelectedListener(this); + dialogBinding.qualitySpinner.setOnItemSelectedListener(this); - threadsCountTextView = view.findViewById(R.id.threads_count); - threadsSeekBar = view.findViewById(R.id.threads); + dialogBinding.videoAudioGroup.setOnCheckedChangeListener(this); - radioStreamsGroup = view.findViewById(R.id.video_audio_group); - radioStreamsGroup.setOnCheckedChangeListener(this); - - initToolbar(view.findViewById(R.id.toolbar)); + initToolbar(dialogBinding.toolbarLayout.toolbar); setupDownloadOptions(); prefs = PreferenceManager.getDefaultSharedPreferences(requireContext()); final int threads = prefs.getInt(getString(R.string.default_download_threads), 3); - threadsCountTextView.setText(String.valueOf(threads)); - threadsSeekBar.setProgress(threads - 1); - threadsSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + dialogBinding.threadsCount.setText(String.valueOf(threads)); + dialogBinding.threads.setProgress(threads - 1); + dialogBinding.threads.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(final SeekBar seekbar, final int progress, final boolean fromUser) { final int newProgress = progress + 1; prefs.edit().putInt(getString(R.string.default_download_threads), newProgress) .apply(); - threadsCountTextView.setText(String.valueOf(newProgress)); + dialogBinding.threadsCount.setText(String.valueOf(newProgress)); } @Override @@ -326,19 +316,19 @@ public class DownloadDialog extends DialogFragment disposables.add(StreamSizeWrapper.fetchSizeForWrapper(wrappedVideoStreams) .subscribe(result -> { - if (radioStreamsGroup.getCheckedRadioButtonId() == R.id.video_button) { + if (dialogBinding.videoAudioGroup.getCheckedRadioButtonId() == R.id.video_button) { setupVideoSpinner(); } })); disposables.add(StreamSizeWrapper.fetchSizeForWrapper(wrappedAudioStreams) .subscribe(result -> { - if (radioStreamsGroup.getCheckedRadioButtonId() == R.id.audio_button) { + if (dialogBinding.videoAudioGroup.getCheckedRadioButtonId() == R.id.audio_button) { setupAudioSpinner(); } })); disposables.add(StreamSizeWrapper.fetchSizeForWrapper(wrappedSubtitleStreams) .subscribe(result -> { - if (radioStreamsGroup.getCheckedRadioButtonId() == R.id.subtitle_button) { + if (dialogBinding.videoAudioGroup.getCheckedRadioButtonId() == R.id.subtitle_button) { setupSubtitleSpinner(); } })); @@ -350,6 +340,12 @@ public class DownloadDialog extends DialogFragment disposables.clear(); } + @Override + public void onDestroyView() { + dialogBinding = null; + super.onDestroyView(); + } + /*////////////////////////////////////////////////////////////////////////// // Radio group Video&Audio options - Listener //////////////////////////////////////////////////////////////////////////*/ @@ -429,8 +425,8 @@ public class DownloadDialog extends DialogFragment return; } - streamsSpinner.setAdapter(audioStreamsAdapter); - streamsSpinner.setSelection(selectedAudioIndex); + dialogBinding.qualitySpinner.setAdapter(audioStreamsAdapter); + dialogBinding.qualitySpinner.setSelection(selectedAudioIndex); setRadioButtonsState(true); } @@ -439,8 +435,8 @@ public class DownloadDialog extends DialogFragment return; } - streamsSpinner.setAdapter(videoStreamsAdapter); - streamsSpinner.setSelection(selectedVideoIndex); + dialogBinding.qualitySpinner.setAdapter(videoStreamsAdapter); + dialogBinding.qualitySpinner.setSelection(selectedVideoIndex); setRadioButtonsState(true); } @@ -449,8 +445,8 @@ public class DownloadDialog extends DialogFragment return; } - streamsSpinner.setAdapter(subtitleStreamsAdapter); - streamsSpinner.setSelection(selectedSubtitleIndex); + dialogBinding.qualitySpinner.setAdapter(subtitleStreamsAdapter); + dialogBinding.qualitySpinner.setSelection(selectedSubtitleIndex); setRadioButtonsState(true); } @@ -475,7 +471,7 @@ public class DownloadDialog extends DialogFragment break; } - threadsSeekBar.setEnabled(flag); + dialogBinding.threads.setEnabled(flag); } @Override @@ -486,7 +482,7 @@ public class DownloadDialog extends DialogFragment + "parent = [" + parent + "], view = [" + view + "], " + "position = [" + position + "], id = [" + id + "]"); } - switch (radioStreamsGroup.getCheckedRadioButtonId()) { + switch (dialogBinding.videoAudioGroup.getCheckedRadioButtonId()) { case R.id.audio_button: selectedAudioIndex = position; break; @@ -506,16 +502,14 @@ public class DownloadDialog extends DialogFragment protected void setupDownloadOptions() { setRadioButtonsState(false); - final RadioButton audioButton = radioStreamsGroup.findViewById(R.id.audio_button); - final RadioButton videoButton = radioStreamsGroup.findViewById(R.id.video_button); - final RadioButton subtitleButton = radioStreamsGroup.findViewById(R.id.subtitle_button); final boolean isVideoStreamsAvailable = videoStreamsAdapter.getCount() > 0; final boolean isAudioStreamsAvailable = audioStreamsAdapter.getCount() > 0; final boolean isSubtitleStreamsAvailable = subtitleStreamsAdapter.getCount() > 0; - audioButton.setVisibility(isAudioStreamsAvailable ? View.VISIBLE : View.GONE); - videoButton.setVisibility(isVideoStreamsAvailable ? View.VISIBLE : View.GONE); - subtitleButton.setVisibility(isSubtitleStreamsAvailable ? View.VISIBLE : View.GONE); + dialogBinding.audioButton.setVisibility(isAudioStreamsAvailable ? View.VISIBLE : View.GONE); + dialogBinding.videoButton.setVisibility(isVideoStreamsAvailable ? View.VISIBLE : View.GONE); + dialogBinding.subtitleButton.setVisibility(isSubtitleStreamsAvailable + ? View.VISIBLE : View.GONE); prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); final String defaultMedia = prefs.getString(getString(R.string.last_used_download_type), @@ -523,24 +517,24 @@ public class DownloadDialog extends DialogFragment if (isVideoStreamsAvailable && (defaultMedia.equals(getString(R.string.last_download_type_video_key)))) { - videoButton.setChecked(true); + dialogBinding.videoButton.setChecked(true); setupVideoSpinner(); } else if (isAudioStreamsAvailable && (defaultMedia.equals(getString(R.string.last_download_type_audio_key)))) { - audioButton.setChecked(true); + dialogBinding.audioButton.setChecked(true); setupAudioSpinner(); } else if (isSubtitleStreamsAvailable && (defaultMedia.equals(getString(R.string.last_download_type_subtitle_key)))) { - subtitleButton.setChecked(true); + dialogBinding.subtitleButton.setChecked(true); setupSubtitleSpinner(); } else if (isVideoStreamsAvailable) { - videoButton.setChecked(true); + dialogBinding.videoButton.setChecked(true); setupVideoSpinner(); } else if (isAudioStreamsAvailable) { - audioButton.setChecked(true); + dialogBinding.audioButton.setChecked(true); setupAudioSpinner(); } else if (isSubtitleStreamsAvailable) { - subtitleButton.setChecked(true); + dialogBinding.subtitleButton.setChecked(true); setupSubtitleSpinner(); } else { Toast.makeText(getContext(), R.string.no_streams_available_download, @@ -550,9 +544,9 @@ public class DownloadDialog extends DialogFragment } private void setRadioButtonsState(final boolean enabled) { - radioStreamsGroup.findViewById(R.id.audio_button).setEnabled(enabled); - radioStreamsGroup.findViewById(R.id.video_button).setEnabled(enabled); - radioStreamsGroup.findViewById(R.id.subtitle_button).setEnabled(enabled); + dialogBinding.audioButton.setEnabled(enabled); + dialogBinding.videoButton.setEnabled(enabled); + dialogBinding.subtitleButton.setEnabled(enabled); } private int getSubtitleIndexBy(final List streams) { @@ -582,7 +576,7 @@ public class DownloadDialog extends DialogFragment } private String getNameEditText() { - final String str = nameEditText.getText().toString().trim(); + final String str = dialogBinding.fileName.getText().toString().trim(); return FilenameUtils.createFilename(context, str.isEmpty() ? currentInfo.getName() : str); } @@ -619,7 +613,7 @@ public class DownloadDialog extends DialogFragment String filename = getNameEditText().concat("."); - switch (radioStreamsGroup.getCheckedRadioButtonId()) { + switch (dialogBinding.videoAudioGroup.getCheckedRadioButtonId()) { case R.id.audio_button: selectedMediaType = getString(R.string.last_download_type_audio_key); mainStorage = mainStorageAudio; @@ -669,7 +663,7 @@ public class DownloadDialog extends DialogFragment filename, mime); } else { File initialSavePath; - if (radioStreamsGroup.getCheckedRadioButtonId() == R.id.audio_button) { + if (dialogBinding.videoAudioGroup.getCheckedRadioButtonId() == R.id.audio_button) { initialSavePath = NewPipeSettings.getDir(Environment.DIRECTORY_MUSIC); } else { initialSavePath = NewPipeSettings.getDir(Environment.DIRECTORY_MOVIES); @@ -862,7 +856,7 @@ public class DownloadDialog extends DialogFragment final Stream selectedStream; Stream secondaryStream = null; final char kind; - int threads = threadsSeekBar.getProgress() + 1; + int threads = dialogBinding.threads.getProgress() + 1; final String[] urls; final MissionRecoveryInfo[] recoveryInfo; String psName = null; @@ -870,7 +864,7 @@ public class DownloadDialog extends DialogFragment long nearLength = 0; // more download logic: select muxer, subtitle converter, etc. - switch (radioStreamsGroup.getCheckedRadioButtonId()) { + switch (dialogBinding.videoAudioGroup.getCheckedRadioButtonId()) { case R.id.audio_button: kind = 'a'; selectedStream = audioStreamsAdapter.getItem(selectedAudioIndex); From 6039484a02bda6eeef9633c46fd5edfc4eb6311d Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Tue, 3 Nov 2020 10:56:29 +0530 Subject: [PATCH 06/11] Use view binding in ChannelFragment. --- .../list/channel/ChannelFragment.java | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java index b97ef9acc..003893517 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java @@ -14,7 +14,6 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.Button; -import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -28,6 +27,7 @@ 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; @@ -80,13 +80,11 @@ public class ChannelFragment extends BaseListInfoFragment private SubscriptionManager subscriptionManager; + 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) { @@ -125,9 +123,7 @@ public class ChannelFragment extends BaseListInfoFragment @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 @@ -141,6 +137,7 @@ public class ChannelFragment extends BaseListInfoFragment @Override public void onDestroyView() { + channelBinding = null; headerBinding = null; playlistControlBinding = null; super.onDestroyView(); @@ -529,10 +526,10 @@ public class ChannelFragment extends BaseListInfoFragment } 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() { From 97672f06de29fb5f5def106a03fcc5d9c8ce938d Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Tue, 3 Nov 2020 13:28:21 +0530 Subject: [PATCH 07/11] Use view binding in SearchFragment. --- .../fragments/list/search/SearchFragment.java | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java index 3b48d9c84..0aaf87ea6 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java @@ -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()); @@ -640,7 +644,8 @@ public class SearchFragment extends BaseListFragment 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"; 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); } } From f80e1bd214ca7db29d58229a2428dc8b82533e08 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Tue, 3 Nov 2020 13:51:37 +0530 Subject: [PATCH 08/11] Use view binding in FeedFragment. --- .../schabi/newpipe/local/feed/FeedFragment.kt | 109 ++++++++++-------- 1 file changed, 58 insertions(+), 51 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt index dbe91ec55..f767f8f22 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt @@ -37,18 +37,10 @@ import androidx.lifecycle.ViewModelProvider import androidx.preference.PreferenceManager import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import icepick.State -import kotlinx.android.synthetic.main.error_retry.error_button_retry -import kotlinx.android.synthetic.main.error_retry.error_message_view -import kotlinx.android.synthetic.main.fragment_feed.empty_state_view -import kotlinx.android.synthetic.main.fragment_feed.error_panel -import kotlinx.android.synthetic.main.fragment_feed.items_list -import kotlinx.android.synthetic.main.fragment_feed.loading_progress_bar -import kotlinx.android.synthetic.main.fragment_feed.loading_progress_text -import kotlinx.android.synthetic.main.fragment_feed.refresh_root_view -import kotlinx.android.synthetic.main.fragment_feed.refresh_subtitle_text -import kotlinx.android.synthetic.main.fragment_feed.refresh_text import org.schabi.newpipe.R import org.schabi.newpipe.database.feed.model.FeedGroupEntity +import org.schabi.newpipe.databinding.ErrorRetryBinding +import org.schabi.newpipe.databinding.FragmentFeedBinding import org.schabi.newpipe.fragments.list.BaseListFragment import org.schabi.newpipe.local.feed.service.FeedLoadService import org.schabi.newpipe.report.UserAction @@ -57,6 +49,12 @@ import org.schabi.newpipe.util.Localization import java.util.Calendar class FeedFragment : BaseListFragment() { + private var _feedBinding: FragmentFeedBinding? = null + private val feedBinding get() = _feedBinding!! + + private var _errorBinding: ErrorRetryBinding? = null + private val errorBinding get() = _errorBinding!! + private lateinit var viewModel: FeedViewModel private lateinit var swipeRefreshLayout: SwipeRefreshLayout @State @@ -86,15 +84,17 @@ class FeedFragment : BaseListFragment() { override fun onViewCreated(rootView: View, savedInstanceState: Bundle?) { super.onViewCreated(rootView, savedInstanceState) - swipeRefreshLayout = requireView().findViewById(R.id.swiperefresh) - swipeRefreshLayout.setOnRefreshListener { reloadContent() } + _feedBinding = FragmentFeedBinding.bind(rootView) + _errorBinding = feedBinding.errorPanel + + feedBinding.swiperefresh.setOnRefreshListener { reloadContent() } viewModel = ViewModelProvider(this, FeedViewModel.Factory(requireContext(), groupId)).get(FeedViewModel::class.java) viewModel.stateLiveData.observe(viewLifecycleOwner, Observer { it?.let(::handleResult) }) } override fun onPause() { super.onPause() - listState = items_list?.layoutManager?.onSaveInstanceState() + listState = _feedBinding?.itemsList?.layoutManager?.onSaveInstanceState() } override fun onResume() { @@ -112,7 +112,8 @@ class FeedFragment : BaseListFragment() { override fun initListeners() { super.initListeners() - refresh_root_view.setOnClickListener { + // Using the non-null property may result in a NullPointerException + _feedBinding?.refreshRootView?.setOnClickListener { triggerUpdate() } } @@ -169,55 +170,60 @@ class FeedFragment : BaseListFragment() { activity?.supportActionBar?.subtitle = null } + override fun onDestroyView() { + _feedBinding = null + super.onDestroyView() + } + // ///////////////////////////////////////////////////////////////////////// // Handling // ///////////////////////////////////////////////////////////////////////// override fun showLoading() { - animateView(refresh_root_view, false, 0) - animateView(items_list, false, 0) + animateView(feedBinding.refreshRootView, false, 0) + animateView(feedBinding.itemsList, false, 0) - animateView(loading_progress_bar, true, 200) - animateView(loading_progress_text, true, 200) + animateView(feedBinding.loadingProgressBar, true, 200) + animateView(feedBinding.loadingProgressText, true, 200) - empty_state_view?.let { animateView(it, false, 0) } - animateView(error_panel, false, 0) + animateView(feedBinding.emptyStateView.root, false, 0) + animateView(errorBinding.root, false, 0) } override fun hideLoading() { - animateView(refresh_root_view, true, 200) - animateView(items_list, true, 300) + animateView(feedBinding.refreshRootView, true, 200) + animateView(feedBinding.itemsList, true, 300) - animateView(loading_progress_bar, false, 0) - animateView(loading_progress_text, false, 0) + animateView(feedBinding.loadingProgressBar, false, 0) + animateView(feedBinding.loadingProgressText, false, 0) - empty_state_view?.let { animateView(it, false, 0) } - animateView(error_panel, false, 0) - swipeRefreshLayout.isRefreshing = false + animateView(feedBinding.emptyStateView.root, false, 0) + animateView(errorBinding.root, false, 0) + feedBinding.swiperefresh.isRefreshing = false } override fun showEmptyState() { - animateView(refresh_root_view, true, 200) - animateView(items_list, false, 0) + animateView(feedBinding.refreshRootView, true, 200) + animateView(feedBinding.itemsList, false, 0) - animateView(loading_progress_bar, false, 0) - animateView(loading_progress_text, false, 0) + animateView(feedBinding.loadingProgressBar, false, 0) + animateView(feedBinding.loadingProgressText, false, 0) - empty_state_view?.let { animateView(it, true, 800) } - animateView(error_panel, false, 0) + animateView(feedBinding.emptyStateView.root, true, 800) + animateView(errorBinding.root, false, 0) } override fun showError(message: String, showRetryButton: Boolean) { infoListAdapter.clearStreamItemList() - animateView(refresh_root_view, false, 120) - animateView(items_list, false, 120) + animateView(feedBinding.refreshRootView, false, 120) + animateView(feedBinding.itemsList, false, 120) - animateView(loading_progress_bar, false, 120) - animateView(loading_progress_text, false, 120) + animateView(feedBinding.loadingProgressBar, false, 120) + animateView(feedBinding.loadingProgressText, false, 120) - error_message_view.text = message - animateView(error_button_retry, showRetryButton, if (showRetryButton) 600 else 0) - animateView(error_panel, true, 300) + errorBinding.errorMessageView.text = message + animateView(errorBinding.errorButtonRetry, showRetryButton, if (showRetryButton) 600 else 0) + animateView(errorBinding.root, true, 300) } override fun handleResult(result: FeedState) { @@ -237,33 +243,34 @@ class FeedFragment : BaseListFragment() { progressState.maxProgress == -1 if (!isIndeterminate) { - loading_progress_text.text = "${progressState.currentProgress}/${progressState.maxProgress}" + feedBinding.loadingProgressText.text = "${progressState.currentProgress}/${progressState.maxProgress}" } else if (progressState.progressMessage > 0) { - loading_progress_text?.setText(progressState.progressMessage) + _feedBinding?.loadingProgressText?.setText(progressState.progressMessage) } else { - loading_progress_text?.text = "∞/∞" + _feedBinding?.loadingProgressText?.text = "∞/∞" } - loading_progress_bar.isIndeterminate = isIndeterminate || - (progressState.maxProgress > 0 && progressState.currentProgress == 0) - loading_progress_bar.progress = progressState.currentProgress + feedBinding.loadingProgressBar.isIndeterminate = isIndeterminate || + (progressState.maxProgress > 0 && progressState.currentProgress == 0) + feedBinding.loadingProgressBar.progress = progressState.currentProgress - loading_progress_bar.max = progressState.maxProgress + feedBinding.loadingProgressBar.max = progressState.maxProgress } private fun handleLoadedState(loadedState: FeedState.LoadedState) { infoListAdapter.setInfoItemList(loadedState.items) listState?.run { - items_list.layoutManager?.onRestoreInstanceState(listState) + feedBinding.itemsList.layoutManager?.onRestoreInstanceState(listState) listState = null } oldestSubscriptionUpdate = loadedState.oldestUpdate val loadedCount = loadedState.notLoadedCount > 0 - refresh_subtitle_text.isVisible = loadedCount + feedBinding.refreshSubtitleText.isVisible = loadedCount if (loadedCount) { - refresh_subtitle_text.text = getString(R.string.feed_subscription_not_loaded_count, loadedState.notLoadedCount) + feedBinding.refreshSubtitleText.text = getString(R.string.feed_subscription_not_loaded_count, + loadedState.notLoadedCount) } if (loadedState.itemsErrors.isNotEmpty()) { @@ -300,7 +307,7 @@ class FeedFragment : BaseListFragment() { else -> "—" } - refresh_text?.text = getString(R.string.feed_oldest_subscription_update, oldestSubscriptionUpdateText) + feedBinding.refreshText.text = getString(R.string.feed_oldest_subscription_update, oldestSubscriptionUpdateText) } // ///////////////////////////////////////////////////////////////////////// From 83f33a7d1b45b4378de197f490542628a4413274 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Tue, 3 Nov 2020 14:01:36 +0530 Subject: [PATCH 09/11] Use view binding in SubscriptionFragment. --- .../subscription/SubscriptionFragment.kt | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index 64286dab3..c745ae39e 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -17,6 +17,7 @@ import android.view.MenuInflater import android.view.View import android.view.ViewGroup import android.widget.Toast +import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.preference.PreferenceManager @@ -29,11 +30,10 @@ import com.xwray.groupie.Section import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder import icepick.State import io.reactivex.rxjava3.disposables.CompositeDisposable -import kotlinx.android.synthetic.main.dialog_title.view.itemAdditionalDetails -import kotlinx.android.synthetic.main.dialog_title.view.itemTitleView -import kotlinx.android.synthetic.main.fragment_subscription.items_list import org.schabi.newpipe.R import org.schabi.newpipe.database.feed.model.FeedGroupEntity +import org.schabi.newpipe.databinding.DialogTitleBinding +import org.schabi.newpipe.databinding.FragmentSubscriptionBinding import org.schabi.newpipe.extractor.channel.ChannelInfoItem import org.schabi.newpipe.fragments.BaseStateFragment import org.schabi.newpipe.local.subscription.SubscriptionViewModel.SubscriptionState @@ -70,6 +70,9 @@ import kotlin.math.floor import kotlin.math.max class SubscriptionFragment : BaseStateFragment() { + private var _binding: FragmentSubscriptionBinding? = null + private val binding get() = _binding!! + private lateinit var viewModel: SubscriptionViewModel private lateinit var subscriptionManager: SubscriptionManager private val disposables: CompositeDisposable = CompositeDisposable() @@ -129,7 +132,7 @@ class SubscriptionFragment : BaseStateFragment() { override fun onPause() { super.onPause() - itemsListState = items_list.layoutManager?.onSaveInstanceState() + itemsListState = binding.itemsList.layoutManager?.onSaveInstanceState() feedGroupsListState = feedGroupsCarousel?.onSaveInstanceState() importExportItemExpandedState = importExportItem.isExpanded @@ -169,7 +172,7 @@ class SubscriptionFragment : BaseStateFragment() { filters.addAction(IMPORT_COMPLETE_ACTION) subscriptionBroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { - items_list?.post { + _binding?.itemsList?.post { importExportItem.isExpanded = false importExportItem.notifyChanged(FeedImportExportItem.REFRESH_EXPANDED_STATUS) } @@ -275,17 +278,18 @@ class SubscriptionFragment : BaseStateFragment() { override fun initViews(rootView: View, savedInstanceState: Bundle?) { super.initViews(rootView, savedInstanceState) + _binding = FragmentSubscriptionBinding.bind(rootView) val shouldUseGridLayout = shouldUseGridLayout() groupAdapter.spanCount = if (shouldUseGridLayout) getGridSpanCount() else 1 - items_list.layoutManager = GridLayoutManager(requireContext(), groupAdapter.spanCount).apply { + binding.itemsList.layoutManager = GridLayoutManager(requireContext(), groupAdapter.spanCount).apply { spanSizeLookup = groupAdapter.spanSizeLookup } - items_list.adapter = groupAdapter + binding.itemsList.adapter = groupAdapter viewModel = ViewModelProvider(this).get(SubscriptionViewModel::class.java) - viewModel.stateLiveData.observe(viewLifecycleOwner, androidx.lifecycle.Observer { it?.let(this::handleResult) }) - viewModel.feedGroupsLiveData.observe(viewLifecycleOwner, androidx.lifecycle.Observer { it?.let(this::handleFeedGroups) }) + viewModel.stateLiveData.observe(viewLifecycleOwner, Observer { it?.let(this::handleResult) }) + viewModel.feedGroupsLiveData.observe(viewLifecycleOwner, Observer { it?.let(this::handleFeedGroups) }) } private fun showLongTapDialog(selectedItem: ChannelInfoItem) { @@ -301,16 +305,16 @@ class SubscriptionFragment : BaseStateFragment() { } } - val bannerView = View.inflate(requireContext(), R.layout.dialog_title, null) - bannerView.isSelected = true - bannerView.itemTitleView.text = selectedItem.name - bannerView.itemAdditionalDetails.visibility = View.GONE + val dialogTitleBinding = DialogTitleBinding.inflate(LayoutInflater.from(requireContext())) + dialogTitleBinding.root.isSelected = true + dialogTitleBinding.itemTitleView.text = selectedItem.name + dialogTitleBinding.itemAdditionalDetails.visibility = View.GONE AlertDialog.Builder(requireContext()) - .setCustomTitle(bannerView) - .setItems(commands, actions) - .create() - .show() + .setCustomTitle(dialogTitleBinding.root) + .setItems(commands, actions) + .create() + .show() } private fun deleteChannel(selectedItem: ChannelInfoItem) { @@ -368,14 +372,14 @@ class SubscriptionFragment : BaseStateFragment() { subscriptionsSection.setHideWhenEmpty(false) if (result.subscriptions.isEmpty() && importExportItemExpandedState == null) { - items_list.post { + binding.itemsList.post { importExportItem.isExpanded = true importExportItem.notifyChanged(FeedImportExportItem.REFRESH_EXPANDED_STATUS) } } if (itemsListState != null) { - items_list.layoutManager?.onRestoreInstanceState(itemsListState) + binding.itemsList.layoutManager?.onRestoreInstanceState(itemsListState) itemsListState = null } } @@ -394,7 +398,7 @@ class SubscriptionFragment : BaseStateFragment() { } feedGroupsSortMenuItem.showMenuItem = groups.size > 1 - items_list.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) } + binding.itemsList.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) } } // ///////////////////////////////////////////////////////////////////////// @@ -403,12 +407,12 @@ class SubscriptionFragment : BaseStateFragment() { override fun showLoading() { super.showLoading() - animateView(items_list, false, 100) + animateView(binding.itemsList, false, 100) } override fun hideLoading() { super.hideLoading() - animateView(items_list, true, 200) + animateView(binding.itemsList, true, 200) } // ///////////////////////////////////////////////////////////////////////// From 5994cd8ea24c1216a771a99258bafc7ffd846675 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Tue, 3 Nov 2020 14:15:43 +0530 Subject: [PATCH 10/11] Use view binding in FeedGroupDialog. --- .../subscription/dialog/FeedGroupDialog.kt | 164 +++++++++--------- 1 file changed, 85 insertions(+), 79 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt index 1d5650a99..8260f0fb9 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt @@ -24,10 +24,10 @@ import com.xwray.groupie.Section import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder import icepick.Icepick import icepick.State -import kotlinx.android.synthetic.main.dialog_feed_group_create.* -import kotlinx.android.synthetic.main.toolbar_search_layout.* import org.schabi.newpipe.R import org.schabi.newpipe.database.feed.model.FeedGroupEntity +import org.schabi.newpipe.databinding.DialogFeedGroupCreateBinding +import org.schabi.newpipe.databinding.ToolbarSearchLayoutBinding import org.schabi.newpipe.fragments.BackPressable import org.schabi.newpipe.local.subscription.FeedGroupIcon import org.schabi.newpipe.local.subscription.dialog.FeedGroupDialog.ScreenState.DeleteScreen @@ -45,6 +45,12 @@ import java.io.Serializable import kotlin.collections.contains class FeedGroupDialog : DialogFragment(), BackPressable { + private var _feedGroupCreateBinding: DialogFeedGroupCreateBinding? = null + private val feedGroupCreateBinding get() = _feedGroupCreateBinding!! + + private var _searchLayoutBinding: ToolbarSearchLayoutBinding? = null + private val searchLayoutBinding get() = _searchLayoutBinding!! + private lateinit var viewModel: FeedGroupDialogViewModel private var groupId: Long = NO_GROUP_SELECTED private var groupIcon: FeedGroupIcon? = null @@ -107,14 +113,16 @@ class FeedGroupDialog : DialogFragment(), BackPressable { override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) - iconsListState = icon_selector.layoutManager?.onSaveInstanceState() - subscriptionsListState = subscriptions_selector_list.layoutManager?.onSaveInstanceState() + iconsListState = feedGroupCreateBinding.iconSelector.layoutManager?.onSaveInstanceState() + subscriptionsListState = feedGroupCreateBinding.subscriptionsSelectorList.layoutManager?.onSaveInstanceState() Icepick.saveInstanceState(this, outState) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + _feedGroupCreateBinding = DialogFeedGroupCreateBinding.bind(view) + _searchLayoutBinding = feedGroupCreateBinding.subscriptionsHeaderSearchContainer viewModel = ViewModelProvider( this, @@ -146,7 +154,7 @@ class FeedGroupDialog : DialogFragment(), BackPressable { add(subscriptionEmptyFooter) spanCount = 4 } - subscriptions_selector_list.apply { + feedGroupCreateBinding.subscriptionsSelectorList.apply { // Disable animations, too distracting. itemAnimator = null adapter = subscriptionGroupAdapter @@ -172,8 +180,11 @@ class FeedGroupDialog : DialogFragment(), BackPressable { override fun onDestroyView() { super.onDestroyView() - subscriptions_selector_list?.adapter = null - icon_selector?.adapter = null + feedGroupCreateBinding.subscriptionsSelectorList.adapter = null + feedGroupCreateBinding.iconSelector.adapter = null + + _feedGroupCreateBinding = null + _searchLayoutBinding = null } /*/​////////////////////////////////////////////////////////////////////////// @@ -193,30 +204,30 @@ class FeedGroupDialog : DialogFragment(), BackPressable { } private fun setupListeners() { - delete_button.setOnClickListener { showScreen(DeleteScreen) } + feedGroupCreateBinding.deleteButton.setOnClickListener { showScreen(DeleteScreen) } - cancel_button.setOnClickListener { + feedGroupCreateBinding.cancelButton.setOnClickListener { when (currentScreen) { InitialScreen -> dismiss() else -> showScreen(InitialScreen) } } - group_name_input_container.error = null - group_name_input.doOnTextChanged { text, _, _, _ -> - if (group_name_input_container.isErrorEnabled && !text.isNullOrBlank()) { - group_name_input_container.error = null + feedGroupCreateBinding.groupNameInputContainer.error = null + feedGroupCreateBinding.groupNameInput.doOnTextChanged { text, _, _, _ -> + if (feedGroupCreateBinding.groupNameInputContainer.isErrorEnabled && !text.isNullOrBlank()) { + feedGroupCreateBinding.groupNameInputContainer.error = null } } - confirm_button.setOnClickListener { handlePositiveButton() } + feedGroupCreateBinding.confirmButton.setOnClickListener { handlePositiveButton() } - select_channel_button.setOnClickListener { - subscriptions_selector_list.scrollToPosition(0) + feedGroupCreateBinding.selectChannelButton.setOnClickListener { + feedGroupCreateBinding.subscriptionsSelectorList.scrollToPosition(0) showScreen(SubscriptionsPickerScreen) } - val headerMenu = subscriptions_header_toolbar.menu + val headerMenu = feedGroupCreateBinding.subscriptionsHeaderToolbar.menu requireActivity().menuInflater.inflate(R.menu.menu_feed_group_dialog, headerMenu) headerMenu.findItem(R.id.action_search).setOnMenuItemClickListener { @@ -234,8 +245,8 @@ class FeedGroupDialog : DialogFragment(), BackPressable { } } - toolbar_search_clear.setOnClickListener { - if (toolbar_search_edit_text.text.isEmpty()) { + searchLayoutBinding.toolbarSearchClear.setOnClickListener { + if (searchLayoutBinding.toolbarSearchEditText.text.isNullOrEmpty()) { hideSearch() return@setOnClickListener } @@ -243,14 +254,14 @@ class FeedGroupDialog : DialogFragment(), BackPressable { showKeyboardSearch() } - toolbar_search_edit_text.setOnClickListener { + searchLayoutBinding.toolbarSearchEditText.setOnClickListener { if (DeviceUtils.isTv(context)) { showKeyboardSearch() } } - toolbar_search_edit_text.doOnTextChanged { _, _, _, _ -> - val newQuery: String = toolbar_search_edit_text.text.toString() + searchLayoutBinding.toolbarSearchEditText.doOnTextChanged { _, _, _, _ -> + val newQuery: String = searchLayoutBinding.toolbarSearchEditText.text.toString() subscriptionsCurrentSearchQuery = newQuery viewModel.filterSubscriptionsBy(newQuery) } @@ -266,16 +277,16 @@ class FeedGroupDialog : DialogFragment(), BackPressable { } private fun handlePositiveButtonInitialScreen() { - val name = group_name_input.text.toString().trim() + val name = feedGroupCreateBinding.groupNameInput.text.toString().trim() val icon = selectedIcon ?: groupIcon ?: FeedGroupIcon.ALL if (name.isBlank()) { - group_name_input_container.error = getString(R.string.feed_group_dialog_empty_name) - group_name_input.text = null - group_name_input.requestFocus() + feedGroupCreateBinding.groupNameInputContainer.error = getString(R.string.feed_group_dialog_empty_name) + feedGroupCreateBinding.groupNameInput.text = null + feedGroupCreateBinding.groupNameInput.requestFocus() return } else { - group_name_input_container.error = null + feedGroupCreateBinding.groupNameInputContainer.error = null } if (selectedSubscriptions.isEmpty()) { @@ -296,10 +307,10 @@ class FeedGroupDialog : DialogFragment(), BackPressable { groupSortOrder = feedGroupEntity?.sortOrder ?: -1 val feedGroupIcon = if (selectedIcon == null) icon else selectedIcon!! - icon_preview.setImageResource(feedGroupIcon.getDrawableRes(requireContext())) + feedGroupCreateBinding.iconPreview.setImageResource(feedGroupIcon.getDrawableRes(requireContext())) - if (group_name_input.text.isNullOrBlank()) { - group_name_input.setText(name) + if (feedGroupCreateBinding.groupNameInput.text.isNullOrBlank()) { + feedGroupCreateBinding.groupNameInput.setText(name) } } @@ -346,10 +357,10 @@ class FeedGroupDialog : DialogFragment(), BackPressable { subscriptionMainSection.update(subscriptions, false) if (subscriptionsListState != null) { - subscriptions_selector_list.layoutManager?.onRestoreInstanceState(subscriptionsListState) + feedGroupCreateBinding.subscriptionsSelectorList.layoutManager?.onRestoreInstanceState(subscriptionsListState) subscriptionsListState = null } else { - subscriptions_selector_list.scrollToPosition(0) + feedGroupCreateBinding.subscriptionsSelectorList.scrollToPosition(0) } } @@ -357,17 +368,16 @@ class FeedGroupDialog : DialogFragment(), BackPressable { val selectedCount = this.selectedSubscriptions.size val selectedCountText = resources.getQuantityString( R.plurals.feed_group_dialog_selection_count, - selectedCount, selectedCount - ) - selected_subscription_count_view.text = selectedCountText - subscriptions_header_info.text = selectedCountText + selectedCount, selectedCount) + feedGroupCreateBinding.selectedSubscriptionCountView.text = selectedCountText + feedGroupCreateBinding.subscriptionsHeaderInfo.text = selectedCountText } private fun setupIconPicker() { val groupAdapter = GroupAdapter() groupAdapter.addAll(FeedGroupIcon.values().map { PickerIconItem(requireContext(), it) }) - icon_selector.apply { + feedGroupCreateBinding.iconSelector.apply { layoutManager = GridLayoutManager(requireContext(), 7, RecyclerView.VERTICAL, false) adapter = groupAdapter @@ -381,20 +391,20 @@ class FeedGroupDialog : DialogFragment(), BackPressable { when (item) { is PickerIconItem -> { selectedIcon = item.icon - icon_preview.setImageResource(item.iconRes) + feedGroupCreateBinding.iconPreview.setImageResource(item.iconRes) showScreen(InitialScreen) } } } - icon_preview.setOnClickListener { - icon_selector.scrollToPosition(0) + feedGroupCreateBinding.iconPreview.setOnClickListener { + feedGroupCreateBinding.iconSelector.scrollToPosition(0) showScreen(IconPickerScreen) } if (groupId == NO_GROUP_SELECTED) { val icon = selectedIcon ?: FeedGroupIcon.ALL - icon_preview.setImageResource(icon.getDrawableRes(requireContext())) + feedGroupCreateBinding.iconPreview.setImageResource(icon.getDrawableRes(requireContext())) } } @@ -405,22 +415,20 @@ class FeedGroupDialog : DialogFragment(), BackPressable { private fun showScreen(screen: ScreenState) { currentScreen = screen - options_root.onlyVisibleIn(InitialScreen) - icon_selector.onlyVisibleIn(IconPickerScreen) - subscriptions_selector.onlyVisibleIn(SubscriptionsPickerScreen) - delete_screen_message.onlyVisibleIn(DeleteScreen) + feedGroupCreateBinding.optionsRoot.onlyVisibleIn(InitialScreen) + feedGroupCreateBinding.iconSelector.onlyVisibleIn(IconPickerScreen) + feedGroupCreateBinding.subscriptionsSelector.onlyVisibleIn(SubscriptionsPickerScreen) + feedGroupCreateBinding.deleteScreenMessage.onlyVisibleIn(DeleteScreen) - separator.onlyVisibleIn(SubscriptionsPickerScreen, IconPickerScreen) - cancel_button.onlyVisibleIn(InitialScreen, DeleteScreen) + feedGroupCreateBinding.separator.onlyVisibleIn(SubscriptionsPickerScreen, IconPickerScreen) + feedGroupCreateBinding.cancelButton.onlyVisibleIn(InitialScreen, DeleteScreen) - confirm_button.setText( - when { - currentScreen == InitialScreen && groupId == NO_GROUP_SELECTED -> R.string.create - else -> android.R.string.ok - } - ) + feedGroupCreateBinding.confirmButton.setText(when { + currentScreen == InitialScreen && groupId == NO_GROUP_SELECTED -> R.string.create + else -> android.R.string.ok + }) - delete_button.isGone = currentScreen != InitialScreen || groupId == NO_GROUP_SELECTED + feedGroupCreateBinding.deleteButton.isGone = currentScreen != InitialScreen || groupId == NO_GROUP_SELECTED hideKeyboard() hideSearch() @@ -434,26 +442,26 @@ class FeedGroupDialog : DialogFragment(), BackPressable { // Utils //​//////////////////////////////////////////////////////////////////////// */ - private fun isSearchVisible() = subscriptions_header_search_container?.visibility == View.VISIBLE + private fun isSearchVisible() = _searchLayoutBinding?.root?.visibility == View.VISIBLE private fun resetSearch() { - toolbar_search_edit_text.setText("") + searchLayoutBinding.toolbarSearchEditText.setText("") subscriptionsCurrentSearchQuery = "" viewModel.clearSubscriptionsFilter() } private fun hideSearch() { resetSearch() - subscriptions_header_search_container.visibility = View.GONE - subscriptions_header_info_container.visibility = View.VISIBLE - subscriptions_header_toolbar.menu.findItem(R.id.action_search).isVisible = true + searchLayoutBinding.root.visibility = View.GONE + feedGroupCreateBinding.subscriptionsHeaderInfoContainer.visibility = View.VISIBLE + feedGroupCreateBinding.subscriptionsHeaderToolbar.menu.findItem(R.id.action_search).isVisible = true hideKeyboardSearch() } private fun showSearch() { - subscriptions_header_search_container.visibility = View.VISIBLE - subscriptions_header_info_container.visibility = View.GONE - subscriptions_header_toolbar.menu.findItem(R.id.action_search).isVisible = false + searchLayoutBinding.root.visibility = View.VISIBLE + feedGroupCreateBinding.subscriptionsHeaderInfoContainer.visibility = View.GONE + feedGroupCreateBinding.subscriptionsHeaderToolbar.menu.findItem(R.id.action_search).isVisible = false showKeyboardSearch() } @@ -462,37 +470,35 @@ class FeedGroupDialog : DialogFragment(), BackPressable { } private fun showKeyboardSearch() { - if (toolbar_search_edit_text.requestFocus()) { - inputMethodManager.showSoftInput(toolbar_search_edit_text, InputMethodManager.SHOW_IMPLICIT) + if (searchLayoutBinding.toolbarSearchEditText.requestFocus()) { + inputMethodManager.showSoftInput(searchLayoutBinding.toolbarSearchEditText, + InputMethodManager.SHOW_IMPLICIT) } } private fun hideKeyboardSearch() { - inputMethodManager.hideSoftInputFromWindow( - toolbar_search_edit_text.windowToken, - InputMethodManager.RESULT_UNCHANGED_SHOWN - ) - toolbar_search_edit_text.clearFocus() + inputMethodManager.hideSoftInputFromWindow(searchLayoutBinding.toolbarSearchEditText.windowToken, + InputMethodManager.RESULT_UNCHANGED_SHOWN) + searchLayoutBinding.toolbarSearchEditText.clearFocus() } private fun showKeyboard() { - if (group_name_input.requestFocus()) { - inputMethodManager.showSoftInput(group_name_input, InputMethodManager.SHOW_IMPLICIT) + if (feedGroupCreateBinding.groupNameInput.requestFocus()) { + inputMethodManager.showSoftInput(feedGroupCreateBinding.groupNameInput, + InputMethodManager.SHOW_IMPLICIT) } } private fun hideKeyboard() { - inputMethodManager.hideSoftInputFromWindow( - group_name_input.windowToken, - InputMethodManager.RESULT_UNCHANGED_SHOWN - ) - group_name_input.clearFocus() + inputMethodManager.hideSoftInputFromWindow(feedGroupCreateBinding.groupNameInput.windowToken, + InputMethodManager.RESULT_UNCHANGED_SHOWN) + feedGroupCreateBinding.groupNameInput.clearFocus() } private fun disableInput() { - delete_button?.isEnabled = false - confirm_button?.isEnabled = false - cancel_button?.isEnabled = false + _feedGroupCreateBinding?.deleteButton?.isEnabled = false + _feedGroupCreateBinding?.confirmButton?.isEnabled = false + _feedGroupCreateBinding?.cancelButton?.isEnabled = false isCancelable = false hideKeyboard() From f04b5fd42f493df0dc6b35c8c45b3b498f4ef9f5 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Tue, 3 Nov 2020 14:17:24 +0530 Subject: [PATCH 11/11] Use view binding in FeedGroupReorderDialog. --- .../dialog/FeedGroupReorderDialog.kt | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupReorderDialog.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupReorderDialog.kt index 380bf13f5..3b74ddc74 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupReorderDialog.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupReorderDialog.kt @@ -16,10 +16,9 @@ import com.xwray.groupie.TouchCallback import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder import icepick.Icepick import icepick.State -import kotlinx.android.synthetic.main.dialog_feed_group_reorder.confirm_button -import kotlinx.android.synthetic.main.dialog_feed_group_reorder.feed_groups_list import org.schabi.newpipe.R import org.schabi.newpipe.database.feed.model.FeedGroupEntity +import org.schabi.newpipe.databinding.DialogFeedGroupReorderBinding import org.schabi.newpipe.local.subscription.dialog.FeedGroupReorderDialogViewModel.DialogEvent.ProcessingEvent import org.schabi.newpipe.local.subscription.dialog.FeedGroupReorderDialogViewModel.DialogEvent.SuccessEvent import org.schabi.newpipe.local.subscription.item.FeedGroupReorderItem @@ -27,6 +26,9 @@ import org.schabi.newpipe.util.ThemeHelper import java.util.Collections class FeedGroupReorderDialog : DialogFragment() { + private var _binding: DialogFeedGroupReorderBinding? = null + private val binding get() = _binding!! + private lateinit var viewModel: FeedGroupReorderDialogViewModel @State @@ -48,6 +50,7 @@ class FeedGroupReorderDialog : DialogFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + _binding = DialogFeedGroupReorderBinding.bind(view) viewModel = ViewModelProvider(this).get(FeedGroupReorderDialogViewModel::class.java) viewModel.groupsLiveData.observe(viewLifecycleOwner, Observer(::handleGroups)) @@ -61,15 +64,20 @@ class FeedGroupReorderDialog : DialogFragment() { } ) - feed_groups_list.layoutManager = LinearLayoutManager(requireContext()) - feed_groups_list.adapter = groupAdapter - itemTouchHelper.attachToRecyclerView(feed_groups_list) + binding.feedGroupsList.layoutManager = LinearLayoutManager(requireContext()) + binding.feedGroupsList.adapter = groupAdapter + itemTouchHelper.attachToRecyclerView(binding.feedGroupsList) - confirm_button.setOnClickListener { + binding.confirmButton.setOnClickListener { viewModel.updateOrder(groupOrderedIdList) } } + override fun onDestroyView() { + _binding = null + super.onDestroyView() + } + override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) Icepick.saveInstanceState(this, outState) @@ -89,7 +97,7 @@ class FeedGroupReorderDialog : DialogFragment() { } private fun disableInput() { - confirm_button?.isEnabled = false + _binding?.confirmButton?.isEnabled = false isCancelable = false }